Internationalization

android用の神経衰弱ゲームを公開しました(・∀・)
The Match-up(Memory) game for android was released!

Google Play:
Mole's Match-up.

Introduction page:
Mole’s Match-upをリリースした∩( ・ω・)∩


http://code.google.com/intl/ja/webtoolkit/doc/latest/tutorial/i18n.html

 GWT アプリケーションの国際化

この時点で、あなたはStockWatcherアプリケーションの最初の実装を作成済みです。
このチュートリアルでは、StockWatcherのユーザーインターフェイスをドイツ語に翻訳することによって、アプリケーションに他の言語とデータフォーマット をサポートさせるようにする方法を学びます。  具具体的にあなたがすることは:
  1. 国際化手法の選択
  2. サポートする各言語の翻訳を作成することによるStockWatcherの国際化
  3. コンテキスト(ロケール)に適切な翻訳を選択することによるStockWatcherのローカライズ
Note: GWTアプリケーションの国際化についての幅広いガイドについては、Internationalizationを見てください。

 始める前に

StockWatcher プロジェクト

このチュートリアルはGWTの概念とBuild a Sample GWT Application チュートリアルで作成した
StockWatcherアプリケーションを基にしています。 もしGWTアプリケーション作成チュートリアルを
終えておらずGWTの概念がある程度わかっているなら(慣れ親しんでいるなら)、
ここでStockWatcherプロジェクトをコードとしてインポートすることが出来ます。 
  1. StockWatcher projectをダウンロードします。
  2. ファイルを解凍します。
  3. エクリプスへプロジェクトをインポートします。
    1. ファイル メニューから、インポートメニューオプションを選択します。
    2. [一般]-[既存プロジェクトをワークスペースへ]を選択します。次へ(N)ボタンをクリックします。
    3. [ルート・ディレクトリーの選択(T)]でブラウズしStockWatcherのあるディレクトリ
      (ファイルを解凍した場所から)を選択します。完了(F) ボタンをクリックします。
antを使用している場合は、StockWatcher/build.xmlの何処にGWTを解凍したかを指す
 gwt.sdk プロパティを編集します。

 1. 設計

翻訳される必要があるものを決定します…ローカライズ可能なもの

現在の英語インターフェイスのStockWatcherを見ると、ローカライズ可能な2タイプのテキストがあることがわかります: 定数とメッセージ
screenshot: StockWatcher English UI

国際化手法の選択

GWTアプリケーションを国際化(インターナショナリゼーション)する場合、いくつかの手法のうちから一つ選択します。StockWatcherはユーザーインターフェイス内に2,3の定数とパラメータ化された決まったメッセージしか持ちませんので、静的文字列インターナショナリゼーションを使用します。
静的文字列インターナショナリゼーションは実行時にごくわずかなオーバーヘッドしか必要としないので、定数とパラメータ化された決まったメッセージ両方の翻訳に非常に効率的な手法です。
(※原文はinitializationになっていますが、出現回数・前後の文脈から考えて、おそらくinternationalizationが正しいと思われるのでここではそうしています)
更にもっとも実装することが容易な手法でもあります。静的文字列インターナショナリゼーションは 翻訳された文字列とパラメータ化されたメッセージを格納するために標準のJavaプロパティファイルを使用し、これらの値を取得するための型重視のJavaインターフェイスを実装します。

パラメータ化されたメッセージ…SQL等でparameterized query(パラメータ化クエリ、パラメータライズドクエリ)と呼ばれるものがあり、それはSQL文自体は不変でクエリの対象となるパラメータを他で設定しているものらしいので、その流れから考えると、その内容を他(この場合で言うとプロパティファイル)で設定しているメッセージ?

動的文字列インターナショナリゼーションは静的文字列インターナショナリゼーションよりも遅いですが、非常に柔軟性があります。この手法を使用するアプリケーションはモジュールのホストページでローカライズされた文字列を調べます;したがって、新たなロケールを追加した時に再コンパイルをする必要がありません。 GWTアプリケーションを既存のサーバサイドローカライゼーションシステムと統合する必要がある場合、動的文字列インターナショナリゼーションは考慮すべき選択肢です。
ローカライザブルインターフェイス

