Wrong Java resource bundle loaded - java

In my application, I'm using java resource bundle for the translation of its labels.
I currently have two files:
resources.properties with labels in English (default language)
resources_fr.properties with labels in French
Then, I load the bundle properties with the following command:
ResourceBundle.getBundle(RESOURCE_BUNDLE_NAME, locale);
... where locale is the user's locale.
When I'm working with a French web browser, that's ok, I'm getting all my messages in French, as my locale is correctly set to fr.
But when I switch my browser to English US, they're still in French!
The locale variable is correctly set with the en_US locale, but the getBundle method returns me a bundle with the fr locale instead of just returning the default bundle...
Is it a normal behaviour? I'm very surprised, as I was expecting the English values of resources.properties to be used when the locale has no specific resource bundle attached to it (like French)...

It is the normal result, which is nevertheless quite surprising if you haven't read the (rather lengthy) description of getBundle carefully. The important part is:
If no matching resource bundle is found, the default control's getFallbackLocale method is called, which returns the current default locale. A new sequence of candidate locale names is generated using this locale and and searched again, as above.
This is a bit unexpected. Only after having tried with the default locale in addition to the specified locale, the method does what you would expect:
If still no result bundle is found, the base name alone is looked up.
This is a reasonable behavior for a desktop application. After all, if you have succeeded in starting a Java application given the machine's default locale, you should know how to handle the application if it comes up using the default locale instead of the one that you have specified. But if your application is a web server and the server's locale is used instead of the preferences that you have specified in your browser, the resulting page can be quite a puzzle.
The proper way to handle this is to suppress the usage of the fallback locale. You could do this in your code by specifying the additional argument ResourceBundle.Control.getNoFallbackControl(ResourceBundle.Control.FORMAT_DEFAULT), resulting in
ResourceBundle.getBundle(RESOURCE_BUNDLE_NAME, locale,
ResourceBundle.Control.getNoFallbackControl(
ResourceBundle.Control.FORMAT_DEFAULT));
(I usually define a constant for the additional argument somewhere when I need this more than once.) This results in the behavior that you were expecting.

This might help to clarify your question:
http://docs.oracle.com/javase/tutorial/i18n/resbundle/propfile.html
These Locale objects should match the properties files created in the
previous two steps. For example, the Locale.FRENCH object corresponds
to the LabelsBundle_fr.properties file. The Locale.ENGLISH has no
matching LabelsBundle_en.properties file, so the default file will be
used.

Related

What locale does DecimalFormat and DateFormat use by default? (why is it different to Locale.getDefault()?)

