もくじ
→https://qiita.com/tera1707/items/4fda73d86eded283ec4f
やりたいこと
WPF(画面はxaml)のアプリで、OSの言語設定を切り替えると、その設定に合った言語でUIの文言を表示できるようにしたい。( = 多言語対応したい)
前提
.NET Framework 4.7.2
を使用。
やり方
Properties.Resources.resx
を使う。
この場合だと、下記のようになる。
リソースファイル名 | OS言語設定 |
---|---|
Resources.fi.resx | フィンランド語 |
Resources.ja.resx | 日本語 |
Resources.resx | 英語 |
今回は、デフォルトの言語 = 英語、としてやってみる。
※デフォルト言語のリソースが、ロケールがファイル名についてないResources.resx
になるということ。
手順
Propertiesの準備
.NET Frameworkでプロジェクトを作成する。
作成したら、プロジェクトの下のProperties
を開く。
言語別で表示分けしたい文言をここに設定する。(標準の言語は今回英語にするので、英語で入力。)
まず呼び出すときの名前を付けて、その値も入力する。
※一つ追加したら、その下に空欄が追加されるので、複数登録したかったら下に追加していけばいい。
アクセス修飾子の設定をpublic
にする。
これをしておくと、xamlのコードからここの名前を使って呼び出せるようになる。
※publicにしてないと、xaml編集中は問題ないが、実行時のInitializeComponent()
で下記エラーになる。
System.Windows.Markup.XamlParseException: '''System.Windows.Markup.StaticExtension' の値の指定時に例外がスローされました。' 行番号 '12'、行位置 '10'。'
ArgumentException: 'WpfApp52.Properties.Resources.MyString1' StaticExtension 値は、列挙値、静的フィールド、または静的プロパティに解決できません。
xaml画面の準備
xaml画面に、下記2点追加する。
- Propertiesへのネームスペースの定義を追加する。
書き方は、xmlns:properties="clr-namespace:プロジェクト名
.Properties" - 言語別に表示したい文字列のためのTextBlockを追加する。
書き方は、{x:Static追加したネームスペース
:Resources.追加したリソースの名前
}
<Window x:Class="WpfApp52.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:properties="clr-namespace:WpfApp52.Properties" ★ネームスペース追加(「WpfApp52」はプロジェクト名)
xmlns:local="clr-namespace:WpfApp52"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<!-- ★言語別に表示したい文字列のためのTextBlockを追加する -->
<TextBlock Text="{x:Static properties:Resources.MyString1}" />
</Grid>
</Window>
ここまでで、デフォルトの言語の表示はできた。
これだけだとデフォルトの英語だけになるので、ほかの言語のリソースを追加する。
他の言語用のResources.resxの追加
まずは、日本語のリソースを追加する。
Propertiesを右クリック > [追加] > [新しい項目] を選択する。
[リソースファイル]を追加する。名前は、Resources.ja.resx
にしておく。
デフォルト言語のリソースと同じように、下記を行う。
- リソースの名前とその値を追加
-
アクセス修飾子
をpublicにする
これで、日本語用リソースの追加完了。
今WindowsのOS言語設定を日本語にしているので、画面エディタ上で文言が日本語リソースのものになった。
手順は以上。
Resource.〇〇.resxの〇〇の名付け方
例えば、言語設定の画面の設定が、
-
英語(米国)
だったら、en
をつければいいのでResource.en.resx
-
スペイン語 (アルゼンチン)
だったら、es-ar
をつければいいのでResource.es-ar.resx
とする。
ちなみに、es-ar
のように、ハイフンで2つをつなげているものは、〇〇-△△
の〇〇
が言語コード、△△
が地域コードらしい。
だから、ja-jp
だと、日本語-日本、es-ar
だったら、そのままだが、スペイン語-アルゼンチン、を表している。
現在の言語と地域のコードをC#でとってくる
下記のようなコードで、現在のロケール設定を取ってこれる。
→https://docs.microsoft.com/ja-jp/dotnet/api/system.globalization.cultureinfo.currentculture?view=netcore-3.1
// ja
string code1 = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
// ja-JP
string code2 = CultureInfo.CurrentUICulture.Name;
// 細かいこと調べられてないので、参考程度に。
ニュートラル言語設定とresxの関係
プロジェクトのプロパティの中にある「ニュートラル言語」の設定を例えば日本語にしていると、「Resources.ja.resx」があったとしても「Resources.resx」の方が日本語として扱われる。
ニュートラル言語に設定している言語のリソースとして「Resources.resx」が使われる様子。
なので、ニュートラル言語を設定するのであれば、その言語に対応するリソースを「Resources.resx」に書かないといけない。
また、ニュートラル言語を「なし」にしていると、今現在のWindowsの表示言語設定に対応する「Resources.〇〇.resx」があればその中の情報を使い、対応するのがなければ「Resources.resx」が使われる様子。(やってみた限りそう見えた)
注意と今後やること
この方法は、上記手順だけではアプリ起動後、動的に言語切り替えはできないもののお手軽ではあるが、xaml上でエラーになり、画面エディタが使えなくなる場合がある。
今回の実験だとそういうことは起きなかったが、実際仕事のアプリではそういうエラーになっていた。そうなるとき、ならないときの違いはよくわからない。
wpfとしては、「リソースディクショナリ」を使って多言語対応することを推奨しているようで、そっちのやり方ならそういうことが起きないっぽい。(未検証)
下の「参考」に挙げた「WPFアプリの文字列のローカライズ(多言語化)」
のページにその方法が書かれていたので、次回試したい。
追記
.NET CoreのWPFプロジェクトだと、そもそもProperties
の項目がない。
(下記は.NET core 3.0)
今後はPropertiesを使った言語切り替えはしてくれるな、ということか?
そういう意味でも正しい言語切り替えのやり方を調べたい。
追記2
追加でいろいろ手順をやると、動的にも言語切り替えできるらしい。こちら参照。
気づいたこと
OSの言語設定が、追加したリソースの中にない言語だったとき
デフォルトのリソールResources.resx
は、現在のOSの言語設定が、用意したリソース(今回だったら日本語)の中にないものだった場合に表示する、という動きをするみたい。
なので、上の状態でOSの言語設定を「フランス語」にすると、デフォルトのリソースが使われて英語表示になる。
追加したリソースの実体の見方
ビルドすると、上記のように、追加で作成したリソースのdll(ここではjp
フォルダの中のWpfApp51.resources.dll
)が作成される。
※別プロジェクト作って実験したのでPJ名が上の方と変わっている。
※試しにフィンランド語のResources.fi.resx
も追加したのでfi
フォルダも追加されている。
OSの言語設定を切り替えたときには、各言語のフォルダの中の<PJ名>.resources.dll
がリソースとして使われて、言語の切り替えが行われる。
標準の言語のリソースはどこに行ったかというと、exe(今回だとWpfApp51.exe
)の中に含まれているらしい。(だから、「標準」として使われて、追加のリソースがない時はそれが使われる)
参考
ロケールの動的変更の仕方
http://grabacr.net/archives/1647
WPFアプリの文字列のローカライズ(多言語化)
ローカライズのやり方の種類をいくつか挙げているページ。
→今回のやり方は、このページの「4.Resources.resxを使う方法」にあたる。
https://nishy-software.com/ja/dev-sw/wpf-app-localize-strings/
CultureInfoや CultureInfo.CurrentCultureのMS docs説明
https://docs.microsoft.com/ja-jp/dotnet/api/system.globalization.cultureinfo.currentculture?view=netcore-3.1
MSのロケールIDの一覧
https://docs.microsoft.com/ja-jp/previous-versions/windows/scripting/cc392381(v=msdn.10)?redirectedfrom=MSDN
jaとja-jpの違い
http://hensa40.cutegirl.jp/archives/3190
ja=ニュートラルカルチャ、ja-jp=特定のカルチャ、優先順位は?
https://www.atmarkit.co.jp/fdotnet/dotnettips/314winmultilang/winmultilang.html