UI とアプリ パッケージ マニフェストの文字列をローカライズする

Windows アプリ SDK アプリをローカライズすることの価値提案について詳しくは、「グローバリゼーションとローカライゼーション」をご覧ください。

アプリで複数の表示言語をサポートする必要があり、コード、XAML マークアップ、アプリ パッケージ マニフェスト内に文字列リテラルが含まれている場合は、その文字列をリソース ファイル (.resw) に移動します。 アプリでサポートする各言語用に、このリソース ファイルを翻訳したコピーを作成することができます。

ハードコーディングされた文字列リテラルは、命令型コードまたは XAML マークアップ (TextBlockText プロパティなど) で表示できます。 また、アプリ パッケージ マニフェスト ソース ファイル (Package.appxmanifest ファイル) に、たとえば Visual Studio マニフェスト デザイナーの [アプリケーション] タブの [表示名] の値として表示することもできます。 これらの文字列をリソース ファイル (.resw) に移動し、アプリとマニフェスト内のハードコーディングされた文字列リテラルをリソース識別子への参照に置き換えます。

1 つのイメージ リソース ファイルに 1 つのイメージ リソースのみが含まれるイメージ リソースとは異なり、複数の文字列リソースが文字列リソース ファイルに含まれています。 文字列リソース ファイルはリソース ファイル (.resw) であり、通常、この種のリソース ファイルはプロジェクトの \Strings フォルダーに作成します。 リソース ファイル (.resw) の名前で修飾子を使用する方法の背景については、「言語、スケール、その他の修飾子に合わせてリソースを調整する」を参照してください。

リソース ファイルに文字列を格納する

  1. アプリのデフォルト言語を設定します。

    1. Visual Studio でソリューションを開いた状態で、Package.appxmanifest を開きます。
    2. [アプリケーション] タブで、[既定の言語] が適切に設定されていることを確認します (たとえば、"en" や "en-US")。 残りの手順では、既定の言語を "en-US" に設定していることを前提としています。

    Note

    少なくとも、この既定の言語にローカライズされた文字列リソースを提供する必要があります。 これらは、ユーザーの優先言語または表示言語設定に一致するものが見つからない場合に読み込まれるリソースです。

  2. 既定の言語のリソース ファイル (.resw) を作成します。

    1. プロジェクト ノードで、新しいフォルダーを作成し、Stringsという名前を付けます。
    2. Stringsの下に新しいサブフォルダーを作成し、en-USの名前を付けます。
    3. en-US の下で、新しいリソース ファイル (.resw) ([新しい項目の追加] ダイアログの [WinUI ファイルの種類] の下) を作成し、名前が Resources.resw であることを確認します。

    Note

    移植する .NET リソース ファイル (.resx) がある場合は、「XAML と UI の移植」を参照してください。

  3. Resources.resw を開き、これらの文字列リソースを追加します。

    Strings/en-US/Resources.resw

    Screenshot of the Add Resource table of the Strings > E N U S > Resources.resw file.

    この例では、"Greeting" は、マークアップから参照できる文字列リソース識別子です。 識別子 "Greeting" の場合、Text プロパティには文字列が提供され、Width プロパティには文字列が提供されます。 "Greeting.Text" は、UI 要素のプロパティに対応するため、プロパティ識別子の例です。 たとえば、[名前] 列に "Greeting.Foreground" を追加し、その [値] を "Red" に設定することもできます。 "Farewell" 識別子は、単純な文字列リソース識別子です。サブプロパティはなく、後で示すように、命令型コードから読み込むことができます。 コメント欄は、翻訳者に特別な指示を与えるのに適した場所です。

    この例では、"Farewell" という名前の単純な文字列リソース識別子エントリがあるため、同じ識別子に基づくプロパティ識別子持つことはできません。 そのため、"Farewell.Text" を追加すると、Resources.resw のビルド時に重複エントリ エラーが発生します。

    リソース識別子では大文字と小文字が区別されず、リソース ファイルごとに一意である必要があります。 意味のあるリソース識別子を使用して、翻訳者に追加のコンテキストを提供してください。 また、文字列リソースが翻訳のために送信された後は、リソース識別子を変更しないでください。 ローカリゼーション チームは、リソース識別子を使用して、リソースの追加、削除、更新を追跡します。 リソース識別子の変更 ("リソース識別子のシフト" とも呼ばれる) を行うと、文字列が削除されて他の文字列が追加されたような表示状態になります。このため、リソース識別子を変更した場合は、文字列を翻訳し直す必要があります。

