Is there any reason why certain display names are displayed in English despite the locales not being in English (ie: not translated).
For example: Locale: "ru" is not translated
Locale locale = new Locale("ru");
Currency curr = Currency.getInstance("USD");
System.out.println(curr.getDisplayName(locale));
// US Dollar
Locale: "es" is translated
Locale locale = new Locale("es");
Currency curr = Currency.getInstance("USD");
System.out.println(curr.getDisplayName(locale));
// dólar estadounidense
Is this intentional? Or has Java not gotten around to translating it? Or am I doing something incorrectly?
I tried to locate the files where these translations are stored but couldn't find them. If someone could point me to that resource as well that would be helpful.
Thanks.
Java uses an extensible mechanism to provide data (such as strings, formatters, etc) that is localized.
Classes can implement
LocaleServiceProvider
to be a factory of local-sensitive data. A lot of classes injava.util
andjava.text
rely on these providers to work properly with differentLocale
by delegating the creating of objects to them.
You can find examples of Local Service Providers in the java.util.spi
package, that are usually used to display text or numbers in a way that is dependent on the Locale. It includes CurrencyNameProvider
which is used by Currency
when calling Currency#getDisplayName
.
Classes wanting to use a specific LocaleServiceProvider
(such as CurrencyNamePovider
) use LocaleServiceProviderPool
to find the instances of the provider that support a specific Locale.
LocaleServiceProviderPool
tries first to use a default implementation included in the JRE. If it's not found, it relies on the simple Service Provider Interface (SPI) mechanism in Java and uses a ServiceLoader
1 to try to find implementations provided by third party libraries.
This is what is written in the tutorial about Locale:
These methods first check whether the Java runtime environment supports the requested locale; if so, they use that support. Otherwise, the methods call the getAvailableLocales() methods of installed providers for the appropriate interface to find a provider that supports the requested locale.
The default implementations of the providers that come with the JRE can be found in the package sun.util.locale.provider
. It's complex, but it essentially gets the data from the jar localedata.jar
. In Oracle JDK, it is located in java_home/jre/lib/ext/localedata.jar
. If you list the files that are in this jar, and check the files in sun.util.resources.es
and in sun.util.resources.ru
, you will see that there is many more currency names defined for Spanish than for Russian.
Here are the files for OpenJDK: Russian vs Spanish.
Locales are organized in a hierarchy. For example, a specific region of a country can have a Locale which reflects some local differences from the Locale of the country. If data is not found for a Locale, LocaleServiceProviderPool
will try to use the Locale's parent.
The root of the tree of Locales is basically a "fallback" fictional Locale which provides default values for all localized data.
That's what probably happening when you ask for the display name of USD in russian.
Any program can provide additional Locale information. They need to define a service provider1 by creating the metadata file and implement a CurrencyNameProvider
. You can fill in the missing localized data in your own jar.
Or has Java not gotten around to translating it?
That's pretty much the case.
Or am I doing something incorrectly?
No, you can either rely on the defaults or provide the localized data yourself.
1 The ServiceLoader
will find them by asking the classloader to load the resource META-INF/services/java.text.spi.DateFormatProvider
. If such file is found, it should have in it the specific class name of the implementation. It then tries to create an instance of it through the classloader.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With