4

当我通过 输出数字时,如何在JAVA 11中使用不受支持的区域设置(例如ar-US)?String.format()

Java 8中这工作得很好(尝试jdoodle选择 JDK 1.8.0_66):

Locale locale = Locale.forLanguageTag("ar-US");
System.out.println(String.format(locale, "Output: %d", 120));
// Output: 120

由于Java 11的输出是东方阿拉伯数字(尝试jdoodle使用默认的 JDK 11.0.4):

Locale locale = Locale.forLanguageTag("ar-US");
System.out.println(String.format(locale, "Output: %d", 120));
// Output: ١٢٠

看来,这个问题来自于语言环境数据提供者JRECLDR的切换(来源:@mcarth 在 Java 9 中的本地化更改)。以下是支持的语言环境列表:JDK 11 Supported Locales

更新

我将问题示例更新为ar-US,因为我之前的示例没有意义。我们的想法是有一种在特定国家有意义的格式。在示例中,它将是美国 ( US)。

4

2 回答 2

5

该行为符合被视为首选的 CLDR Locale。为了确认这一点,可以使用 Java-8 中的相同代码段执行

-Djava.locale.providers=CLDR

如果您退后一步查看JEP 252: Use CLDR Locale Data by Default,详细信息如下:

默认查找顺序为 CLDR、COMPAT、SPI,其中 COMPAT 指定 JRE 在 JDK 9 中的区域设置数据。如果特定提供者无法提供请求的区域设置数据,则搜索将按顺序继续到下一个提供者。

因此,简而言之,如果您真的不希望默认行为是 Java-11 的默认行为,您可以使用 VM 参数更改查找顺序

-Djava.locale.providers=COMPAT,CLDR,SPI

进一步了解如何使用 CLDR 选择正确的语言可能会有所帮助!

于 2020-12-09T16:40:23.933 回答
2

我确定我遗漏了一些细微差别,但问题出在你的标签上,所以修复它。具体来说:

ar-EN没有意义。简称:

language = arabic
country = ?? nobody knows.

CN 不是一个国家。en当然是语言代码(英语),但语言标签中的第二部分是国家,而 EN 不是国家。(对于上下文,有en-GB英式英语和en-US美式英语)。

因此,这与ar(如语言 = 阿拉伯语,不依赖于任何特定国家)一样好。即使您确实将其与某个国家/地区联系在一起,这在这里也几乎无关紧要;这可能会影响诸如“一周的第一天是什么”、“假定使用哪种货币符号”以及“温度应该以开尔文还是华氏度表示”之类的事情。它与如何显示数字无关,因为这一切都基于语言。

语言是阿拉伯语,因此,١٢٠ 是您ar在打印数字 120 时尝试作为语言标签时得到的结果。问题是您希望返回"120"这是一个奇怪的愿望1,再加上 java 的事实,不幸的是,很长一段时间都带有一个错误,导致它以这种奇怪的方式运行,认为最好用阿拉伯语来渲染数字 120 "120",这是错误的。

因此,在这种情况下,按照优先顺序:

最佳解决方案

找出为什么您的系统以 ar-EN 结尾,但仍需要“120”,并解决此问题。一般也修复ar-EN;CN 不是一个国家。

更一般地说,“不受支持的语言环境”并不是真正的事情。该ar部分是受支持的,它是标签中唯一用于渲染数字的相关部分。

备择方案

如果上述情况不可能,最可能的最佳答案是明确解决它。自己检测标签,并编写代码来响应格式化这个数字的结果,Locale.ENGLISH而不是使用,保证你得到Output: 120. 其余的似乎更糟:您可以尝试编写一个需要大量工作的本地化提供程序,或者您可以尝试告诉 java 使用提供程序的 JRE 版本,但是那个已经过时并且不会更新,所以您'正在把罐子踢到路上,并为以后的维护负担做好准备。

1.)鉴于 JRE 变体实际上打印了 120,并且您还表示您想要这个,我有一种唠叨的感觉,我错过了一些政治或历史信息,以及ar-EN导致数字 120 呈现"120"为不是这样的期望疯狂的。如果你愿意提供它,我很想听听这个故事!

于 2020-12-09T14:28:33.530 回答