もっとも力強い手法はローカライザブルインターフェイスを実装することです。ローカライザブルの実装は単純な文字列の代用を越えてローカライズされたカスタムタイプバージョンを作成することを可能にします。これはおそらく頻繁に使用することのない高度な実装手法です。

 2. StockWatcherを国際化する: サポートする言語毎の翻訳の作成

処理概要: 静的文字列インターナショナリゼーション

静的文字列インターナショナリゼーションの為に行う処理は簡単です。
  1. 最初に二つのJavaインターフェイスを実装します:
    • 文字列定数用にGWT定数インターフェイス(StockWatcherConstants.java)
    • パラメータ化されたメッセージ用にGWTメッセージインターフェイス (StockWatcherMessages.java)

    これらのインターフェイスはデフォルトの翻訳を指定するためにアノテーションを指定します。

  2. それから、サポートする新しい言語毎用に、二つのJavaプロパティファイルを作成します:
    • 文字列定数用 (StockWatcherConstants_de.properties)
    • パラメータ化されたメッセージ用(StockWatcherMessages_de.properties)
  3. 最後に、Javaソースコードで全ての手書きされた文字列を適切なインターフェイスを呼び出すメソッドで置き換えます。
Tip: GWT はコマンドラインツール(i18nCreator)を提供します。 これはプロパティファイル内の文字列にアクセスするためのJavaインターフェイスの作成を自動化します。特に再利用したい既存のローカライズされたプロパティファイルがある場合にこのツールは役立ちます。

定数インターフェイスを実装する

最初に各翻訳を保持するプロパティファイルにアクセスするJavaインターフェイス(StockWatcherConstants)を作成します。インターフェイスはデフォルトの翻訳を指定するためにアノテーションを使用します。このインターフェイスはGWT  Constants インターフェイスをインプリメントしています。このインターフェイスは作成するどんなStockWatcherConstants*.propertiesファイルとでもそれ自身の名前によって自動的に結び付けられます。
StockWatcherConstants インターフェイスはプロパティファイル内の各定数用のメソッドを含みます。実行時にこれらのメソッドの一つが呼び出されると、 ロケールが一致するどのプロパティファイルからでも戻り値が返って来ます。 (ロケールを設定する方法はすぐに教えます。)  ロケールがセットされていない場合、StockWatcherはアノテーションによって指定されたデフォルトの翻訳を使用します。例えば、ロケールがGermanにセットされている場合、StockWatcherメソッドはAktieWatcherを返します; ロケールがセットされていない場合、stockWatcherメソッドはStockWatcherを返します。

StockWatcherConstantsを作成する

  1. クライアントサブパッケージ内で、インターフェイスを作成し、StockWatcherConstantsと名付けます。
    エクリプスのパッケージエクスプローラーペインでパッケージを選択します。
    com.google.gwt.sample.stockwatcher.client
    エクリプスのメニューバーから、ファイル(F) > 新規(N) > インターフェイスの順に選択します。
    エクリプスは「新規 Java インターフェイス」ウィンドウを開きます。
  2. 「新規 Java インターフェイス」内を埋めます。
    “名前(M)”には StockWatcherConstantsと入力し、他のフィールドはデフォルトのままとします。
     完了(F)ボタンをクリックします。
    エクリプスはStockWatcherConstantsインターフェイス用のスタブコードを作成します。
  3. スタブを以下のコードに置き換えます。
    デフォルト値をセットするためにアノテーションを使用していることに注目してください。
    package com.google.gwt.sample.stockwatcher.client;

    import com.google.gwt.i18n.client.Constants;

    public interface StockWatcherConstants extends Constants {
    @DefaultStringValue("StockWatcher")
    String stockWatcher();

    @DefaultStringValue("Symbol")
    String symbol();

    @DefaultStringValue("Price")
    String price();

    @DefaultStringValue("Change")
    String change();

    @DefaultStringValue("Remove")
    String remove();

    @DefaultStringValue("Add")
    String add();
    }
実装の注意:GWTは別のインターフェイス(ConstantsWithLookup)を提供します。このインターフェイスは実行時に動的に名前によってローカライズされた文字列を探すメソッドを含むこと以外では定数と似ています。

