5

私は現在、より大きな Java デスクトップ アプリケーションに取り組んでおり、翻訳を追加したいところです。l18n システムで気になるのは、コンパイル時のチェックがまったくないことです。

HashMapJava のシステムでは、ローカライズされたすべての文字列に「キー」があり、翻訳された文字列が「値」である のようなものがあります。これは次のようになります (チュートリアルの例から抜粋):

Locale currentLocale;
ResourceBundle messages;

currentLocale = new Locale(language, country);

messages = ResourceBundle.getBundle("MessagesBundle", currentLocale);
System.out.println(messages.getString("greetings"));

これは、単純な/小さなアプリケーションの場合にうまく機能します。しかし、何千もの翻訳された文字列を持つ大規模なアプリケーションでは、「キー」にタイプミスがあり、その結果、空の文字列または間違った文字列が取得されることがあります。

少し運が良ければ、アプリケーションはRuntimeExceptionそれについて通知するためにスローしますが、それでも、特定の状況下で表示されない可能性があるダイアログで間違った「キー」が使用されているため、この時点に到達しない可能性があります(エラーダイアログだとしましょう)。

これを防ぐには、使用された「キー」のコンパイル時チェックを提供するシステムを使用することをお勧めします。これは、たとえば Android で使用されます。XML ファイルでリソースを指定すると、インデックスが作成され、クラスにマップされます (使用する「キー」を含む)。このようにして、次のようなものが得られます ( Android Docsから):

// Set the text on a TextView object using a resource ID
TextView msgTextView = (TextView) findViewById(R.id.msg);
msgTextView.setText(R.string.hello_message);

その「キー」にタイプミスがあると、コンパイル時にエラーが発生します (IDE からの「オートコンプリート」もあります)。

さて、このような作業を行うには、索引付けの部分を実行し、Resource-class ( R.java) を生成する小さなツール/スクリプトが必要です。Android では、Eclipse プラグイン (または一般的には IDE) がそれを行います。

私の質問は次のとおりです。Java で通常のデスクトップ アプリケーションに使用できるシステムは既にありますか? それとも、私が言っていることはひどく間違っていますか?

4

4 に答える 4

4

この問題にはかなり簡単な解決策があります。まず、マジックストリングをコードとして使用せず、定数を定義して参照します。だからあなたは変わる。

messages.getString("greetings");

messages.getString(I18.GREETINGS_CODE);

対応するクラスがあります。

public class I18 {

  public static final String GREETINGS_CODE = "greetings";

}

次に、I18クラス内の各コードが各言語リソースファイルで検索されるテストケースを記述します。いずれかのリソースファイルにコードが欠落している場合は、テストに失敗します。コンパイル時間ではありませんが、問題が発生した場合、プロジェクトはテストに失敗します。

于 2012-04-20T15:27:32.993 に答える
3

標準のリソース バンドルを使用するかなり大規模なエンタープライズ アプリケーションはほとんど見たことがありませんが、これは問題ではありません。

いくつかの成功要因があります。

  1. リソース組織
  2. リソース ヘルパー
  3. リソースファクトリー
  4. キー命名戦略

広告 1. 単一のリソース バンドルを使用することにした場合、問題は特に顕著になります。このように行かないでください。大きな単一ファイルを維持する方法はありません。キーの重複、キーの命名などの問題に直面するでしょう。さらに、大規模なアプリケーションでは、同じファイル セットで同時に作業する人がほとんどいないのが一般的です。リソース バンドルの場合、これは多くのマージと相互の邪魔になることを意味します。これは通常のプログラミング チームの問題ですが、Localizers の場合はさらに深刻です。
必要なのは、複数の小さなリソース ファイルです。アプリケーションの規模によっては、モジュールごとに 1 つのファイル、またはダイアログごとに 1 つのファイルになる場合もあります。ファイルを分割する方法は実際のアプリケーションによって異なりますが、私が推奨するのは、テキストの 2 画面を超えるリソース ファイルを持たないことです。
多数のファイルがある場合、問題はそれらを整理する方法です-有効なディレクトリに配置します。私が提案したいのは、分離することですソース コードからリソース ファイルを抽出します (L10n などと呼ばれる別のディレクトリに配置します)。ResourceBundle.Control クラスをいじる必要がありますが、リソース ファイルのルートの下に言語フォルダーがあると便利です (これにより、各ターゲット言語の翻訳を簡単に分離できます)。次に、言語ルートの下に、各モジュールのサブディレクトリを作成します。モジュール ルートの下に個別のサブディレクトリを作成するか (アプリケーションが非常に大きい場合)、リソース バンドルを直接配置します。

