web-dev-qa-db-ja.com

Java適切な複数形による国際化(i18n)

Javaの標準i18nシステムをChoiceFormatクラスで複数形に使用するつもりでしたが、一部の言語(ポーランド語など)の複雑な複数形ルールを処理できないことに気付きました。英語に似た言語しか扱えないのなら、少し無意味に思えます。

正しい複数形を実現するためにどのようなオプションがありますか?それらを使用することの長所と短所は何ですか?

36
Dr.Haribo

さて、あなたはすでに質問に正しくタグを付けているので、 [〜#〜] icu [〜#〜] について1つか2つ知っていると思います。

ICU)を使用すると、複数形を適切に処理するための2つの選択肢があります。

  • PluralRules 、指定されたロケールのルールを提供します
  • PluralFormat 、前述のルールを使用してフォーマットを許可します

どちらを使用しますか?個人的には、PluralRulesを直接使用して、リソースバンドルから適切なメッセージを選択することを好みます。

ULocale uLocale = ULocale.forLanguageTag("pl-PL");
ResourceBundle resources = ResourceBundle.getBundle( "path.to.messages",
                               uLocale.toLocale());
PluralRules pluralRules = PluralRules.forLocale(uLocale);

double[] numbers = { 0, 1, 1.5, 2, 2.5, 3, 4, 5, 5.5, 11, 12, 23 };
for (double number : numbers) { 
  String resourceKey = "some.message.plural_form." + pluralRules.select(number);
  String message = "!" + resourceKey + "!";
  try {
    message = resources.getString(resourceKey);
    System.out.println(format(message, uLocale, number));
   } catch (MissingResourceException e) { // Log this } 
}

もちろん、あなた(または翻訳者)は適切なフォームをプロパティファイルに追加する必要があります。この例では、次のように言います。

some.message.plural_form.one=Znaleziono {0} plik
some.message.plural_form.few=Znaleziono {0} pliki
some.message.plural_form.many=Znaleziono {0} plików
some.message.plural_form.other=Znaleziono {0} pliku

他の言語(アラビア語など)の場合は、「zero」および「two」キーワードを使用する必要がある場合もあります。詳細については、 CLDRの言語の複数形 を参照してください。

または、PluralFormatを使用して有効なフォームを選択することもできます。通常の例は直接インスタンス化を示していますが、これは私の意見ではまったく意味がありません。 ICUのMessageFormat :で使用する方が簡単です。

String pattern = "Znaleziono {0,plural,one{# plik}" +
                 "few{# pliki}" +
                 "many{# plików}" +
                 "other{# pliku}}";
MessageFormat fmt = new MessageFormat(pattern, ULocale.forLanguageTag("pl-PL"));
StringBuffer result = new StringBuffer();
FieldPosition zero = new FieldPosition(0);
double[] theNumber = { number };
fmt.format(theNumber, result, zero);

もちろん、現実的には、パターン文字列をハードコーディングすることはありませんが、プロパティファイルに次のようなものを配置します。

some.message.pattern=Found {0,plural,one{# file}other{# files}}

このアプローチの唯一の問題は、翻訳者がプレースホルダー形式を認識している必要があることです。上記のコードで示したもう1つの問題は、MessageFormatの静的format()メソッド(使いやすいメソッド)が常にデフォルトのロケールにフォーマットされることです。これは、デフォルトのロケールが通常サーバーのロケールを意味するWebアプリケーションでは実際の問題になる可能性があります。したがって、特定のロケール(浮動小数点数、気を付けてください)用にフォーマットする必要があり、コードはかなり醜いように見えます...

私はまだPluralRulesアプローチを好みます。これは、私にとってははるかにクリーンです(ただし、同じメッセージフォーマットスタイルを使用する必要があり、ヘルパーメソッドでのみラップされます)。

42
Paweł Dyda

ChoiceFormat、as ここで説明 は、あらゆる種類の複数化を処理するのに十分な柔軟性があるようです。

編集:ハリボー博士が彼のコメントで指摘したように、ChoiceFormatはポーランド語の複数化には十分ではありません。しかし 同じブログからのフォローアップ は、より複雑な複数化ルールを処理するICU4Jを示唆しています

3
Peter Elliott