Previous | Next | Trail Map | Writing Java Programs | Writing Global Programs


What Are Locales and How Do I Use Them?

In JDK 1.1, a Locale(in the API reference documentation)object represents a specific locale (remember, a locale is a geographic or political region that shares the same language and customs). A Locale object is just an identifier for a region--it does not contain any application-specific data for that region.

For example, the AroundTheWorld program uses three Locale objects: one for the United States, one for France, and one for French Canada. These Locale objects do not contain the population, literacy rate, or any other AroundTheWorld specific data. The application-specific data is contained in resource bundles. The program uses a Locale object to identify what the current locale is and to decide which resource bundle to use to construct its display.

Let's take a look at the source code for AroundTheWorld. In particular, let's focus on the code that uses Locale objects. The IntlWindow class defines an array of Locales, called supportedLocales, which is created and initialized as follows:

private Locale supportedLocales[] = {
    Locale.US,
    Locale.FRANCE,
    Locale.CANADA_FRENCH
};
This array indicates the number of locales supported by the program and what those locales are. AroundTheWorld currently supports three locales--the United States, France, and French Canada--and uses three of the Locale class's convenient constants to create them.

The construct Locale.US is equivalent to:

new Locale("en", "US");
This particular Locale constructor requires two arguments: The language code and the country code for the Locale that you want to create.

The language codes are lower-case, two-letter codes defined by ISO-639. These codes should only be used programmatically. To display the language name to the user, use getDisplayLanguage. You can find a full list of language codes at a number of sites, such as: http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt

The country codes are upper-case, two-letter codes defined by ISO-3166. Again, these codes should only be used programmatically. To display the country name to the user, use getDisplayCountry. You can find a full list of these codes at a number of sites, such as: http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html

The Locale class has one other constructor that requires three arguments: The language code, the country code as before, and the variant code. For example, the following code snippet creates a California Locale object.

Locale califLocale = new Locale("en", "US", "california");

Note: The JDK does not support a California variant of the United States locale. If you tried to get a number formatter or other similar object for this locale, it will be suitable for the more general United States locale. For information about adding support for your own locales (such as the California locale), see [PENDING].

The variant codes are vendor and browser-specific. Use WIN for Windows, MAC for Macintosh, and POSIX for POSIX. Remember that if the Variant is not found, the more generic version will be used. That is, if you ask for "en", "US", "MAC", and there is no Macintosh version (the code may not even be running on a Macintosh), then "en", "US" will be used. Where there are two variants, separate them with an underscore, and put the most important one first. For example, a Traditional Spanish collation for Windows might be referenced, with "ES", "ES", "Traditional_WIN".

The JDK provides support for the following locales:
Locale Language Country
da_DK Danish Denmark
de_AT German Austria
de_CH German Switzerland
de_DE German Germany
el_GR Greek Greece
en_CA English Canada
en_GB English United Kingdom
en_IE English Ireland
en_US English United States
es_ES Spanish Spain
fi_FI Finnish Finland
fr_BE French Belgium
fr_CA French Canada
fr_CH French Switzerland
fr_FR French France
it_CH Italian Switzerland
it_IT Italian Italy
ja_JP Japanese Japan
ko_KR Korean Korea
nl_BE Dutch Belgium
nl_NL Dutch Netherlands
no_NO Norwegian (Nynorsk) Norway
no_NO_B Norwegian (Bokmål) Norway
pt_PT Portuguese Portugal
sv_SE Swedish Sweden
tr_TR Turkish Turkey
zh_CN Chinese (Simplified) China
zh_TW Chinese (Traditional) Taiwan

[PENDING: define exactly what supported means]

You can explicitly create a Locale object as shown above or you can get a Locale object from the application or from an AWT Component(in the API reference documentation). When an IntlWindow is first created, it uses its own Locale object to establish which locale is initially selected (and thus which flag is highlighted and which LinguaPanel is displayed):

private int selectedFlag = -1;

. . .

currentLocale = getLocale();

for (int i = 0; i < supportedLocales.length; i++) {
    if (currentLocale == supportedLocales[i])
        selectedFlag = i;
}

if (selectedFlag == -1) {
    currentLocale = supportedLocales[0];
    selectedFlag = 0;
}

Once you've got a Locale object, you can:

  1. get information from it about the locale
  2. pass it to other objects that perform Locale-Sensitive Operations

Getting Information from a Locale

The Locale class provides a number of "getter" methods for retrieving information about the locale: getCountry, getLanguage, getDisplayLanguage to name a few.

The AroundTheWorld program uses Locale's getDisplayName method to provide a unique name for each LinguaPanel to the CardLayout layout manager:

cards.add(supportedLocales[i].getDisplayName(), linguaPanel);
The CardLayout layout manager uses this name to show the correct LinguaPanel based on the currently selected locale:
((CardLayout)cards.getLayout()).show(cards, currentLocale.getDisplayName());
This form of getDisplayName returns the name of the locale in the language of application's default locale. The Locale class provides a locale-sensitive version of getDisplayName which the LinguaPanel uses to display the name of the currently selected locale to the user in the language of the currently selected locale:
localeValue.setText(locale.getDisplayName(locale));

Locale-Sensitive Operations

AroundTheWorld uses an array of Locale objects to identify the locales that it supports. The program also uses locales to inform locale-sensitive operations (such as constructing the LinguaPanels, and loading resource bundles) which locale to use.

For example, look at the code in IntlWindow that creates the LinguaPanels:

// create a card panel
    cards = new Panel();
    cards.setLayout(new CardLayout());

// create the LinguaPanels that go into the card layout
    for (int i = 0; i < supportedLocales.length; i ++) {
        LinguaPanel linguaPanel = null;
        try {
            linguaPanel = new LinguaPanel(supportedLocales[i], inAnApplet,
                                  defaultFont, boldFont, soundImages, soundNames);
        } catch (java.util.MissingResourceException e) {
            System.out.println("Couldn't load resource(s).");
        }

        // add it to the card layout
        cards.add(supportedLocales[i].getDisplayName(), linguaPanel);
    }

// add the card layout to this window
    add("Center", cards);
This code snippet steps through the supportedLocales array and creates one LinguaPanel for each supported locale. Because the creation of a LinguaPanel is locale-sensitive (it displays text and numbers and other language-dependent elements) its constructor requires a Locale object as an argument. What does LinguaPanel do with its Locale object? Let's check it out.

The first thing locale-sensitive operation the LinguaPanel constructor does is load resource bundles based on the locale argument. These resource bundles contain text and numbers specific to the locale. Resource bundles are covered in the next section: Managing Locale-Senitive Data.

LinguaPanel also uses the Locale object to get date, number, currency and number formatters appropriate for the locale. Formatting is covered along with data parsing in Formatting and Parsing.


Previous | Next | Trail Map | Writing Java Programs | Writing Global Programs