定数のドイツ語翻訳を作成する

インターナショナル文字セットへのエンコーディングをする

アプリケーションのユーザーインターフェイスを国際化する時に心に留めておいて欲しいことは、サポートしようとしている言語がASCII文字セットに無い文字を含んでいるかもしれないということです。従って翻訳を含むHTMLホストページ(StockWatcher.html)とJavaプロパティファイルの両方で、エンコーディングをUTF-8にセットしなければなりません。
  1. アプリケーションホストページ用のエンコーディングをチェックします。
    StockWatcher.htmlを開きます。
    まだエンコーディングがUTF-8にセットされていない場合は、以下のコードを要素へコピーします。

 StockWatcherConstant_de.propertiesを作成する

  1. クライアント サブパッケージ内で、Javaプロパティファイルを作成します。
    “親フォルダを入力または選択(E)”で以下のフォルダを選択します。
    StockWatcher/src/com/google/gwt/sample/stockwatcher/client
    ファイルネームに以下の値を入力します。
    StockWatcherConstants_de.properties
  2. ファイルのエンコーディングをUTF-8へ変更します。
    ファイルを選択してからエクリプスメニューバーからファイル(F)> プロパティー(R) を選択するか右クリックしてコンテキストメニューからプロパティー(R)を選択します。
    エクリプスはプロパティウィンドウを開きます。
    “テキスト・ファイルのエンコード(T)”で”その他(O):”を選択し、ドロップダウンリストから”UTF-8”を選択します。”適用(A)”ボタンをクリックして変更内容を保存します。
    Note: あなたのエクリプスの設定によっては変更内容を適用する時に、以下の警告を受けるかもしれません: UTF-8 conflicts with the encoding defined in the content type (ISO-8859-1). Do you wish to set it anyway?
    警告を無視して変更内容を適用してください。
  3. ドイツ語ユーザーインターフェイス内の静的文字列用のマッピングを追加します。
    StockWatcherConstant_de.properties ファイルへ以下のテキストをコピー&ペーストしてください。
    stockWatcher = Aktienbeobachter
    symbol = Symbol
    price = Kurs
    change = Änderung
    remove = Entfernen
    add = Hinzufügen
Note: プロパティファイルに接尾辞をつける
あなたが以前にインターナショナリゼーションを扱ったことがない場合、 何故ドイツ語プロパティファイルへ_de接尾辞を付加するのか不思議に思うかもしれません。接尾辞 _deはドイツ語(Deutsch)用の標準言語タグです。言語タグはドキュメントまたはアプリケーションのロケールの省略形です。言語を指定するのに加えて、更にロケールの地域を示す下位タグを含むことが出来ます。例えば、フランス語圏のカナダ用の言語タグはfr_CAです。
GWTではプロパティファイルは(Javaリソースバンドルのように)言語コード接尾辞でロケールを示します。デフォルトロケール用のプロパティファイルは例外です。実行時に特にロケールがセットされていない場合は、言語コード接尾辞がないプロパティファイルが使用されます。StockWathcerではデフォルトプロパティファイルを使う代わりにアノテーションでデフォルトの翻訳を指定しています。

メッセージインターフェイスを実装する

最初に、Javaインターフェイス(StockWatcherMessages)を作成します。これはパラメータ化された各メッセージの翻訳を保持するプロパティファイルにアクセスします。このインターフェイスはGWT Messages インターフェイスをimplementsします。 StockWatcherConstants インターフェイスと異なり、このインターフェイスのメソッドはパラメータを包含します。これらのメソッドを呼んだ場合、渡した引数はプロパティファイルの文字列内に残したプレースホルダーに置き換えられます。このインターフェイスはどんなStockWatcherMessages*.propertiesファイルでもそれ自身の名前によって自動的に結び付けられます。

データフォーマットを国際化する

