25

This question seems insanely simple, yet I'm embarrased to say I haven't been able to figure out how it works.

I want my Java SE application to get its number format from whatever is configured in the OS. Just like any other application on that OS.

My target is primarily Windows. Consider this example in Windows:

enter image description here

I use this little example to check the result:

public class MyMain {
    public static void main(String[] args) {
        DecimalFormat decFormat = new DecimalFormat();
        DecimalFormatSymbols decSymbols = decFormat.getDecimalFormatSymbols();           
        System.out.println("Decimal separator is : " + decSymbols.getDecimalSeparator());
        System.out.println("Thousands separator is : " + decSymbols.getGroupingSeparator());
    }
}

With the screenshot example above my little Java example prints:

Decimal separator is : ,
Thousands separator is : .

I would have expected it to say that the decimal separator is a dot and the thousands separator is a comma - because that's what I've told Windows and that's what all other Windows applications pick up.

I'm under the impression that in Windows these settings take effect for new processes. I've tried restarting my IDE. Didn't help.

What am I doing wrong?

peterh
  • 18,404
  • 12
  • 87
  • 115
  • Look [here](http://stackoverflow.com/questions/838590/how-to-read-list-separator-from-os-in-java) – Jens Jul 07 '14 at 18:05
  • It appears you will need to read this information from the registry if you need it. – Peter Lawrey Jul 07 '14 at 18:07
  • @Jarrod They don't seem to be asking about `Locale` based formats. – Sotirios Delimanolis Jul 07 '14 at 18:10
  • The way to do this is with `Locale` otherwise it will be OS specific. –  Jul 07 '14 at 18:14
  • Forgive my skepticism. I just want my Java application to adapt itself to the user's preferences for how he has told his OS that he wants numbers displayed (could equally been his preference for display of currency, dates or whatever). It simply can't be true that I need to do some OS specific hack here. That's what I have Java for. – peterh Jul 07 '14 at 18:21

2 Answers2

17

I've found the answer myself.

Starting from JDK8 you can ask Java to have the host's settings as your number one priority when resolving locale related stuff.

I've extended my example slightly:

public class MyMain {
    public static void main(String[] args) {
        DecimalFormat decFormat = new DecimalFormat();
        DecimalFormatSymbols decSymbols = decFormat.getDecimalFormatSymbols();
        String localeProvidersList = System.getProperty("java.locale.providers", "JRE,SPI");
        System.out.println("Decimal separator is : " + decSymbols.getDecimalSeparator());
        System.out.println("Thousands separator is : " + decSymbols.getGroupingSeparator());
        System.out.println("Locale providers list : " + localeProvidersList);
    }
}

Running my example above with -Djava.locale.providers=HOST,JRE,SPI gives:

Decimal separator is : .
Thousands separator is : ,
Locale providers list : HOST,JRE,SPI

Running without java.locale.providers defined gives:

Decimal separator is : ,
Thousands separator is : .
Locale providers list : JRE,SPI

Personally I would always run my Java applications with -Djava.locale.providers=HOST,.... because that will make my Java applications behave like native application do on that same host.

I found the answer deep inside the JDK8 javadocs. There's also a few notes about it in the Java 8 Enhancements docs.

peterh
  • 18,404
  • 12
  • 87
  • 115
2

You need to see: how to detect operating system language (locale) from java code. It seems like the bug was introduced in early Java 7 releases, and is somewhat fixed in later Java 7.

To test, I set my Window 7 Region to "French France". (Same as you show in your screen shot.)

Running this code:

System.out.println("default locale=" + Locale.getDefault());
System.out.println("user.language=" + System.getProperty("user.language"));
DecimalFormat decFormat = new DecimalFormat();
DecimalFormatSymbols decSymbols = decFormat.getDecimalFormatSymbols();
System.out.println("Decimal separator is : " + decSymbols.getDecimalSeparator());

with Java 6 (jdk1.6.0_45) output:

default locale=fr_FR

user.language=fr

Decimal separator is : ,

with Java 7 (jdk1.7.0_40) output:

default locale=en_US

user.language=en

Decimal separator is : ,

So only the decimal separator is correct with Java 7. One possible difference - is that I didn't change my "System Locale" from English (US) to French (France), because it required a restart. So perhaps that may affect what Java 7 is displaying for the Locale and user.language values.

Community
  • 1
  • 1
Sam Goldberg
  • 6,711
  • 8
  • 52
  • 85
  • Thanks, but the issue here is how to get Java to recognize the customized settings (choices made by user) on the right-hand side picture of the screenshot above. The problem is that Java - unlike various user interfaces like Windows or KDE - links everything to locale. I guess that some 30 years ago this was a sound design choice. Now, with globalization, end users no longer feel that there's (necessarily) any direct link between their choice of locale and their choice of say number formatting. Java's model is flawed. It belongs to another age. Windows, KDE and OSX does it correctly. – peterh Jul 08 '14 at 06:13