Home > Java > Bugs in Java 7 Locale or ResourceBundle?

Bugs in Java 7 Locale or ResourceBundle?

September 18th, 2011 joconner Leave a comment Go to comments

While working on a chapter in an upcoming APress book, I was experimenting with Java 7′s Locale and ResourceBundle classes. Java 7 introduces two new Locale categories: DISPLAY and FORMAT. You can set the default locale for localizable user interface resources independently from the default locale for data Format subclasses. For example, you supposedly can set up a DISPLAY locale to display Spanish (es) resources for the user interface text but use American English (en-US) for date formats.

This does seem to work correctly the first time you load a ResourceBundle, but subsequent calls to getBundle seem to get stuck with previous DISPLAY locale settings. For example, take a look at the following code:


public void setCategoryDefaultLocale(Locale displayLocale, Locale formatLocale) {
    Locale.setDefault(Locale.Category.DISPLAY, displayLocale);
    Locale.setDefault(Locale.Category.FORMAT, formatLocale);   
}

public void demoDefaultLocaleSettings() {
    DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT,
        DateFormat.SHORT);
    ResourceBundle resource = ResourceBundle.getBundle("mypackage.resource.SimpleResources");
    String greeting = resource.getString("GOOD_MORNING");
    String date = df.format(NOW);
    System.out.printf("DISPLAY LOCALE: %s\n",
        Locale.getDefault(Locale.Category.DISPLAY));
    System.out.printf("FORMAT LOCALE:  %s\n",
        Locale.getDefault(Locale.Category.FORMAT));
    System.out.printf("%s, %s\n\n", greeting, date );
    ResourceBundle.clearCache();   
}

Now I call the two methods above in succession:


setCategoryDefaultLocale(Locale.forLanguageTag("es-MX"), Locale.US);
demoDefaultLocaleSettings();
setCategoryDefaultLocale(Locale.US, Locale.forLanguageTag("es-MX"));
demoDefaultLocaleSettings();

In the following output, notice that the first call to demoDefaultLocaleSettings does actually grab the es-MX resources for the DISPLAY locale, and it formats the NOW date using the en-US FORMAT locale. That’s exactly what I’d expect. However, the subsequent call (even after flushing the ResourceBundle cache), still loads the es-MX resources despite the explicit request for en-US resources. I expected that ResourceBundle would have loaded and retrieved “Good morning!” after the second call to setCategoryDefaultLocale.


DISPLAY LOCALE: es_MX
FORMAT LOCALE:  en_US
¡Buenos días!, 9/18/11 1:59 AM

DISPLAY LOCALE: en_US
FORMAT LOCALE:  es_MX
¡Buenos días!, 18/09/11 01:59 AM

I suspect that the real problem isn’t in the Locale.setDefault methods. Instead, I’m going to blame ResourceBundle for this until I can prove otherwise.

If you’ve seen this in the past, let me know. I’m coming up empty for now trying to resolve why I don’t get U.S. English in the second call. Let me know if you know anything about this! Maybe a bug? Maybe user error?

VN:F [1.9.22_1171]
Rating: 0.0/5 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)
Be Sociable, Share!
Categories: Java Tags: ,
  1. naoto
    September 18th, 2011 at 08:34 | #1

    Hi John,

    Thank you for your write ups! I am now traveling (actually I am in Irvine, close to you!) so I cannot try it myself, but I believe the ResourceBundle is working correctly. Its getBundle method (without locale instance) loads the resource for the default locale, i.e., Locale.getDefault() value, which won’t be affected by Locale.setDefault(Locale.Category, Locale) invocation.

    HTH, Naoto

    VA:F [1.9.22_1171]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
  2. joconner
    September 18th, 2011 at 11:24 | #2

    @naoto
    Thanks Naoto, but what is the purpose then of Locale.setDefault(Locale.Category.DISPLAY, aLocale)? My first call to resource bundle does seem to load the es-MX resources:
    ResourceBundle resource = ResourceBundle.getBundle(“mypackage.resource.SimpleResources”);

    The second call (after I’ve set the default to en-US for DISPLAY), continues to load the es-MX resources. How is the Category.DISPLAY supposed to affect resource bundles?

    VA:F [1.9.22_1171]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
  3. naoto
    September 18th, 2011 at 19:18 | #3

    ResourceBundle is not necessarily related to DISPLAY locale because it’s up to application’s design. Some apps want to load resources that are FORMAT related. So the default behavior just relies on Locale.getDefault().

    Having said that, I’d modify your example to ResourceBundle.getBundle(“mypackage…”, Locale.getDefault(Locale.Category.DISPLAY)) as you *already know* that the resource is DISPLAY related.

    Locale.setDefault(Category) affects the behavior of the locale sensitive services that explicitly relate to user visible display, such as the locale names for user display, i.e., Locale.getDisplayName().

    VA:F [1.9.22_1171]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
  4. joconner
    September 18th, 2011 at 21:13 | #4

    @naoto
    I guess the point of the categories is completely lost on me. I thought the point was to be able to setDefault(category, alocale) and thereafter anything that depended on a default would use the defaults set from the setDefault call. That makes sense to me. But I think you are saying something very different. From the documentation, I interpreted that resource bundles would be related to the DISPLAY locale and Format subclasses would be related to the FORMAT locale. I think I’ve interpreted incorrectly.

    VA:F [1.9.22_1171]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
  5. naoto
    September 18th, 2011 at 22:19 | #5

    Hmm, can you let me know which document made you interpret that resource bundles would be related to the DISPLAY locale?

    VA:F [1.9.22_1171]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
  6. Erivando Nogueira
    March 22nd, 2013 at 10:40 | #6

    I had a problem with it.
    I’ve been doing a program for jre 1.6 and 1.7. My solution was:
    first check the version of jre;

    if the Java 6, use

    Locale.getDefault (); or
    new Locale (System.getProperty (“user.language”)
    System.getProperty (“user.country”))

    if the Java 7, use

    new Locale (System.getProperty (“user.language.format”)
    System.getProperty (“user.country.format”))

    VA:F [1.9.22_1171]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
  1. No trackbacks yet.