38

我打算将 Java 的标准 i18n 系统与 ChoiceFormat 类一起用于复数,但后来意识到它不能处理某些语言(例如波兰语)的复杂复数规则。如果它只处理类似于英语的语言,那么它似乎有点毫无意义。

有哪些选择可以实现正确的复数形式?使用它们的优点和缺点是什么?

4

2 回答 2

45

好吧,您已经正确标记了问题,所以我假设您对ICU 有所了解。

使用 ICU,您有两种选择来正确处理复数形式:

使用哪一个?就个人而言,我更喜欢直接使用 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

对于其他语言(即阿拉伯语),您可能还需要使用“零”和“二”关键字,有关详细信息,请参阅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}}

这种方法的唯一问题是,翻译者必须知道占位符格式。我试图在上面的代码中展示的另一个问题是,MessageFormat 的静态 format() 方法(易于使用的方法)总是为默认语言环境格式化。这在 Web 应用程序中可能是一个真正的问题,其中默认区域设置通常意味着服务器的区域设置。因此,我必须为特定的语言环境(浮点数,请注意)进行格式化,并且代码看起来相当难看......

我仍然更喜欢 PluralRules 方法,它对我来说更干净(尽管它需要使用相同的消息格式样式,只用辅助方法包装)。

于 2013-01-14T22:10:20.933 回答
3

ChoiceFormat,正如这里所解释的,它似乎足够灵活,可以处理您可能会遇到的任何类型的复数形式。

编辑:正如哈里博博士在他的评论中指出的那样,ChoiceFormat 不足以满足波兰语的多元化。但是来自同一个博客的后续文章建议 ICU4J 处理更复杂的复数规则

于 2013-01-14T21:21:43.290 回答