国際化
国際化 (I18N) とは、アプリケーションを異なる言語に適応させ、地域の差異を吸収することを意味します。アプリケーションを国際化対応可能にするためには、以下の手順に従ってください。
使用するのは UTF-8 だけ!
Play はたったひとつの文字エンコーディングをサポートします: UTF-8 です。文字エンコーディングの問題は異様で扱いが難しいので、Play は、ただひとつの文字エンコーディングをサポートすることを選択しました。UTF-8 では、すべての言語のすべての文字を表示することができます。
アプリケーション全体を通して、一貫して UTF-8 を使用するよう気を付けてください:
- すべてのソースファイルを UTF-8 として編集してください
- HTTP ヘッダに適切な文字エンコーディングを定義してください
- HTML meta タグに UTF-8 を設定してください
- データベースを使用する場合は、UTF-8 を使用するようデータベースを設定し、常に UTF-8 を使用して接続してください
注意
UTF-8 エンコーディングに関する問題は、Play の設定ファイルのほとんどが、それらが Java プロパティファイルであるにも関わらず、 *.properties
と名付けられていない理由です。Java は、プロパティファイルは ISO-8859-1 でエンコーディングしなければならないという制約を課します。Play の設定ファイルは UTF-8 でエンコーディングしなければなりません。これ以上なにか言う必要はありますか?
メッセージの外部化
I18N をサポートするには、アプリケーション中のすべてのメッセージを外部化しなければなりません。
アプリケーションの conf/
ディレクトリに messages
という名前のファイルを作成してください。このファイルは本当にただの Java プロパティファイルです。
hello=Hello!
back=Back
その後、アプリケーションで使用する言語ごとに、特別な message
ファイルを定義することができます。単純に、ISO 言語コードをファイルの拡張子として追加してください。
例えば、対応するフランス語の訳語を含むメッセージファイルは conf/messages.fr
です:
hello=Bonjour!
back=Retour
アプリケーションがサポートする言語の定義
サポートする言語のリストを application.langs 設定 に定義してください。
新しいユーザからの最初のリクエストの際は、Play は使用するデフォルトの言語を推測します。これは HTTP Accept-language
ヘッダを解析して行います。その後、選択した言語を PLAY_LANG
クッキーに保存します。このため、次のリクエストは選択した言語を使用します。
en_US と en_GB や zh_CN と zh_TW のようなバリアントを区別するために、言語/国のペアを使うこともできます。しかし、あるユーザは Accept-language において言語のみを提示し、国を提示しないかもしれないことに注意してください。このような理由から、常に (例えば en のような) “生の” 言語を提供すべきです。
例えば、ユーザのほとんどが US からやってくるけれど、イギリス英語もサポートしたい場合、アメリカ英語には単に “en” を使い、イギリス英語に “en_GB” を使うことをお勧めします。
play.i18n.Lang
オブジェクトにアクセスすることで、アプリケーションからこのユーザの現在の言語情報を検索することができます:
String lang = Lang.get();
このユーザの言語情報を恒久的に変更したい場合は、change() メソッドを使用します:
Lang.change("ja");
新しい値は、このユーザの言語クッキーに保存し直されます。
ロケールに沿った日付データフォーマット
date.format を設定して、使用するデフォルトの日付フォーマットを指定します。
ローカライズされたメッセージの検索
メッセージ引数
メッセージファイルに定義したメッセージをアプリケーションコードから検索することができます。Java からは、 play.i18n.Messages
オブジェクトを使用します。
public static void hello() {
renderText(Messages.get("hello"));
}
標準的な java.util.Formatter
の‘フォーマット文字列構文’をサポートしています。メッセージ中に動的な内容を定義することもできます:
hello=Hello %s!
%s
は String
として出力されるメッセージ引数を表しています。メッセージ引数は、 Messages.get
の (可変長) 引数に追加することで提供されます:
public static void hello(String user) {
renderText(Messages.get("hello", user));
}
テンプレート出力
テンプレートでは、特別な &{…}
構文を使ってローカライズされたメッセージを表示することができます:
<h1>&{'hello'}</h1>
メッセージ引数に動的なコンテンツを使うこともできます:
<h1>&{'hello', params.user}</h1>
複数の引数
以下の二つの ‘10 進数’ の引数を参照するメッセージのように、複数のメッセージ引数を定義することができます:
guess=Please pick a number between %d and %d
メッセージ引数は表示する順序通りに指定します:
<p>&{'guess', low, high}</p>
引数インデックス
明示的に順序を指定したメッセージ引数を使うこともできます。例えば、二つの引数を持つ英語のメッセージがあるとします:
guess.characteristic=Guess %s’s %s.
以下のようにして出力します:
<p>&{'guess.characteristic', person.name, 'age'}</p>
フランス語版メッセージの二つの引数は順序が逆なので、フランス語版メッセージでは引数インデックスを指定します:
guess.characteristic=Devinez %2$s de %1$s.
%2$s
には 二番目の 引数が 10 進数として出力されます。
最後に、特徴的な名称である ‘age’ も国際化したいので、以下のように変更したメッセージ定義と、メッセージキー person.age
を使って、出力を変更したいと思います:
guess.characteristic=Guess %s’s &{%s}.
person.age = age
フランス語版メッセージ定義は以下のように変更します。
guess.characteristic=Devinez &{%2$s} de %1$s.
person.age = l’age
&{%s}
は、それ自身が引数の値をメッセージキーとして、メッセージを引き当てます。
考察を続けます
次: キャッシュ