MSDNは、WPFアプリケーションをローカライズするいくつかの方法を提供します。たとえば、XMLファイル、リソースファイル(.resx)、またはXAMLを使用します。 例として、そこで検討されたのはまさに後者のオプションであり、その利点は描かれていましたが、次のような多くの欠点もあります。
1)実際のUI(マークアップ要素)とコードからのメッセージ(MessageBox、ステータス変更など)をローカライズするためのさまざまなソース。
2)プロジェクトの編集、コンソールから行テーブルのアンロード、サテライトアセンブリへのロードの過度のダンス。
3)各UI要素のUidの慎重な制御。
MergedDictionariesなどを使用した独自のアプローチもあります。
それらのそれぞれは、何らかの理由で私にはあまり合いませんでした-過度の体の動き(csprojファイルの手動編集、開発マシンのロケールでのシャーマニズムなど)、さまざまな追加ユーティリティ、余分なコード(ロケールに応じて辞書をマージする)を引き付けるのは簡単です、しかし、審美的ではありません。 しかし、resxファイルでは、すべてが可能な限りうまくいきました。さらに、これにより、アプリケーションを変換する(WinFormsで)使い慣れたワークフローが残りました。
Visual Studioの機能を使用してWPFアプリケーションをローカライズする方法をさらに詳しく見てみましょう。 1つのウィンドウ-ログインでテストプロジェクトWpfAppLocalizedを作成します。
まず、ローカライズが必要な要素-ログイン、パスワードラベル、ログイン、キャンセルボタン、不正なログイン/パスワードに関するメッセージ、ログイン成功に関するメッセージを決定します。
そのため、自動的に作成されたリソースファイルWpfAppLocalized / Properties / Resources.resxを開き(または新しいリソースファイルを作成します)、必要な値を文字列リソースに入力します。
コードでは、いくつかの方法でリソースにアクセスできますが、Studioはプロキシクラスを便利に作成します。値にアクセスするには、自動生成されたクラスWpfAppLocalization.Properties.Resourcesの静的プロパティを使用できます-この点は非常に重要です。 それまでの間、最も簡単なことから始めましょう-メッセージの表示。 ログインをクリックするための簡単なハンドラーを作成します。
if (Login.Text.Equals( "admin" ) && Password.Password.Equals( "admin" ))
{
MessageBox.Show(Properties.Resources.LoginSuccessfullMessage);
}
else
{
ErrorMessage.Text = Properties.Resources.LoginFailedMessage;
}
* This source code was highlighted with Source Code Highlighter .
すべてがシンプルで明確です。 しかし今、最も興味深いのは、XAMLマークアップのローカライズです。 もちろん、額で行動することができます-各要素に名前を割り当て、コンポーネントの初期化時にリソースから必要なプロパティに値を割り当てます-これはジェダイのやり方ではありません。 前述したように、Studioは各行リソースにアクセスするための静的プロパティのセットを持つリソースファイルのクラスを生成します...そしてすぐに思い浮かぶのは、「もちろん、x:Static!」です。 Markup-Extension x:Staticは、静的プロパティを介してXAML要素のプロパティ値を初期化するために使用されます。 しかし、最初に、名前空間を宣言する必要があります。名前空間を通じて、マークアップで静的クラスを参照します。
< Window x:Class ="WpfAppLocalized.MainWindow"
xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:res ="clr-namespace:WpfAppLocalized.Properties"
Title ="Login" Height ="150" Width ="270" MaxWidth ="270" MinWidth ="270" MaxHeight ="150" MinHeight ="150" >
* This source code was highlighted with Source Code Highlighter .
私たちにとって最も重要な行は、「xmlns:res =“ clr-namespace:WpfAppLocalized.Properties”」です。 これは、コード内の名前空間へのXML名前空間resの実際のバインディングです。 これで、静的を介してコントロールのプロパティの値を入力できます。ログインラベルの場合は次のようになります。
< TextBlock HorizontalAlignment ="Right" VerticalAlignment ="Center" Grid . Column ="0" Text ="{x:Static res:Resources.LoginLabel}" />
* This source code was highlighted with Source Code Highlighter .
お気づきのように、Textプロパティは拡張機能Staticを介して初期化されました。 Resourcesクラスの静的プロパティLoginLabelの値が取得されます。 ただし、Visual Studioでこれを行おうとすると、エディターは「Type 'res:Resources'には 'LoginLabel'という名前の静的メンバーが含まれていません」と表示し、起動時に例外 'WpfAppLocalized.Properties.Resources.LoginLabel' StaticExtension値がスローされます列挙、静的フィールド、または静的プロパティに解決できません。 その理由は非常に単純です-デフォルトでは、リソースのプロキシクラスは内部修飾子で生成されます-つまり これらのリソースは、XAMLローダーでは使用できません。 修飾子をpublicに変更するだけです-その後、アプリケーションは動作します。
そのため、この段階では、すべてのインターフェイス要素とすべてのメッセージはリソースからのテキストのみを使用します。実際は、さまざまな言語のサポートを追加するときです。 これは非常に簡単です-ソースリソースファイルResources.resxを新しいリソース{Cl-LN} .resxにコピーするだけです。ここで、clはカルチャ(国)、LNは言語です。 たとえば、ロシアのロシア語の場合、リソースファイルはResources.ru-RU.resxという名前になります。 たとえば、カナダでは、Resources.ca-EN.resxとResources.ca-FR.resxの2つのファイルを作成できます-英語とフランス語用です。 言語に分割する必要がない場合は、省略することができ、Resources.ru.resxがロシアの国に使用されます。 そのため、新しいリソースファイルを開きます-そして、メインのファイルと同じように入力されるようになりました-しかし、英語の碑文をネイティブのロシア語に安全に翻訳できるようになりました-そして、プロジェクト内の不要なファイルを避けるために、アクセス修飾子を設定しますはい、そのような奇妙な修飾子)。
素晴らしい、翻訳が完了しました。 さて、質問する時が来ました-そして、文化に応じてリソースの選択のロジックをどこでコーディングする必要がありますか? 答えは、どこにも必要ありません。 アプリケーションのビルドが正常に完了すると、EXEを持つフォルダーに別のフォルダーが表示されます-ru、WpfAppLocalized.resources.dllファイルが含まれています。 これらはローカライズされたリソースです。 .NET Frameworkアプリケーションの起動時に、オペレーティングシステムの文化と言語に応じて、特定のサテライトアセンブリが読み込まれるため、特定のリソースが使用されます。 これは、アプリケーションのローカライズバージョンの外観です。
それだけです、ご清聴ありがとうございました。
PS記事を読み直しているときに、どのような質問が発生する可能性があるかを考え、すぐに回答することにしました。
Q:アプリケーション言語を強制的に変更する方法(たとえば、ユーザーに選択肢を与える)
A:システムは、System.Threading.Thread.CurrentThread.CurrentUICultureの値を使用して、どのカルチャリソースを読み込むかを決定します。 したがって、アプリケーション言語をロシア語に変更するには、InitializeComponentの前にWpfAppLocalizationコンストラクターで次を追加する必要があります。
System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo( "en-US");
Q:異なるアプリケーションで同じリソースアセンブリを使用できますか?
A:はい、可能です-名前空間接続のみが少し変更されます-アセンブリ名もそこに追加されます-xmlns:res = "clr-namespace:WpfAppLocalized.Properties、assembly = GlobalRes.dll"
Q:サテライトアセンブリがない言語でアプリケーションを起動した場合はどうなりますか?
A:メインアセンブリのリソースが使用されます。
UPD: WpfAppLocalizedプロジェクトを投稿しました。