When debugging my application, if found that DecimalFormat and DateFormat are set to use nl_NL by default, but the system locale seems to be en_US.
I found the first by evaluating:
new DecimalFormat().symbols.locale
new SimpleDateFormat().locale
And the second:
Locale.getDefault()
System.getProperty("user.country")
System.getProperty("user.language")
What is happening there?
How can I set those formatters to use a certain locale by default? (I'm writing unit tests and would like to set a specific locale without touching the application code)
As of Java 7, the default locale comes in two categories: "DISPLAY" and "FORMAT".
Both are initially set according to the environment. They can be found by calling Locale.getDefault(Category).
Besides the system properties mentioned in the question:
"user.country"
"user.language"
The following can also be present when running the JVM:
"user.country.format"
"user.language.format"
"user.country.display"
"user.language.display"
The reason for that seems to be that some OS's allow independent localization settings for displaying text and for formatting dates, numbers and currency.
Answering my last question, by calling Locale.setDefault(Locale) the default locale will be set for all categories.

How to get systeminfo locale - Locale.getDefault()

Currently my System Locale is en-UK, it used to be en-US (I've restarted my computer for this change to be in effect)
When I print Locale.getDefault().getCountry().toString() I still get US though.
In the API it states:
getDefault()
Gets the current value of the default locale for this
instance of the Java Virtual Machine.
Maybe the JVM locale is not related to the system locale? If so, how do I get the system locale on Windows?
Edits:
after researching the other questions about this, I found it useful to say that I'm dealing with Java 6.
I've just found that on my OS (Windows 7) the System locale change is not reflected in Java, but the Control Panel > Region and Language > Formats change is reflected.
I've overlooked something, in production code the osgi.nl config attribute is set, changing what Locale.getDefault would return otherwise
Your JVM locale and System locale can indeed possibly be different.
When the JVM is first loaded it assigns its locale to be the same as the system's locale unless you specified otherwise on the command line (not all implementations let you do this).
You can see what the value of this JVM locale is from Locale.getDefault().
In case you want to change that you can: Locale.setDefault("<preferred_locale>") read more about it here.
The system locale setting depends on the OS that you are using. I don't know much about Windows but, you can see what the values are from System.getEnv(). It returns a Map<String, String> of all environment properties and you can look for something like LANG or GDM_LANG, etc.
The country variant is taken from the "Non-Unicode" settings in the extended dialog of Windows locale.
There was is bug in Sun JDK 6u27+ and JDK 7, BugId 7073906:
The Locale returned from Locale.getDefault() is en_US when it shoud be en_GB.
I think this is what is biting you here :)
I realized in production an argument WAS being set that altered the Locale.getDefault() return value. This was difficult to check/prove.
My solution was that the user.country and user.language were not changed and reflected the actual Locale.
Locale locale = new Locale(System.getProperty("user.language"),System.getProperty("user.country"));
Locale.setDefault(locale);
//this will do the trick for me
Big thanks to everyone who answered and commented.

Selecting a useful codepage given a particular locale

Given a Locale in Java (eg. Locale.FRANCE) how can I pick a sensible code-page to accompany it for single-byte encoding? I can get the language from the locale (eg. "fr") but then turning this into a code-page ("ISO-8859-1") seems tricky. As I understand it the mapping isn't necessarily one-to-one, so at this point I'm simply trying to guess at something for a default option.
public static Charset guessSinglebyteCharsetFromLocale(Locale loc) {
// ...
}
The use-case here is exporting a CSV file for use in Excel. Excel doesn't appear to understand Unicode unless the user explicitly goes through the Data->Import Text wizard, and the requirement is for them to be able to open these files "as simple as possible". In my system I know the Locale for the current user, so I want to automatically guess at a codepage that will mangle their data the least.
To my knowledge, there is no one-to-one java Locale to java Charset conversion available in Java. You will need to build a table of possible locale that your application expects to encounter.
For Excel to recognized the converted single byte text, your computer will need to be set to intended locale for 'non-unicode' applications using the Region/language settings from the Control Panel. This also imposes another requirement, namely that only one locale can exist within one csv file.

Locale setDefault() Risk in Java

I got one application that can switch language between English and Germany. When in Germany language i want the currency display will auto convert into German format. Therefore in my program i have to do checking for the locale then convert the currency based on the language selected. I choose to use locale.setDefault() but i not sure whether this will has any risk or not based on below statement which i found. Can somebody advise for this?
Statement:
"Since changing the default locale may affect many different areas of functionality, this method should only be used if the caller is prepared to reinitialize locale-sensitive code running within the same Java Virtual Machine."
Thanks.
That warning means that if you've already had code that initialized based on a different locale, then it won't magically hear about the locale change and update. For example, if you already set up your title bar and menus and button labels in English and then call setDefault(Locale.GERMANY), all of the text will still be in English. Your example sounds like you won't be changing the locale after startup, so just make sure that you call setDefault early, before you do anything that depends on the locale.

Changing language without changing locale in JSF

I currently have a JSF application which sets the locale based on a user's choice of language. He gets a dropdown, and when choosing English, I set the locale to en, etc.
This works very nice with number formats as well as with the language strings loaded from my ResourceBundle.
So for en, I get English words and a . as decimal seperator.
For fr, I get French and a , as decimal seperator.
However, there is now a requirement that for this website, the number format must always have a , as decimal seperator. So, I was thinking to keep the locale fixed to fr.
Still the user must be able to change his language.
So, is it possible in JSF to load a different language without changing the locale?
Seams you need a special solution for formatting, so overwriting the formatters might be the better solution. I think JSF supports replacing the default number format.
Just explicitly specify the locale attribute of the <f:convertNumber> tags which you're using there.
E.g.
<f:convertNumber ... locale="fr" />
or something like
<f:convertNumber ... locale="#{app.defaultNumberLocale}" />
It would otherwise indeed default to UIViewRoot#getLocale(), as you're experiencing.
See also:
<f:convertNumber> tag documentation - read the locale attribute

Categories

Resources