XAML から文字列リソース識別子を参照する

x:Uid ディレクティブを使用して、マークアップ内のコントロールまたはその他の要素を文字列リソース識別子に関連付けます。

<TextBlock x:Uid="Greeting"/>

実行時に、\Strings\en-US\Resources.resw が読み込まれます (現時点では、プロジェクト内のリソース ファイルのみが A ファイルであるため)。 TextBlockx:Uid ディレクティブにより、文字列リソース識別子 "Greeting" を含む Resources.resw 内のプロパティ識別子を検索するための検索が行われます。 "Greeting.Text" プロパティ識別子と "Greeting.Width" プロパティ識別子が見つかり、その値が TextBlock に適用され、マークアップでローカルに設定された値がオーバーライドされます。 "Greeting.Foreground" 値を追加すると、それも適用されます。 ただし、XAML マークアップ要素のプロパティの設定に使用されるのはプロパティ識別子のみであるため、この TextBlock で x:Uid を "Farewell" に設定しても効果はありません。 Resources.resw には文字列リソース識別子 "Farewell" が含まれて "います" が、それに対するプロパティ識別子は含まれません。

文字列リソース識別子を XAML 要素に割り当てる場合は、その識別子のすべてのプロパティ識別子が XAML 要素に適していることを確認してください。 たとえば、TextBlockx:Uid="Greeting" を設定した場合、TextBlock 型には Text プロパティがあるため、"Greeting.Text" は解決されます。 ただし、Buttonx:Uid="Greeting" を設定した場合、Button 型には Text プロパティがないため、"Greeting.Text" は実行時エラーを引き起こします。 この場合の解決策の 1 つは、"ButtonGreeting.Content" という名前のプロパティ識別子を作成し、Buttonx:Uid="ButtonGreeting" を設定することです。

リソース ファイルから Width を設定する代わりに、コントロールのサイズをコンテンツに合わせて動的に調整できるようにすることをお勧めします。

Note

添付プロパティの場合は、.resw ファイルの [名前] 列に特別な構文が必要です。 たとえば、"Greeting" 識別子の AutomationProperties.Name 添付プロパティの値を設定するには、次のように [名前] 列に入力します。

Greeting.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name

コードから文字列リソース識別子を参照する

単純な文字列リソース識別子に基づいて、文字列リソースを明示的に読み込むことができます。

var resourceLoader = new Microsoft.Windows.ApplicationModel.Resources.ResourceLoader();
this.myXAMLTextBlockElement.Text = resourceLoader.GetString("Farewell");

この同じコードをクラス ライブラリ プロジェクト内から使用できます。 実行時に、ライブラリをホストしているアプリのリソースが読み込まれます。 ライブラリは、アプリのローカライズの度合いが高い可能性が高いため、ライブラリをホストするアプリからリソースを読み込むことをお勧めします。 ライブラリがリソースを提供する必要がある場合は、それらのリソースを入力として置き換えるオプションをホスティング アプリに提供する必要があります。

リソース名がセグメントに分かれている ("." 文字が含まれる) 場合は、リソース名のドットをスラッシュ ("/") 文字に置き換えます。 たとえば、プロパティ識別子にはドットが含まれています。したがって、コードからそれらの1つをロードするには、この置換を行う必要があります。

this.myXAMLTextBlockElement.Text = resourceLoader.GetString("Fare/Well"); // <data name="Fare.Well" ...> ...

