Previous | Next | Trail Map | Writing Global Programs | Locale-Sensitive Data


Loading Resource Bundles

A resource bundle is really a set of related classes that inherit from ResourceBundle. These related classes are called a resource bundle family. Each family of resource bundles has the same base name plus an additional component that identifies its locale.

One of AroundTheWorld's resource bundle families is the LabelsBundle family. This family of bundles contains the labels used to identify the various data items (Locale Name, Time, Date and so on). Because AroundTheWorld supports three different locales, it requires three different versions of LablesBundle. The first is the default resource bundle which simply has the same name as its family--LabelsBundle. In AroundTheWorld the default LabelsBundle contains the locale-specific information for the United States simply because the author of the program is American. However, any default data will do. In addition to the default LabelsBundle, AroundTheWorld has two more: LabelsBundle_fr, and LabelsBundle_en_UK. The LabelsBundle component of the classname identifies these two classes as members of the LabelsBundle family. The _fr and _en_UK components of the classname identify the locale. _fr indicates that the data is appropriate for a French speaking locale (any country) and _en_GB indicates that the data is appropriate specifically for the United Kingdom locale.

Each related subclass of ResourceBundle contains the same items, but the items have been translated for the locale represented by that ResourceBundle subclass. For example, both LabelsBundle and LablesBundle_fr have a LocaleLabel item. In LabelsBundle the LocaleLabel item is "Locale:" and in LocaleLabel item it contains a string awaiting translation.

You'll note that the United States and the United Kingdom can share some items (the phrase "Literacy Rate" is the same in both countries) but not others (the representative city for the US is San Francisco but for the UK it's London). In this case, the bundle need only contain specializations for those items that are different (LablesBundle_en_GB only contains the RepCity and TimeZone items).

Along with LabelsBundle, the AroundTheWorld program has three other resource bundle families all loaded by the LinguaPanel class with this code:

ResourceBundle labels = ResourceBundle.getBundle("LabelsBundle", locale);
ResourceBundle paragraph = ResourceBundle.getBundle("ParagraphBundle", locale);
ResourceBundle numbers = ResourceBundle.getBundle("NumbersBundle", locale);
ResourceBundle soundBundle = ResourceBundle.getBundle("SoundBundle", locale);
Three of the bundles, LabelsBundle, NumbersBundle, and SoundBundle, are all subclasses of ListResourceBundle. ParagraphBundle is a PropertyResourceBundle. Let's first investigate loading the list resource bundles. We'll look at the properties bundle later.

The first argument to ResourceBundle.getBundle is the bundle name. This argument must be the fully qualified name of the base resource bundle class. Thus, it must include the full package name as well as the classname: myPackage.MyResources. Each of AroundTheWorld's resource bundles live in the default package, so in this case, the classname is the fully qualified name for each bundle: LabelsBundle, NumbersBundle, and SoundBundle.

Loading a resource bundle via getBundle is a locale-sensitive operation. Thus, the second argument to getBundle is a locale. getBundle uses this locale object to identify which version of the resource bundle to load.

To find the correct, locale-specific, resource bundle, getBundle builds variations of the bundle name until it finds the name of a class that can be loaded. The series of names looks like this:

bundleName + "_" + localeLanguage + "_" + localeCountry + "_" + localeVariant 
bundleName + "_" + localeLanguage + "_" + localeCountry 
bundleName + "_" + localeLanguage 
bundleName + "_" + defaultLanguage + "_" + defaultCountry + "_" + defaultVariant 
bundleName + "_" + defaultLanguage + "_" + defaultCountry 
bundleName + "_" + defaultLanguage 
bundleName
where localeLanguage, localeCountry and localeVariant are taken from the locale specified in the getBundle call. defaultLanguage, defaultCountry and defaultVariant are taken from the default locale. As you can see, the resource bundle named bundleName is the bundle of last resort and contains the values to be used if a version of the bundle is not available for a specific locale. If no ResourceBundle subclass can be found, getBundle throws a MissingResourceException.

Typically, a program provides a default bundle for each of its resource bundles. The default bundle contains the full set of key-value pairs in the bundle. Thus, people performing the localization on the bundle have all the information required.

Let's watch how LabelsBundle is loaded into AroundTheWorld. As you know, AroundTheWorld creates one LinguaPanel per supported locale. Thus, it creates three LinguaPanels, one each for Locale.US, Locale.FRANCE, and Locale.UK. Upon construction each locale-specific LinguaPanel loads a locale-specific version of LabelsBundle.

For example, when AroundTheWorld creates a LinguaPanel for Locale.US, getBundle searches first for LabelsBundle_en_US. This search is in vain because there is no LabelsBundle_en_US class. Then getBundle searches for LabelsBundle_en (again in vain), and finally it searches for and finds LabelsBundle. The LabelsBundle class is the default bundle and contains English versions of the strings appropriate for the US. Thus it was not necessary to provide another LabelsBundle specifically for the US.


Try this: Figure out how the French and UK LabelsBUndle are loaded. Also look at how the NumbersBundles and SoundBundles are loaded.

If the bundle in question is a properties bundle, such as ParagraphBundle in the AroundTheWorld program, getBundle creates a PropertyResourceBundle and initializes it with the information from a properties file. getBundle derives the name of the properties file in the same manner as it derives resource bundle class names.

To recap: To find the correct, locale-specific, properties file when loading a PropertyResourceBundle, getBundle builds variations of the bundle name until it finds the name of a properties file that can be loaded. As with classnames, the series of property filenames looks like this:

bundleName + "_" + localeLanguage + "_" + localeCountry + "_" + localeVariant 
bundleName + "_" + localeLanguage + "_" + localeCountry 
bundleName + "_" + localeLanguage 
bundleName + "_" + defaultLanguage + "_" + defaultCountry + "_" + defaultVariant 
bundleName + "_" + defaultLanguage + "_" + defaultCountry 
bundleName + "_" + defaultLanguage 
bundleName
The properties file has a .properties extension.

When AroundTheWorld creates the LinguaPanel for Locale.US, it searches first for ParagraphBundle_en_US.properties, which it doesn't find, then for ParagraphBundle_en.properties, which again it doesn't find, and then finally for ParagraphBundle.properties, which it does find. As with LabelsBundle, default data is contained in this resource bundle. Because the default contains the information for the United States, a specific US version of this bundle is not necessary.

The French ParagraphBundle properties file is called ParagraphBundle_fr.properties. Again, only the values (not the keys) are translated into another language. This properties file is loaded into the PropertyResourceBundle when AroundTheWorld creates the Locale.FRANCE LinguaPanel.

The United States and the Untied Kingdom cannot share ParagraphBundles because the paragraph provides a description of the locale. The language that the paragraphs are written in is the same for each locale. However, the contents are different. Thus AroundTheWorld must provide a third file ParagraphBundle_en_GB.properties which gets loaded when the program creates the Locale.UK LinguaPanel.


Previous | Next | Trail Map | Writing Global Programs | Locale-Sensitive Data