In Java, why does the decimal separator follow Locale, not its country, and, more importantly, how to override it?

I am working on an international project and noticed that in Java the choice of the decimal separator is based on the Locale language, and not on its country. For example:

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)); 

outputs the following result:

 -123.456,78 -123,456.78 

I would expect him to follow the country, because if I am in the country, whether I speak English or Italian, the numbers in this country are written with a decimal separator as a comma.

My question is double:

  • Does anyone know why this behavior follows language?
  • More importantly, can anyone suggest detailed information on how to change the default behavior in Java to follow the language instead?

Thanks.

+6
java decimal-point number-formatting locale
source share
8 answers

It is very, very likely that your system does not have the famous language "en_IT" and that Java does not know such a locale.

Therefore, you will get resources for the closest Locale match, according to this note in the JavaDoc Locale :

When you request a resource for a particular locale, you get the best match available, not necessarily what you requested. See the ResourceBundle for more information.

the corresponding documentation in the ResourceBundle shows that only the country never tries to identify this resource as an identifier. Only language, language + country and language + country + option are used.

+6
source share

1.- Does anyone know why this behavior follows language?

One of the first aspects that change in the application in accordance with its language version is the language. Think of Switzerland, where they have both French and German as official languages. Using a country in this scenario is pointless because besides the currency there is another aspect (for example, the displayed messages to take into account)

The same goes for a number of countries (Canada is another thing that comes to my mind).

The country has the opportunity to specialize in this language.

Since there is no “Italian English”, en_IT does not make much sense. Therefore, "English" is required, and therefore the returned instance is an instance with "en" in English.

2.- More importantly, can anyone suggest detailed information on how to change the default behavior in Java to follow the language instead?

Do you mean that the country is right?

The answer lies in the method: NumberFormat.getAvailableLocales () , which in turn leads you to: NumberFormatProvider , which is an abstract class that you can extend to return the correct NumberFormat for "en_IT" (which will pretty much return it_IT)

How to install this new class is beyond my knowledge, but I think you will have to hack it somewhere in the jre directory.

EDIT

As I suspect, the class should be installed in the jre/ext folder and that it is.

Elsewhere, there is a project that did something similar to supporting "gl_ES" (Galician)

Here are the installation instructions and what it is:

http://www.javagalician.org/install.html

So basically, if you want to provide a bunch of instances for Italy (or even better than one), you just need to create one instance of NumberFormatProvider and give it answers to all available languages.

+4
source share

But if you are an Englishman living in Italy, most likely you still write your numbers in English and count your money in pounds in your head - and vice versa; -)

So for me this behavior seems quite logical. And I'm afraid that there can be no way to get what you want: - (

Update based on Oscar Reyes comment:. In Java 6, the NumberFormatProvider function allows you to achieve your goal.

+3
source share

Changing all of Java is a big order; as far as I know, there is no way to do this at the JVM level. However, you can manually set the number format for your specific classes / projects in almost any locale (or even on an imaginary system) with the DecimalFormatSymbols class . See “Changing the formatting characters” on the Java Formatting Tutorials page for more details. .

Of course, this is not an optimal approach if your program can be used in more than three or four different places, but it can work if you only support several.

+2
source share

Your suggestion: "I would expect it to follow the country, because if I am in the country, whether I speak English or Italian, the numbers in this country are written with a decimal separator as a comma." wrong. Several bilingual countries have special formatting rules for numbers. Among countries with formatting rules in Sun JDK, this applies to Canada, India, and Luxembourg.

+2
source share

I think you can override the NumberFormat behavior for each locale using the LocaleServiceProvider . This will require Java 6, though ...

0
source share

I would expect him to follow the country, because if I am in the country, whether I speak English or Italian, the numbers in this country are written with a decimal separator as a comma.

Not. Some countries with many official languages, such as Canada (two official languages), have different language-based formatting conventions:

 -1 234,56 (Locale.CANADA_FRENCH) -1,234.56 (Locale.CANADA (should probably be named CANADA_ENGLISH)) 
0
source share

As people note, the problem is most likely that java cannot find your exact local, so he went to what he thought was closest. If you have a DecimalFormat object, you can manually change the delimiters if you want.

 DecimalFormat format = ...; DecimalFormatSymbols symbols = format.getDecimalFormatSymbols(); symbols.setDecimalSeparator(','); symbols.setGroupingSeparator('.'); format.setDecimalFormatSymbols(symbols); 
0
source share

All Articles