わからない場合は、MakePri.exe を使用してアプリの PRI ファイルをダンプできます。 各リソースの uri が、ダンプされたファイルで示されています。

<ResourceMapSubtree name="Fare"><NamedResource name="Well" uri="ms-resource://<GUID>/Resources/Fare/Well">...

アプリ パッケージ マニフェストの文字列リソース識別子を参照する

  1. アプリ パッケージ マニフェスト ソース ファイル (Package.appxmanifest ファイル) を開きます。既定では、アプリの Display name は文字列リテラルで表されます。

    Screenshot of the Package.appxmanifest file showing the Application tab with the Display name set to Adventure Works Cycles.

  2. この文字列のローカライズ可能なバージョンを作成するには、Resources.resw を開き、名前が "AppDisplayName" で値が "Adventure Works Cycles" の新しい文字列リソースを追加します。

  3. 表示名の文字列リテラルを、先ほど作成した文字列リソース識別子 ("AppDisplayName") への参照に置き換えます。 これを行うには、ms-resourceURI (Uniform Resource Identifier) スキームを使用します。

    Screenshot of the Package.appxmanifest file showing the Application tab with the Display name set to M S resource App Display Name.

  4. ローカライズするマニフェスト内の文字列ごとに、このプロセスを繰り返します。 たとえば、アプリの短い名前 (スタート画面のアプリのタイルに表示されるように構成できます)。 ローカライズできるアプリ パッケージ マニフェスト内のすべての項目の一覧については、「ローカライズ可能なマニフェスト項目」を参照してください。

文字列リソースをローカライズする

  1. 別の言語のリソース ファイル (.resw) のコピーを作成します。

    1. [Strings] の下に新しいサブフォルダを作成し、Deutsch (Deutschland) の "de-DE" という名前を付けます。

    Note

    フォルダー名には、任意の BCP-47 言語タグを使用できます。 言語修飾子の詳細と共通言語タグの一覧については、「言語、スケール、およびその他の修飾子用にリソースを調整する」を参照してください。 2. Strings/en-US/Resources.resw フォルダに Strings/de-DE のコピーを作成します。

  2. 文字列を翻訳します。

    1. Strings/de-DE/Resources.resw を開き、[値] 列の値を変換します。 コメントを翻訳する必要はありません。

    Strings/de-DE/Resources.resw

    add resource, german

必要に応じて、手順 1 と 2 を繰り返して、さらに言語を作成できます。

Strings/fr-FR/Resources.resw

add resource, french

アプリをテストする

アプリの既定の表示言語をテストします。 その後、設定 >時刻と言語>地域と言語>言語 で表示言語を変更し、アプリを再テストできます。 UI やシェルの文字列 (タイトル バー (表示名) やタイルの短い名前など) を確認します。

Note

表示言語設定に一致するフォルダ名が見つかった場合は、そのフォルダ内のリソースファイルがロードされます。 それ以外の場合、フォールバックが行われ、アプリの既定の言語のリソースで終わります。

文字列を複数のリソースファイルに分解する

すべての文字列を 1 つのリソース ファイル (resw) に保持することも、複数のリソース ファイルにまたがってファクタリングすることもできます。 たとえば、エラー メッセージを 1 つのリソース ファイルに保持し、アプリ パッケージ マニフェスト文字列を別のリソース ファイルに保持し、UI 文字列を 3 番目のリソース ファイルに保持できます。 この場合のフォルダ構造は次のようになります。

Screenshot of the Solution panel showing the Adventure Works Cycles > Strings folder with German, U S English, and French locale folders and files.

文字列リソース識別子参照のスコープを特定のファイルに設定するには、識別子の前に /<resources-file-name>/ を追加するだけです。 次のマークアップの例では、ErrorMessages.resw に "PasswordTooWeak.Text" という名前のリソースが含まれており、その値がエラーを記述していることを前提としています。

