« 【 #VS2013 】アカウントの画像を変更する方法 | トップページ | 【Windows Phone 開発】 ユーザー レビューに返信できるようになった!! #wpdev_jp »

2014年8月13日 (水)

【WP8.1】中華フォント対策はどれがいいか? ~CultureInfo.CurrentUICulture の仕様が変わっていた件 #wpdev_jp

Windows Phone 8.1 の Windows Runtime アプリになっても、 あいかわらず 「中華フォント問題」 の対策が必要です。
それには、 App クラスの中で Frame を生成した直後に、
rootFrame.Language = ???
と設定してやればいいんです。 が、 問題は 「???」 をどう書くか?

3通りの書き方があります。
どれがいいんでしょう? 順番に見ていきましょう。

例として、 英語と日本語に対応したアプリを考えてみます。
※ 英語アプリで日本語のコンテンツを表示して審査に通るのか、 って問題は、 とりあえず横に置いときます f(^^;

日本語環境では日本語の UI を、 それ以外の環境では英語の UI を表示するものとします。
つまり、Package.appxmanifest の [既定の言語] を 「en-US」 にし、
/Strings/en-US/Resources.resw

/Strings/ja-JP/Resources.resw
を用意します。

それでは…


1◆ CultureInfo.CurrentUICulture

これは、 MS エヴァの高橋さんご推薦の方法

rootFrame.Language = System.Globalization.CultureInfo.CurrentUICulture.Name;

でも、 CultureInfo.CurrentUICulture って、 ユーザーが OS に設定した言語が返ってくるから、 英語環境なら英語、 中国語環境なら中国語が返ってきて、 けっきょく日本語環境の端末以外では中華フォントになっちゃう…
…と思っていました (汗;

なんと、 CultureInfo.CurrentUICulture の仕様が、 .NET 4.5 で変わっていたんですねぇ。
ということで、 しばらく脱線します f(^^;

CultureInfo.CurrentUICulture は、 内部的に Win32 API の GetUserDefaultUILanguage 関数を呼び出していて、 GetUserDefaultUILanguage API の返値はユーザーの設定によって変わります

ので、 CultureInfo.CurrentUICulture は、 英語環境なら英語、 中国語環境なら中国語が返ってくると思いこんでたんですが…。
.NET 4.5 の MSDN (英語版、 日本語訳の方は例によってワケワカメw) を見ると…

  • By retrieving the culture that is specified by the DefaultThreadCurrentUICulture property in the application domain in which the thread is executing, if the property value is not null.
  • By calling the Windows GetUserDefaultUILanguage function.

上の 1つめの項目が、 .NET 4.5 で追加されていました (従来は、 2つめの項目だけだった)。
これにより、 Windows ストア アプリや Windows Phone ストア アプリでは、 GetUserDefaultUILanguage API によらず、 アプリ起動時にシステムが設定した言語 (つまり、 Package.appxmanifest で設定した言語) が CultureInfo.CurrentUICulture の値になります。
※ ということは、 多言語対応していないアプリでは、 どんな環境でも CultureInfo.CurrentUICulture は同じ値になるということです (既定の言語を 「ja-JP」 にしていたら、 常に 「ja」 が返ってくる)。

さて、 話を戻して。

既定の言語が 「en-US」 で、 日本語環境では 「ja-JP」 の文字列リソースを使うように多言語化している場合、 CultureInfo.CurrentUICulture の値は、 日本語環境では 「ja」、 それ以外の環境では 「en-US」 になります。

ので、
rootFrame.Language = System.Globalization.CultureInfo.CurrentUICulture.Name;
としてやると…、

日本語環境では、日本語のフォントになります
Currentuiculture_01

英語環境 (その他、日本語以外の環境) では、 中華フォントに! orz
Currentuiculture_01_2
※ これは多言語対応アプリですよ~。ボタンの文字列がちゃんと英語リソースになってます。


2◆ ApplicationLanguages.Languages[0]

これは、 Visual Studio 2013 Update 2 以降の、 VB の いくつかの Windows ストア用テンプレートに書かれている方法 (Phone 用には書かれていないw)。

[VS2013Update3 の VB で新規作成した Hub アプリのコード]
20140815_vs2013update3vb_hubapp01
※上半分の App クラスに下記のコードが見える。 下半分の NavigationHelper クラスには、 #If WINDOWS_PHONE_APP Then …などとあって、 VB でもユニバーサル プロジェクト化が進行中だと分かる。

' 既定の言語を設定します
rootFrame.Language = ApplicationLanguages.Languages(0)

C# で書くなら、 こう↓です。

rootFrame.Language = ApplicationLanguages.Languages[0];

(2014/8/17 追記) [VS2013Update3 の C# で新規作成した空のアプリのコード]
20140817_vs2013u3_cblankapp02
※ 普段使いの Hub アプリとか、 ユニバーサルプロジェクトとかには、 入っていない。 あったりなかったり… 不思議だ (--;

ApplicationLanguages.Languages は、 マニフェストに設定されている言語のリストです*1。 ただし、 アプリ起動時にシステムが設定した言語が、 リストの先頭に来ます。
ということで、 先の CultureInfo.CurrentUICulture と同じ結果になります。

※ 上で脱線した話に気付くまでは、 違う結果になるじゃんと思っていた時期もありましたw

*1(2014/8/17 追記) ApplicationLanguages.Languages のリストは、 MSDN によれば正確には次のようにして生成されるようです。
1. (オプション) PrimaryLanguageOverride による上書き
2. ユーザーの言語の優先順位を示した一覧です。この一覧は、アプリのマニフェストのサポート対象言語の一覧によってフィルター処理されます。 (←通常はこれになっているはず)
3. 1 と 2 が空の場合、アプリでサポートされる既定の言語


3◆ "ja"

UI は多言語化するけどコンテンツは日本語なんだ、 いつも日本語フォントで表示したい、 というときは、 どうしましょう?
上の 2通りのやり方では、 どちらも日本語環境以外では中華フォントになってしまいます。

簡単ですね。 リテラルを指定してやればOK。

rootFrame.Language = "ja";

日本語環境では、日本語のフォント
_01

英語環境 (その他、日本語以外の環境) でも日本語フォント (^^)
_01_2
※ ボタンの文字列にはちゃんと英語リソースが使われている!

で、 多言語対応しないときも、 リテラルで指定しちゃえばいいですね。 つまり、 いつでもリテラルで OK。


◆結論

日本語以外の環境でも日本語のコンテンツを見せるんだ、 というときには、 リテラルで指定すればよろし。
環境によっては中華フォントで見せなければならないというときは…、 悩んでくだされ f(^^;

|

« 【 #VS2013 】アカウントの画像を変更する方法 | トップページ | 【Windows Phone 開発】 ユーザー レビューに返信できるようになった!! #wpdev_jp »

プログラミング」カテゴリの記事

* プログラミング ( Metro スタイル )」カテゴリの記事

コメント

この記事へのコメントは終了しました。

トラックバック


この記事へのトラックバック一覧です: 【WP8.1】中華フォント対策はどれがいいか? ~CultureInfo.CurrentUICulture の仕様が変わっていた件 #wpdev_jp:

« 【 #VS2013 】アカウントの画像を変更する方法 | トップページ | 【Windows Phone 開発】 ユーザー レビューに返信できるようになった!! #wpdev_jp »