jump to navigation

OK, so it WAS broken, and SHOULD have been fixed… November 7, 2008

Posted by globalizer in Java, Locales.
trackback

Here I complained about a seemingly wrongheaded change in the Java locale look-up algorithm. It turns out that the only change was to fix incorrect API docs. The original documentation described what everybody seems to agree is the desired behavior, but the APIs apparently were never implemented in that way. So, the docs were changed to describe the actual fallback behavior.

As described in the forum post linked above, in JDK 6 you can now get rid of the undesired behavior with ResourceBundle.Control.getNoFallbackControl().

It is still a mystery to me why the API was not changed to get the behavior that everybody agrees is more sensible, though. I certainly understand that API changes should not be undertaken lightly, in case you break previous implementations, but in this case I have a hard time seeing how anybody would rely on the existing behavior (and those would be easily fixable).

In any case, my previous post was wrong – I didn’t have all the old JDKs available to test, and relied on the documentation instead.

Advertisements

Comments»

1. yoshito - November 14, 2008

I think you misunderstand several things. First of all, the behavior of Java ResourceBundle has never changed since it was introduced. The order of bundle look up is –

Requested locale (language1, country1, variant1)
Default locale (language2, country2, variant2)

* baseName + “_” + language1 + “_” + country1 + “_” + variant1
* baseName + “_” + language1 + “_” + country1
* baseName + “_” + language1
* baseName + “_” + language2 + “_” + country2 + “_” + variant2
* baseName + “_” + language2 + “_” + country2
* baseName + “_” + language2
* baseName

See Java API references –

1.3.1 – http://java.sun.com/j2se/1.3/docs/api/java/util/ResourceBundle.html
1.4.2 – http://java.sun.com/j2se/1.4.2/docs/api/java/util/ResourceBundle.html#getBundle(java.lang.String,%20java.util.Locale,%20java.lang.ClassLoader)
5.0 – http://java.sun.com/j2se/1.5.0/docs/api/java/util/ResourceBundle.html#getBundle(java.lang.String,%20java.util.Locale,%20java.lang.ClassLoader)

And these old versions work as documented.

You also wrote
> It is still a mystery to me why the API was not changed to get the behavior that everybody agrees is more sensible

I do not think everybody agrees the behavior. In fact, I think you’re missing a point. If no default fallback is involved and always use a root bundle (bundle with no locale), the fallback behavior is determined by the application developer. However, the choice of application developer does not always match its user’s requirement. If the application provider package root bundle to include English contents, user cannot use any other languages as default fallback without repackaging the resource bundles.

You also said below in the previous blog post –
– I have xxx.properties including English contents
– I do not have xxx_en.properties
Here is a problem. If you support English locale in your app, you must provide xxx_en.properties even the contents is empty. Otherwise, Java runtime does not think your app supports English locale.

2. globalizer - November 14, 2008

No, I don’t think I have misunderstood anything. In my original post I stated that I have a hardcopy of the Java API docs for Java Standard Edition 1.2, and in that hardcopy the description is what I stated.

The forum post quoted stated that the API docs were corrected in the 1.3 version, which is the earliest one you quote.

With respect to what the desired behavior is: as I say, I personally have never met anybody who thinks the current behavior makes sense, since it basically prevents the provider of an application from providing consistent and predictable behavior.

Your last statement,
“If you support English locale in your app, you must provide xxx_en.properties even the contents is empty. Otherwise, Java runtime does not think your app supports English locale.”

is just bizarre. You are saying that if I want to support locale-based number formatting, for instance, I would need to provide a resource bundle for each locale that I want to support, otherwise the Java runtime will think all those locales are unsupported?

That is just plain wrong – Java doesn’t care which resource bundles are present or not in connection with locale support. Application resource bundles are purely used to provide a translated UI, that’s it. Other locale resources like number formatting, etc., are provided by Java, completely independent of what the application ships.

I have proven that many times by shipping applications with no resource bundles other than the root bundle, but with support for the scores of locales supported by Java (may be up to 100+ by now, I haven’t counted recently).

3. yoshito - November 14, 2008

> In my original post I stated that I have a hardcopy of the Java API docs for Java Standard Edition 1.2, and in that hardcopy the description is what I stated

I checked JDK 1.2 documentation – it’s same with JDK1.3. However, I also checked JDK1.1. It’s interesting that it put default locale inheritance chain after root bundle. So – both of us were wrong. This change was made between 1.1 and 1.2 at least in the API reference document. I did not check the behavior of JDK 1.1 although. (by the way, you can download old Java runtime/docs from archived area in java.sun.com)

>Application resource bundles are purely used to provide a translated UI, that’s it.

Yes, I agree to you with this point. And many application providers simply put English contents in root bundles. But my point is, why you think English is better fallback for Portuguese (when missing) over Spanish? It’s true many application providers assume English is the final default. But it should be what application users decide, not application provider. Application users can change default locale of the system and return French UI for any unsupported locale requests.

If you are application provider and want to force English as default fallback for unknown locale request, you can do whatever you want. ResourceBundle#getLocale returns the resolved locale. In fact, JSTL implementation does such thing, because it has to support Accept-Language header including multiple language tags with priorities.

4. globalizer - November 14, 2008

Ah, thx for checking – I have the 1.1 hardcopy, and the 1.2 “addition”, so I am really referring to 1.1.

About the fallback:
“But my point is, why you think English is better fallback for Portuguese (when missing) over Spanish? ”

Because that is what our customers want. And there is not doubt about it. Our customers in Portugal don’t even want to fall back to Brazilian Portuguese instead of European Portuguese, much less Spanish. So in this case we definitely know what our customers want, and that is English.

The problem with the default locale as fallback is that we then have to tell our customers that to get the correct fallback language for our application (English, in our case), they have to change the default locale of their systems. Which they obviously do not want to do, just to accomodate a single application. Unless we jump through hoops to work around the “wrong” fallback chain.

As Masayoshi pointed out in the forum there is a reasonable fix in 1.6.

5. yoshito - November 14, 2008

>As Masayoshi pointed out in the forum there is a reasonable fix in 1.6.

Yes. And if you want to do so, you can do it with Java 6. Java 6 ResourceBundle.Control opens up the control for developers to support any locale fallback behavior – for example, if someone request “ca” (Catalan) and resource is missing, you may want to return “es_ES” (Spanish – Spain) instead of root or default. This is pretty flexible framework.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: