Java 货币显示名称国际化

2022-09-04 21:19:08

是否有任何原因可以解释为什么某些显示名称以英文显示,尽管区域设置不是英文的(即:未翻译)。

例如:Locale:“ru”未翻译

Locale locale = new Locale("ru");
Currency curr = Currency.getInstance("USD");
System.out.println(curr.getDisplayName(locale));
// US Dollar

区域设置:“es”已翻译

Locale locale = new Locale("es");
Currency curr = Currency.getInstance("USD");
System.out.println(curr.getDisplayName(locale));
// dólar estadounidense

这是故意的吗?还是Java没有开始翻译它?还是我做错了什么?

我试图找到存储这些翻译的文件,但找不到它们。如果有人能给我指出该资源,那将是有帮助的。

谢谢。


答案 1

区域设置服务提供商

Java 使用可扩展的机制来提供本地化的数据(如字符串、格式化程序等)。

类可以实现为本地敏感数据的工厂。中的许多类都依赖于这些提供程序,通过将对象的创建委托给它们来正确处理不同的类。LocaleServiceProviderjava.utiljava.textLocale

您可以在 java.util.spi 包中找到本地服务提供程序的示例,这些提供程序通常用于以依赖于区域设置的方式显示文本或数字。它包括 CurrencyNameProvider,它在调用 Currency#getDisplayName 时使用。

查找实现

希望使用特定(如 )用途来查找支持特定区域设置的提供程序实例的类。LocaleServiceProviderCurrencyNamePoviderLocaleServiceProviderPool

LocaleServiceProviderPool首先尝试使用 JRE 中包含的默认实现。如果未找到,则它依赖于Java中的简单服务提供程序接口(SPI)机制,并使用ServiceLoader1尝试查找第三方库提供的实现

这是在关于 Locale 的教程中编写的内容:

这些方法首先检查 Java 运行时环境是否支持请求的语言环境;如果是这样,他们将使用该支持。否则,这些方法将调用相应接口的已安装提供程序的 getAvailableLocales() 方法,以查找支持所请求的区域设置的提供程序。

可以在包中找到 JRE 附带的提供程序的默认实现。它很复杂,但它本质上是从罐子中获取数据的。在 Oracle JDK 中,它位于 .如果您列出此 jar 中的文件,并检查 和 中的文件,您将看到为西班牙语定义的货币名称比为俄语定义的货币名称多得多。sun.util.locale.providerlocaledata.jarjava_home/jre/lib/ext/localedata.jarsun.util.resources.essun.util.resources.ru

以下是OpenJDK的文件:俄语西班牙语

如果它根本没有定义怎么办

区域设置按层次结构进行组织。例如,某个国家/地区的特定区域可以具有区域设置,它反映了与该国家/地区的区域设置的一些本地差异。如果未找到区域设置的数据,将尝试使用区域设置的父级。LocaleServiceProviderPool

区域设置树的根基本上是一个“回退”虚构区域设置,它为所有本地化数据提供默认值。

当您要求以俄语显示美元时,可能会发生这种情况。

扩展

任何程序都可以提供其他区域设置信息。他们需要通过创建元数据文件来定义服务提供者1 并实现 .您可以在自己的 jar 中填写缺少的本地化数据。CurrencyNameProvider

结论

还是Java没有开始翻译它?

情况差不多就是这样。

还是我做错了什么?

不可以,您可以依赖默认值,也可以自己提供本地化数据。


1 ServiceLoader 将通过要求类加载器加载资源来找到它们。如果找到这样的文件,它应该具有实现的特定类名。然后,它尝试通过类装入器创建它的实例。META-INF/services/java.text.spi.DateFormatProvider


答案 2