ResourceDictionaryでxamlの画面を多言語対応(ローカライズ)する

もくじ
https://tera1707.com/entry/2022/02/06/144447

やりたいこと

以前の記事で、WPFでPropertiesを使ってローカライズする方法を調べた。

今回、ResourceDictinaryを使ってローカライズする方法を知ったのでメモしておく。

やりかた

言語ごとのResourceDictionaryを作る

まず、言語ごとのリソースファイルを作る。

今回は下図のように、Resourcesフォルダを作り、その下にStringResource.**.xamlを作った。
(「**」の部分に、言語コード(jaenなど)が入る)

試しに作ったリソースディクショナリは下記のような内容。

StringResource.en.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:sys="clr-namespace:System;assembly=mscorlib">
    <sys:String x:Key="TestString1">aiueo</sys:String>
    <sys:String x:Key="TestString2">kakikukeko</sys:String>
</ResourceDictionary>

StringResource.ja.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:sys="clr-namespace:System;assembly=mscorlib">
    <sys:String x:Key="TestString1">あいうえお</sys:String>
    <sys:String x:Key="TestString2">かきくけこ</sys:String>
</ResourceDictionary>

ResourceDictionaryを切り替える処理を書く

次に、そのリソースを使って言語ごとに文言を使い分けたいウインドウのコードビハインドに、下記のようなコードを書く。
InitializeComponent();の前の、言語ごとのリソースディクショナリを読み込む部分がキモになる部分。

using System;
using System.Globalization;
using System.Windows;

namespace CultureTest
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            // 言語ごとのリソースディクショナリを読み込む
            // InitializeComponent()の前にやること。
            var cultureCode = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;// "ja"や"en"などが入る ※「CultureInfo.CurrentUICulture.Name」だと"ja-JP"等になる
            var dictionary = new ResourceDictionary();
            dictionary.Source = new Uri(@"Resources/StringResource." + cultureCode + @".xaml", UriKind.Relative);
            this.Resources.MergedDictionaries.Add(dictionary);

            InitializeComponent();
        }
    }
}

これで、使うリソースディクショナリを切り替える。

画面にリソースを使う部分を書く

画面に、リソースを使う部分を書く。

今回は簡易的に、TextBlockに、作った文言を言語ごとに切り替えて出してみる。

<Window x:Class="CultureTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:CultureTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">    
    <Grid>
        <TextBlock Text="{StaticResource TestString1}"/>
    </Grid>
</Window>

結果

Windowsの設定で、英語を選択しているとき

日本語を選択しているとき

難点

コードビハインドに、リソースディクショナリを切り替えるコードを書かないといけない。

ウインドウのリソースディクショナリを下記のようにxamlに書くときに、

    <Window.Resources>
        <ResourceDictionary Source="Resources/StringResource.en.xaml"/>
    </Window.Resources>

なにかうまいこと、コンバーター等を使って「en」のところを今の言語ごとに切り替えてやればうまくいくのかもしれないが、未検証。

ただ、そこまでWPFでやるなら、以前調べた方のやり方でよいのかもしれない...

参考

このページの「3. リソースディクショナリを使う方法」をほぼそのまんま試させていただいた。
ありがとうございます。

https://nishy-software.com/ja/dev-sw/wpf-app-localize-strings/