I am setting up ResourceBundle and I am getting strange results that are against Oracle documentation. https://docs.oracle.com/cd/E23095_01/Platform.93/ATGProgGuide/html/s1804resourcebundleinheritance01.html

I have 3 files:

Animals_fr.properties

name=animals_fr

Animals_en.propertis

name=animals_en
age=5

Animals.properties

name=animals
age=0

Then I have the code:

Locale localeFr = new Locale("fr");
Locale.setDefault(new Locale("en","US"));
ResourceBundle b = ResourceBundle.getBundle("Animals", localeFr);
System.out.println(b.getString("name"));
System.out.println(b.getString("age"));

Based on the Oracle documentation inheritance should be like this:

Animals_fr - locale bundle
Animals_en - default locale bundle
Animals - default bundle

and the result should be :

animals_fr
5

But I am getting result:

animals_fr
0

Any ideas what is wrong?

Thanks

1 Answers

1
Holger On Best Solutions

The document, you’ve linked, describes how a resource bundle is looked up, rather than how a single resource key will be resolved.

This matches the documented default behavior, which says

If the specified locale's language, script, country, and variant are all empty strings, then the base name is the only candidate bundle name. Otherwise, a list of candidate locales is generated from the attribute values of the specified locale (language, script, country and variant) and appended to the base name.

which describes how a single Locale leads to a sequence of candidate names. In your case, it would be just [ Animal_Fr ]. Then, it says:

This continues until a result resource bundle is instantiated or the list of candidate bundle names is exhausted. 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.

So, if Animal_Fr did not exist, it did fall back to the default locale, trying with a candidate sequence of [ Animals_en_US, Animals_en ].

But since Animal_Fr does exist and can be instantiated, this lookup will not continue. Rather, for looking up a particular resource key, the chaining becomes relevant, which is documented as:

Once a result resource bundle has been found, its parent chain is instantiated. If the result bundle already has a parent (perhaps because it was returned from a cache) the chain is complete.

Otherwise, getBundle examines the remainder of the candidate locale list that was used during the pass that generated the result resource bundle. […] When it comes to the end of the candidate list, it tries the plain bundle name. With each of the candidate bundle names it attempts to instantiate a resource bundle […].

Whenever it succeeds, it calls the previously instantiated resource bundle's setParent method with the new resource bundle. This continues until the list of names is exhausted or the current bundle already has a non-null parent.

So the linked document is right regarding the overall behavior of getBundle, which is the result of the two-step process described in the documentation. But when it comes to the parent chain, which is relevant for the behavior of getString, only the candidate list of the current lookup phase will be used.

So, depending on which actual bundles do exist, it may end up with either

Animals_fr ‣ Animals

or

Animals_en_US ‣ Animals_en ‣ Animals

in your example setup.