当前位置: 首页 > 面试题库 >

带有适当复数的Java国际化(i18n)

况鸿雪
2023-03-14
问题内容

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

有哪些选项可以实现正确的复数形式?使用它们的利弊是什么?


问题答案:

好了,您已经正确标记了问题,所以我假设您了解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} 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方法,对我而言,这种方法更加简洁(尽管它需要使用相同的消息格式样式,仅使用辅助方法进行包装)。



 类似资料:
  • 主要内容:时区转换,可用时区UTC代表协调世界时。 这是时间标准,并在全世界普遍使用。 所有时区的计算都与UTC的时差相当。 例如,丹麦哥本哈根的时间是表示UTC时间加上一个小时。用于在数据库中存储日期和时间。 时区转换 以下示例将展示各种时区的转换。 我们将以毫秒为单位打印一天中的小时和时间。 第一次将会有所不同,第二次将保持不变。 文件:IOTester.java - 执行上面示例代码,得到以下结果 - 可用时区 以下示

  • 使用的方法,可以更改数字的默认分组。 下面的例子说明了相同的情况。 文件:IOTester.java - 执行上面示例代码,得到以下结果 -

  • 在这个例子中,我们将演示如何解析不同地区的数字。 文件:IOTester.java - 执行上面示例代码,得到以下结果 -

  • 使用类,可以更改默认分隔符,分组分隔符等。 下面的例子说明了上述的情况。 文件:IOTester.java - 执行上面示例代码,得到以下结果 -

  • 类根据给定的模式格式化日期。 它也用于解析日期从字符串,其中字符串包含提到的格式的日期。 请参阅以下使用类的示例。 文件:IOTester.java - 执行上面示例代码,得到以下结果 -

  • 类根据区域设置格式化日期。 由于不同的国家使用不同的格式来显示日期。 这个类在处理应用程序内部化日期时非常有用。 以下示例显示如何创建和使用类。 文件:IOTester.java - 执行上面示例代码,得到以下结果 -