<TextBlock x:Uid="/ErrorMessages/PasswordTooWeak"/>

/<resources-file-name>/ 以外のリソース ファイルの文字列リソース識別子の前に Resources.resw を追加するだけで済みます。 これは、"Resources.resw" が既定のファイル名であるため、ファイル名を省略した場合に想定されます (このトピックの前の例で行ったように)。

次のコード例では、ErrorMessages.resw に "MismatchedPasswords" という名前のリソースが含まれており、その値がエラーを記述していることを前提としています。

var resourceLoader = new Microsoft.Windows.ApplicationModel.Resources.ResourceLoader("ErrorMessages");
this.myXAMLTextBlockElement.Text = resourceLoader.GetString("MismatchedPasswords");

"AppDisplayName" リソースを Resources.resw から ManifestResources.resw に移動する場合は、アプリ パッケージ マニフェストで ms-resource:AppDisplayNamems-resource:/ManifestResources/AppDisplayName に変更します。

リソース ファイル名がセグメントに分かれている ("." 文字が含まれる) 場合、参照するときは名前のドットを残します。 リソース名の場合のように、リソース名のドットをスラッシュ ("/") 文字に置き換えることはしません

var resourceLoader = new Microsoft.Windows.ApplicationModel.Resources.ResourceLoader("Err.Msgs");

わからない場合は、MakePri.exe を使用してアプリの PRI ファイルをダンプできます。 各リソースの uri が、ダンプされたファイルで示されています。

<ResourceMapSubtree name="Err.Msgs"><NamedResource name="MismatchedPasswords" uri="ms-resource://<GUID>/Err.Msgs/MismatchedPasswords">...

特定の言語またはその他のコンテキストの文字列を読み込む

デフォルトのResourceContext (ResourceLoaderの作成時に取得される)には、各修飾子名の修飾子値が含まれており、デフォルトのランタイム・コンテキスト(つまり、現在のユーザーとマシンの設定)を表します。 リソース ファイル (.resw) は、(その名前に含まれる修飾子に基づいて) 実行時コンテキストでの修飾子の値と比較されます。

ただし、アプリでシステム設定をオーバーライドし、読み込む一致するリソース ファイルを探すときに使用する言語、スケール、またはその他の修飾子の値を明示的に指定したい場合があります。 たとえば、ユーザーがツールヒントやエラー メッセージの代替言語を選択できるようにすることができます。

これを行うには、新しい ResourceContext を構築し、その値をオーバーライドしてから、そのコンテキスト オブジェクトを文字列検索で使用します。

var resourceManager = new Microsoft.Windows.ApplicationModel.Resources.ResourceManager();
var resourceContext = resourceManager.CreateResourceContext();
resourceContext.QualifierValues["Language"] = "de-DE";
var resourceMap = resourceManager.MainResourceMap.GetSubtree("Resources");
this.myXAMLTextBlockElement.Text = resourceMap.GetValue("Farewell", resourceContext).ValueAsString;

上記のコード例のように QualifierValues を使用すると、任意の修飾子に対して機能します。 言語の特殊なケースでは、代わりにこれを行うこともできます。

resourceContext.Languages = new string[] { "de-DE" };

クラス ライブラリから文字列を読み込む

参照されるクラス ライブラリの文字列リソースは、通常、ビルド プロセス中に含まれるパッケージのサブフォルダーに追加されます。 このような文字列のリソース識別子は通常LibraryName/ResourcesFileName/ResourceIdentifier の形式を取ります。

ライブラリは、独自のリソースの ResourceLoader を取得できます。 たとえば、次のコードは、ライブラリまたはそれを参照するアプリが、ライブラリの文字列リソースの ResourceLoader を取得する方法を示しています。

var resourceLoader = new Microsoft.Windows.ApplicationModel.Resources.ResourceLoader("ContosoControl/Resources");
this.myXAMLTextBlockElement.Text = resourceLoader.GetString("exampleResourceName");

