ストアアプリ xaml 国際化 i18n の仕方

C# 2015 の内容です
2015以前のバージョンのVSではやり方が違うようです。

UWPアプリの国際化

(1) デフォルト言語の設定
Package.appxmanifestの既定のの言語(default language)
ja-JPになっているので、en-USに変更します
※カルチャのリソースが存在しない場合、この言語が適用されます

(2) リソースの作成
カルチャ名 ("ja-JP" など) と、それに続く既定のリソース名とリソース ファイルの拡張子 ("ko-kr\Resources.resw" など) を使用して、リソースを表します。
https://msdn.microsoft.com/ja-jp/library/hh694557.aspx
カルチャ名より前の親フォルダの規定はないようなので、
i18nフォルダを作成しその下にローカライズされたものをいれることにします
ソリューションエクスプローラーで追加をクリックし
  1. 「新しいフォルダ」で i18n  i18n/ja-JP と i18n/en-USを作成してください
    ※エクスプローラーなどで直接フォルダを作ると
    ソリューションエクスプローラーで表示されないので注意してください
  2. 次にサブフォルダ内で「新しい項目」→「リソースファイル(.resw)」 をクリックします。
    Resources.reswが作成されます
(2-1) i18n/en-US/Resources.resw
リソース キー
キー名
TextBlock_1.Content This is TextBlock
キー名には、コントロールのUIDと設定したいプロパティの名前と . でつないだ名前にします
UID名.プロパティ名
TextBlockでは、Contentとなります

(2-2) i18n/ja-JP/Resources.resw
リソース キー
キー名
TextBlock_1.Content テキストです

(3) MainPage.xaml
<TextBlock x:Uid="TextBlock_1"></TextBlock>
コントロールに uidを割り当てます。
x:Uid="stringID" をコントロールに埋め込みます
  • stringID: アプリ内の XAML 要素を一意に識別し、リソース ファイルのリソース パスの一部となる文字列です。
  • x:Name が XAML 名前スコープによって制御されるのに対して、x:Uid が XAML 言語で定義された一意性の適用の概念によって制御されることはありません。
  • x:Uid 解決の目的で、1 つのリソース範囲を共有します。個々の XAML ファイルに合わせた x:Uid 範囲の概念は存在しません。

リソースに複数同じUIDのプロパティ値が存在するとエラーになります
x:Uid="open" としていて、Textblockとメニューにいれたとします
これらは、ContentとTextとそれぞれ違うプロパティになります
open.Content open.Text という値をリソースに埋めていると
型 'Windows.UI.Xaml.Markup.XamlParseException' の例外が
発生しましたが、ユーザー コード内ではハンドルされませんでした
となります。「stringID」と「リソースキー名.プロパティ値」は、一対一の関係でないといけません

以上の(1)~(3)だけで 国際化は完了です
カレントカルチャもとづいて、勝手に切り替わります

海外に住んでいて日本語Windowsでない場合は、英語になってしまいます。
これでは困ります。ユーザーが切り替えれるようにする必要があります
つづいて、動的に リソースを 変更する方法です

リソース文字列の取得
var loader = new Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView();
var text = loader.GetString("リソース名");


起動時に en-USにする方法
App.xaml.cs を開き OnLaunched関数に以下の行を追加します
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
  System.Globalization.CultureInfo.CurrentUICulture = new System.Globalization.CultureInfo("en-US");
こうすると、英語になります。 国際化した意味がないですけどね~。
確認したらコードを消すか、コメントアウトするといいです。

クリックしたら切り替える
ChangeCulture関数を作りました。
永続させる 設定する this.ChangeCulture("en-US");
クリアする this.ChangeCulture("");
一時的 設定する this.ChangeCulture("en-US", false);
例ではクリックと同時に切り替わります。設定は、永続します

ストアアプリにApplication.DoEventsがないため、ストップウォッチに回しています
1ms待ちでもリソース変更するようです。念のため10msにしています。

private void button_open1_Click(object sender, RoutedEventArgs e)
{
    this.ChangeCulture("en-US");
    //this.ChangeCulture("ja-JP", false);
}

public async void ChangeCulture(string CultureName, bool is_Permanence = true)
{
    if (CultureName == "")
    {
        // reset PrimaryLanguageOverride
        Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = "";
    }
    else
    {
        System.Globalization.CultureInfo cn = new System.Globalization.CultureInfo(CultureName);
        if (is_Permanence)
            Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = cn.Parent.Name;
        else
            System.Globalization.CultureInfo.CurrentUICulture = cn;
    }

    // clear resource cache
    Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Reset();
    Windows.ApplicationModel.Resources.Core.ResourceContext.GetForViewIndependentUse().Reset();
    if (this.Frame != null)
    {
        // wait for resource change
        var stopwatch = System.Diagnostics.Stopwatch.StartNew();
        await System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(10));
        stopwatch.Stop();
        // refresh page
        this.Frame.Navigate(typeof(MainPage));
    }
}