6
votes

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

2
Did you try setting up an English locale?Lenymm
Ok, I figured out what happens in that method: - First, the bundles of the provided locale ("en_US" and then "en") are checked - If they're not available, the default locale of the system (here French) is used - And finally, if none is found, the bundle file with the base name (ie w/o any language nor country code) is used So even if I can keep my resources.properties file as default, I should copy it to a resources_en.properties file in order to avoid having the system locale (fr) being used.Stéphane Wantiez
Good job figuring that out for yourself. Make sure to read the link bellow if you got any further questions.Lenymm

2 Answers

0
votes

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.

4
votes

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.