我原本打算使用Java标准的i18n系统和ChoiceFormat类来处理复数形式,但是发现它无法处理某些语言(例如波兰语)的复杂复数规则。如果只能处理类似英语的语言,那似乎有点毫无意义。
有哪些选项可以实现正确的复数形式?使用它们的优缺点是什么?
我原本打算使用Java标准的i18n系统和ChoiceFormat类来处理复数形式,但是发现它无法处理某些语言(例如波兰语)的复杂复数规则。如果只能处理类似英语的语言,那似乎有点毫无意义。
有哪些选项可以实现正确的复数形式?使用它们的优缺点是什么?
好的,您已经正确标记了问题,所以我认为您对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}}
ChoiceFormat
,如这里所述,似乎足够灵活,可以处理您可能遇到的任何复数形式。ChoiceFormat
不能满足波兰语复数形式的要求。但是同一博客的后续建议使用ICU4J来处理更复杂的复数规则。
MessageFormat
API和ResourceBundle
API的区别? - BalusC