広告 2. ResourceBundle クラスを直接使用する方法はありません。問題の 1 つは、ファイルにそのようなキーがない場合、または探しているファイルがない場合にMissingResourceExceptionがスローされることです。代わりに、たとえば、感嘆符の間のキーの名前 (!the.key.does.not.exist!) など、何か問題が発生したことを (ユーザー インターフェイスで) 確認したいと思うでしょう。これは、Eclipse の "Externalize Strings " はデフォルトで行います。
ResourceBundle のラッパーであるか、そこから派生するリソース ヘルパーを作成することを決定する場合があります。選択はあなた次第です(ただし、上記のような深刻なリソース編成では、独自の ResourceBundle.Control クラスを作成する必要があるため、派生するのが合理的な選択です)。単純な翻訳処理のほかに、メッセージの書式設定、複数形などの処理などの追加機能を Resource Helper に追加できます。
現時点では、間違ったリソース キー名の問題は処理されません。実際の UI テストが必要です。タイプミスが表示されます。間違ったキーを使用している場合 (特に、コピー アンド ペースト デザイン パターンを使用している人にとっては ;)) 何もないと思います問題を解決するテクノロジー。機械は考えません。とにかく、(たとえば) キー定数またはネストされた列挙型を持つネストされたクラスを配置することで、キーに関する問題を処理できます。このようなソリューションの問題点は、モジュールごとに個別の Resource Helper が必要になることです。これは良いアイデアではありません (特に大規模なアプリケーションでは)。実行可能ですが、面倒です。もちろん、文字列を外部化するための IDE の組み込みメカニズムは、このソリューションでは機能しません。

広告 3. 多数のリソース ファイルを操作するには、リソース ヘルパーを作成する静的リソース ファクトリ (またはファクトリ) を構築する必要があります。私の戦略は、公に見える列挙型を Factory 内にネストし、リソース ファイルをその定数として持つことです。次に、有効なバンドルをリクエストします。次に例を示します。

ResourceHelper helper = ResourceFactory(
                          ResourceFactory.Bundles.ERRORS, Locale locale);

広告 4. 混乱を避けるために、チームは単一のリソース キーの命名戦略を決定する必要があります。キー名について私が提案するのは(モジュールごとに1つのファイルを持つ)ことです:

  • ダイアログまたはユニット
  • わかりやすい名前
  • コンテキスト

例えば:

  • validation.invalid.username.error
  • validation.enter.pass.label
  • validation.dialog.title
  • menu.main.file.open.item
  • login.dialog.ok.button

コンテキスト (ラベル、dialog.title、項目、エラー、メッセージ、パターンなど) は、翻訳者にとって非常に重要です。翻訳は通常、文脈によって異なります。これが、翻訳を再利用すべきではない理由でもあります (「OK」、「キャンセル」、「中止」、「ヘルプ」などの一般的なボタン名や一般的なメニュー名や項目などの非常に一般的な項目は別として)。

于 2012-04-21T08:05:17.520 に答える
2

リソースにインデックスを付けることができるこのようなツールについては、私は決して気にしません。私見、かなり珍しい要件。アプローチの 1 つ - コードで文字列リテラルを使用する代わりに、それらをすべて単一のクラスに移動し、static final 修飾子で宣言します。この定数をリソース マップのキーとして使用します。また、リフレクションを使用して、単一のクラスで宣言されたすべてのリソースがリソースのファイルに存在することを確認するテストを作成するのは非常に簡単です。コードアナライザーを書くよりもはるかに簡単です

于 2012-04-20T15:22:12.157 に答える
1

c10nはあなたが探しているものだと思います(@eee から親切に指摘されたように、ありがとう!)。

全体的なアイデアは、エラーが発生しやすいキーを記述することから解放し、翻訳値で注釈を付けたコンパイル時にチェックされるプレーンな Java インターフェイス メソッドに置き換えることです。

例えば:

public interface Bundle{
  @En("Hello, World!")
  @De("Hallo Welt!")
  String greeting();
}

// ... somewhere in your code
public class MyClass{
  private static final Bundle bundle = C10N.get(Bundle.class);

  public void myMethod(){
    System.out.println(bundle.greeting());
  }
}

インターフェイスでリファクタリングを行い、Bundleメソッドの名前を変更して移動し、インターフェイスを追加し、拡張し、構成することができます。javacでコンパイルされている限り、正しい翻訳が確実に表示されます。

詳細については、上記のリンクを参照してください

于 2012-04-21T09:21:39.427 に答える