パスが不明な場合は、MakePri.exe コマンド ライン オプションを指定して、コンポーネントまたはライブラリの PRI ファイルをダンプできます。 各リソースの uri が、ダンプされたファイルで示されています。

<NamedResource name="exampleResourceName" uri="ms-resource://Contoso.Control/Contoso.Control/ReswFileName/exampleResourceName">...

他のパッケージからの文字列の読み込み

アプリ パッケージのリソースは、ResourceManager からアクセスできるパッケージ独自の最上位の ResourceMap を使用して管理およびアクセスされます。 各パッケージ内では、さまざまなコンポーネントが独自の ResourceMap サブツリーを持つことができ、ResourceMap.GetSubtree を介してアクセスできます。

フレームワーク パッケージは、絶対リソース識別子 URI を使用して独自のリソースにアクセスできます。 詳細については、UWP ドキュメントの「URI スキーム」も参照してください。

パッケージ化されていないアプリケーションでの文字列の読み込み

Windows バージョン 1903 (2019 年 5 月の更新プログラム) では、パッケージ化されていないアプリケーションでもリソース管理システムを利用できます。

Windows アプリ SDK ユーザー コントロール/ライブラリを作成し、文字列をリソース ファイルに格納する。 その後、XAML から文字列リソース識別子を参照したりコードから文字列リソース識別子を参照したりクラス ライブラリから文字列を読み込んだりできます

パッケージ化されていないアプリケーションでリソースを使用するには、いくつかのことを行う必要があります。

  1. パッケージ化されていないシナリオには既定のビューがないため、コードからリソースを解決するときに、ResourceManager のオーバーロードされたコンストラクターを使用してアプリの .pri ファイルのファイル名を渡します。
  2. MakePri.exe を使用して、アプリの resources.pri ファイルを手動で生成します。
    • makepri new /pr <PROJECTROOT> /cf <PRICONFIG> /of resources.pri を実行します。
    • <PRICONFIG> では、すべてのリソースが 1 つの resources.pri ファイルにバンドルされるように、"<packaging>" セクションを省略する必要があります。 createconfig によって作成された既定の MakePri.exe 構成ファイルを使用する場合は、作成した後、"<packaging>" セクションを手動で削除する必要があります。
    • <PRICONFIG> には、プロジェクト内のすべてのリソースを 1 つの resources.pri ファイルにマージするために必要なすべての関連インデクサーが含まれている必要があります。 createconfig によって作成される既定の MakePri.exe 構成ファイルには、すべてのインデクサーが含まれます。
    • 既定の構成を使用しない場合は、PRI インデクサーが有効になっていることを確認し (これを行う方法については、既定の構成を確認してください)、プロジェクト ルート内にあるプロジェクト参照や NuGet 参照などから見つかった PRI をマージします。

      Note

      /IndexName を省略し、プロジェクトにアプリ マニフェストがない場合、PRI ファイルの IndexName/ルート名前空間は自動的に Application に設定され、ランタイムはパッケージ化されていないアプリについて認識します (これにより、パッケージ ID に対する以前のハード依存関係が削除されます)。 リソース URI を指定する場合、ルート名前空間を省略した ms-resource:/// 参照は、パッケージ化されていないアプリのルート名前空間として Application を推論します (または、ms-resource://Application/ のように Application を明示的に指定することもできます)。

  3. .exe のビルド出力ディレクトリに PRI ファイルをコピーします
  4. .exe を実行します

    Note

    リソース管理システムは、パッケージ化されていないアプリの言語に基づいてリソースを解決するときに、ユーザーの優先言語リストではなくシステム表示言語を使用します。 ユーザーの優先言語の一覧は、Windows App SDK パッケージ アプリにのみ使用されます。

重要

リソースが変更されたときは常に、PRI ファイルを手動でリビルドする必要があります。 MakePri.exe コマンドを処理し、resources.pri の出力を .exe ディレクトリにコピーする、ビルド後スクリプトを使用することをお勧めします。

重要な API

関連項目