パラメータ化されたメッセージはアラートとエラーメッセージをポップアップすることを制限されません。レーベルウィジェットへテキストをセットしたアプリケーション内のどんな場所でもパラメータ化されたメッセージとなる可能性はあります? 例えば、StockWatcher内のタイムスタンプはパラメータ化されたメッセージです;日付の値を渡すだけでなく、ロケールによってデータフォーマットを変更することも出来ます。
  1. クライアントサブパッケージで、インターフェイスを作成してStockWatcherMessagesと名付けます。
  2. 以下のコードをスタブと置き換えます。
    package com.google.gwt.sample.stockwatcher.client;

    import com.google.gwt.i18n.client.Messages;

    import java.util.Date;

    public interface StockWatcherMessages extends Messages {
    @DefaultMessage("''{0}'' is not a valid symbol.")
    String invalidSymbol(String symbol);

    @DefaultMessage("Last update: {0,date,medium} {0,time,medium}")
    String lastUpdate(Date timestamp);

    }

パラメータ化されたメッセージを初期化する時のTips

引数の番号を指定する
メッセージ文字列全てはメッセージ文字列に埋めこまれた{0}を持つことに注意してください?これらは実行時にStockWatcherMessagesインターフェイスメソッドへ渡された引数によって置き換えられるプレースホルダーです。 
一つ以上の引数を必要とする文字列の場合、シーケンシャルにプレースホルダーに番号をつけてください。
例えば: myString = First parm is {0}, second parm is {1}, third parm is {2}.
引用符(‘)で囲まれたテキストの処理
メッセージがシングルクォート(‘)が含んでいる場合(StockWatcher内のメッセージの多くは含んでいます?)、Javaプロパティファイル内でそれらを2連続のシングルクォートに置き換える必要があります。通常、GWT メッセージ用のフォーマットルールはJavaの MessageFormat クラスへ適用されるものと同じです。

パラメータ化されたメッセージのドイツ語翻訳を作成する

  1. Javaプロパティファイルを作成します。
    “親フォルダを入力または選択(E)”で以下のフォルダを選択します。
    StockWatcher/src/com/google/gwt/sample/stockwatcher/client
    ファイルネームに以下の値を入力します。
    StockWatcherMessages_de.properties
  2. ファイルのエンコーディングをUTF-8へ変更します。
  3. 英語ユーザーインターフェイス内のパラメータ化されたテキスト用のマッピングを追加します。
    StockWatcherMessages_de.properties ファイルへ以下のテキストをコピー&ペーストします。
    lastUpdate = Letzte Aktualisierung: {0,date,medium} {0,time,medium}
    invalidSymbol = ''{0}'' ist kein gültiges Aktiensymbol.

手書きされた文字列を生成されたローカライズされた文字列に置き換える

StockWatcherのインターナショナリゼーションの次のステップは、ソースコード内の全ての手書きされた文字列を二つの新しいインターフェイスの一つへのメソッドコールに置き換えることです。

HTMLホストページ内の手書きされた文字列を置き換える

現在、StockWatcherアプリケーションはプログラム的に生成されていない文字列を一つ持っています: タイトル, StockWatcher。それはホストページ(StockWatcher.html)のHTML

見出しです。

サンプルGWTアプリケーション構築するチュートリアルで、我々が見せたかったことは同じページ上でStockWatcherによって生成された文字列と静的なHTML要素を混ぜ合わせることが出来るということです。更に株テーブルの周りに静的なテキストを置くために速く簡単な方法でもありました。しかしながら、StockWactherのインターナショナリゼーションを行っている今、これが最も柔軟な方法ではないということがわかります。
この見出しを生成する簡単な方法は

要素内のテキストをGWT レーベルウィジェットへ置き換えて、ウィジェットのsetText(String)メソッドを呼び出すことです。思い出してください、GWTウィジェットは直接HTMLホストページへ埋め込むことは出来ません; 従って、最初にルートパネルでウィジェットをラップします。

  1. StockWatcher.htmlを開きます。
    id:”appTitle”を

    見出しに割り当てることによってルートパネルと

    見出し関連付けます。

    見出し内のテキストを削除します。





    StockWatcher


では、StockWatcherの全てのローカライズされた文字列を実行時にセット出来るようにしましょう。

プログラム的に文字列セットを置き換える

