在Java中,为什么小数分隔符遵循Locale的语言,而不是其国家/地区,更重要的是,如何覆盖它?
我正在开展一个国际项目,并且观察到,在Java中,小数分隔符的选择基于Locale的语言,而不是其国家。 例如:
DecimalFormat currencyFormatter = (DecimalFormat) NumberFormat.getInstance(new Locale("it","IT")); System.out.println(currencyFormatter.format(-123456.78)); currencyFormatter = (DecimalFormat) NumberFormat.getInstance(new Locale("en","IT")); System.out.println(currencyFormatter.format(-123456.78));
产生以下输出:
-123.456,78 -123,456.78
我原本期望它跟随这个国家,因为如果我在国内,无论我说英语还是意大利语,那个国家的数字都用小数点分隔符写成逗号。
我的问题是双重的:
- 有谁知道为什么这种行为遵循语言?
- 更重要的是,任何人都可以提供有关如何修改Java中的默认行为以遵循该语言的详细信息吗?
谢谢。
很可能你的系统上没有已知的“en_IT”语言环境,并且Java知道没有这样的语言环境。
因此,您将获得最接近匹配的Locale的资源,根据Locale的JavaDoc中的这个注释:
当您要求特定区域设置的资源时,您将获得最佳可用匹配,而不一定是您要求的。 有关更多信息,请查看
ResourceBundle
。
ResourceBundle
中的相关文档显示,从未尝试过单独的国家/地区作为查找给定资源的标识符。 仅使用语言,语言+国家和语言+国家+变体。
1.-有谁知道为什么这种行为遵循语言?
应用程序根据其语言环境进行更改的第一个方面之一是语言。 想想瑞士,他们将法语和德语作为官方语言。 在这种情况下使用国家是没有意义的,因为除了货币之外还有其他方面(例如显示消息,要考虑)
同样适用于许多国家(加拿大是其他我想到的国家)。
该国可以选择专门使用该语言。
由于没有“意大利语英语”en_IT没有多大意义。 所以它需要“英语”,这就是为什么返回的实例是“en”英语的实例。
2.-更重要的是,任何人都可以提供有关如何修改Java中的默认行为以遵循该语言的详细信息吗?
你的意思是,这个国家对吗?
答案在于方法: NumberFormat.getAvailableLocales() ,它反过来引导您: NumberFormatProvider这是一个抽象类,您可以扩展为返回“en_IT”的正确NumberFormat
(几乎将返回it_IT)
如何安装这个新类超出了我的知识,但我认为你必须在 jre
目录中的某个地方破解它。
编辑
因为我怀疑这个类应该安装在jre/ext
文件夹下,就是这样。
在其他地方有一个项目做了类似于支持“gl_ES”的事情(加利西亚语)
以下是有关如何安装以及它的全部内容的说明:
http://www.javagalician.org/install.html
所以,基本上,如果你想为意大利提供一堆实例(或者更好的是一个实例),你只需要创建一个NumberFormatProvider实例并让它响应所有可用的语言。
但如果你是一个住在意大利的英国人,你很可能仍然用英文的方式写下你的数字,并用脑袋计算你的钱 – 反之亦然;-)
所以对我来说,这种行为看起来很合乎逻 而且我担心可能没有办法得到你想要的东西:-(
根据Oscar Reyes的评论进行更新:在Java 6中,NumberFormatProvider使您能够实现目标。
修改所有Java是一个很大的顺序; 据我所知,在JVM级别没有办法做到这一点。 但是,您可以使用DecimalFormatSymbols类手动将特定类/项目的数字格式设置为几乎任何区域设置(甚至是虚构系统)。 有关示例和更多信息,请参阅Java Tutorials页面上的 “更改格式符号”, 格式自定义 。
当然,如果您的程序可能在三个或四个以上的不同位置使用,这不是最佳方法,但如果您只支持少数几个,它可能会有效。
你的假设“我原本希望它跟随这个国家,因为如果我在国内,无论我说英语还是意大利语,那个国家的数字都用小数点分隔符作为逗号。” 是错的。 几个双语国家/地区对数字具有特定语言格式规则 在Sun的JDK中具有格式规则的国家/地区中,这适用于加拿大,印度和卢森堡。
我认为您可以使用LocaleServiceProvider覆盖每个Locale的NumberFormat行为。 这需要Java 6,但……
正如人们所指出的那样,问题很可能是java无法找到你确切的本地,所以它去了它认为最接近的地方。 如果您有一个DecimalFormat对象,可以根据需要手动更改分隔符。
DecimalFormat format = ...; DecimalFormatSymbols symbols = format.getDecimalFormatSymbols(); symbols.setDecimalSeparator(','); symbols.setGroupingSeparator('.'); format.setDecimalFormatSymbols(symbols);
我原本期望它跟随这个国家,因为如果我在国内,无论我说英语还是意大利语,那个国家的数字都用小数点分隔符写成逗号。
没有。一些拥有许多官方语言的国家(如加拿大(两种官方语言))根据语言有不同的格式约定:
-1 234,56 (Locale.CANADA_FRENCH) -1,234.56 (Locale.CANADA (should probably be named CANADA_ENGLISH))