好了,您已经正确标记了问题,所以我假设您了解ICU的一两件事。
使用ICU,您有两种选择来正确处理复数形式:
- 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} pliksome.message.plural_form.few=Znaleziono {0} plikisome.message.plural_form.many=Znaleziono {0} plikówsome.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方法,对我而言,这种方法更加简洁(尽管它需要使用相同的消息格式样式,仅使用辅助方法进行包装)。