StockWatcherクラスを調べて手書きされたテキストである文字列を全て置き換えます。
  1. StockWatcherConstantsインターフェイスと StockWatcherMessagesインターフェイスのインスタンスを作成します。
    StockWatcherクラスに、以下のインスタンスフィールドの組を追加します。
    private ArrayList stocks = new ArrayList();
    private StockWatcherConstants constants = GWT.create(StockWatcherConstants.class);
    private StockWatcherMessages messages = GWT.create(StockWatcherMessages.class);
    これらはクラスではなくインターフェイスなので、直接インスタンス化は出来ません。代わりにGWT.create(Class)メソッドを使用します。そうすると、これらのインターフェイスの適切な文字列を取得する為のアクセサメソッドを使用することが出来ます。
  2. エクリプスはGWTにフラグをつけ、インポート宣言を追加するように提案します。
    import com.google.gwt.core.client.GWT;
  3. 全ての手書きされた文字列を定数クラスへのメソッドコールへ置き換えます。
    ウィンドウタイトル、アプリケーションタイトル、”Add Stock”ボタン、フレックステーブルのコラムヘッダの値を定数プロパティファイルから取得します。
    public void onModuleLoad() {
    // Set the window title, the header text, and the Add button text.
    Window.setTitle(constants.stockWatcher());
    RootPanel.get("appTitle").add(new Label(constants.stockWatcher()));
    addStockButton = new Button(constants.add());


    // Create table for stock data.
    stocksFlexTable.setText(0, 0, constants.symbol());
    stocksFlexTable.setText(0, 1, constants.price());
    stocksFlexTable.setText(0, 2, constants.change());
    stocksFlexTable.setText(0, 3, constants.remove());

    ...
  4. パラメータ化されたエラーメッセージを置き換えます。
    addStockメソッドで、無効な株コード入力時用のアラートメッセージを置き換えます。
    変更:

    private void addStock() {
    final String symbol = newSymbolTextBox.getText().toUpperCase().trim();
    newSymbolTextBox.setFocus(true);

    // Stock code must be between 1 and 10 chars that are numbers, letters, or dots.
    if (!symbol.matches("^[0-9a-zA-Z\.]{1,10}$")) {
    Window.alert("'" + symbol + "' is not a valid symbol.");
    Window.alert(messages.invalidSymbol(symbol));
    newSymbolTextBox.selectAll();
    return;
    }

    ...
  5. dateフォーマットを決定するロジックをMessageインターフェイスへ移動します。
    updateTable(StockPrice[] prices) メソッドで、変数(※この場合は可変の?)timestampを自身のlastUpdateメソッドと置き換えます。 
    変更:

    private void updateTable(StockPrice[] prices) {
    for (int i = 0; i < prices.length; i++) {
    updateTable(prices[i]);
    }

    // Display timestamp showing last refresh.
    lastUpdatedLabel.setText("Last update : "
    + DateTimeFormat.getMediumDateTimeFormat().format(new Date()));

    lastUpdatedLabel.setText(messages.lastUpdate(new Date()));

    }

 3. StockWatcherをローカライズする

この時点であなたはStockWatcherのユーザーインターフェイスのローカライズバージョン2つを作成済みです。しかしどうやってGWTはどのように実行時にどちらをロードするべきか知るのでしょうか?GWTは遅延バインディング(deferred binding)と呼ばれるメカニズムを使用してカスタマイズされたGWTアプリケーションのJavaScriptコンパイル成果物を生産するためにクライアントプロパティを使用します。実行時に提供されるべき正しいローカライズバージョンのStockWatcherを選択するために、GWTはクライアントプロパティのロケールを評価します。

 インターナショナリゼーションと遅延バインディング

あなたはサンプルGWTアプリケーションを構築するチュートリアル内で、GWTが異なるwebブラウザを対象とした、アプリケーションの異なる置換を生成するために遅延バインディングを使用するのを見ました。実行時、GWTブートストラップコードはエンドユーザーが使用しているブラウザに依存して決定される適切な置換を届けます。ユーザーエージェントはGWTクライアントプロパティなので、これらのブラウザ特有のコンパイル成果物が作成されます。同様にGWTはロケールをクライアントプロパティとして表します。これはGWTコンパイラがサポートされている各ロケールを表す国際化されたアプリケーションのカスタムバージョンを生成するということを意味します。
複数のクライアントプロパティがある場合、GWTは有り得るクライアントプロパティの値の組み合わせごとの一意的なコンパイル成果物を生成します。したがって、例えば、GWTが5つのブラウザをサポートし、あなたがアプリケーションを4つの異なる言語へ翻訳した場合、GWTコンパイラはアプリケーションの合計20の異なるバージョンを産み出します。しかしながら、アプリケーションの各ユーザーには彼または彼女特有のwebブラウザとロケールの組み合わせにマッチした置換のコードのみ提供されます。

StockWatcherがサポートするロケールを識別する

クライアントプロパティ値(ロケール)のセットを拡張することによって、現在、StockWatcherがGerman (de) ロケールをサポートしていることをGWTコンパイラに伝えます。
  1. ドイツ語をサポートしている言語として識別します。
    StockWatcher.gwt.xmlを開き、以下のプロパティを追加します。



  2. 開発モードでStockWatcherをリフレッシュします。
    デフォルトでは英語バージョンをロードします。
  3. ドイツ語バージョンをロードします。
    URLの最後に &locale;=deを付加します。
    http://localhost:8888/StockWatcher.html?gwt.codesvr=127.0.0.1:9997&locale;=de
    全ての定数がドイツ語で表示されます。
  4. 株コードに無効な文字を入力します。
    エラーメッセージがドイツ語で表示されます。
    日付と通貨のフォーマットもローカライズされていることに注目してください。
    screenshot: StockWatcher German UI
  5. StockWatcherをコンパイルし、プロダクションモードで開きます。
    webブラウザはStockWatcherのデフォルトインターフェイスを表示します。
  6. ドイツ語インターフェイスをテストします。
    URLにロケールを付加します。 ?locale=de
    webブラウザはStockWatcherのドイツ語インターフェイスを表示します。
  7. 生成されたファイルを見ます。
    ドイツ語インターフェイスを作成する前の二倍の置換用のファイルを見なければならないでしょう?

 ユーザーのロケールを決定する

実行時、どうやってあなたはユーザーのロケールを決定しますか? あなたは多くのウェブサイトがやっているように手動で選択する言語またはロケールのリストをユーザーに与えるかもしれません。
更に 正しいロケールを決定するためにブラウザのHTTPリクエスト内のAccept-Languageフィールドをwebサーバでチェックすることも出来ます。しかしながら、これを行う場合は、必ずユーザーへAccept-Languageフィールド内の値を上書きして言語プリファレンスを選択する方法を提供してください。

 ロケールのセット

StockWatcherが国際化された今、どうやってGWTは実行時にどのロケールをロードすべきかを知るのか? 答えはGWTはクライアントプロパティの値(ロケール)を使います。このクライアントプロパティをセットするのには二つの方法があります:
  • アプリケーションホストページのへ、プロパティネームと値を含んだHTMLタグを追加します:
  • URLのクエリ文字列へクライアントプロパティ値を付加します:
    http://www.example.org/myapp.html?locale=de
タグとURLの両方に(ロケールのような)クライアントプロパティを指定している場合、URLの値が優先されます。

 複数のブラウザページをまたがってロケールを維持する

GWTモジュール用のロケールセッティングは当該のモジュールの当該のインスタンスにのみ適用されます。これはアプリケーションがあなたのサイト上の他のGWTホストページまたはnon-GWT webページへのリンクを含んでいる場合、ロケールセッティングはそれらのページには持ち越されないということ意味します。したがって、ユーザー固有ロケールを維持したい場合は、GWTアプリケーション内の全てのリンクのクエリ文字列内でロケールを渡すか、またはすべてのロードされたGWTモジュールのホストページへ適切なタグを挿入出来るサーバ上のどこかにロケールを格納する必要があります。

 インターナショナリゼーションについて

この時点で、あなたはGWTアプリケーションのドイツ語置換を生成するために静的文字列インターナショナリゼーションを使用しています。
あなたはユーザーのロケールに基づいて適切な置換をロードするようにローカライゼーションを実装しました。

3つのインターナショナリゼーションの手法全て、GWT I18Nモジュール、または既存のローカライズされたプロパティファイルを再利用するためのGWT i18nCreatorの使用法についてより詳しく学びたいのならば、開発者ガイドのInternationalizationを見てください。