| Writing Global Programs

## Loading Resource Bundles

> The AroundTheWorld program four resource bundles, all loaded by the LinguaPanel class.

> >     ResourceBundle labels = ResourceBundle.getBundle("LabelsBundle", locale);
> >     ResourceBundle paragraph = ResourceBundle.getBundle("ParagraphBundle", locale);
> >     ResourceBundle numbers = ResourceBundle.getBundle("NumbersBundle", locale);
> >     MediaBundle flagNSoundsBundle = (MediaBundle)ResourceBundle.getBundle(
> >                             "FlagNSoundsBundle", locale);

> The first three resources bundles loaded by in this code segment, `LabelsBundle`, `NumbersBundle`, and `FlagNSoundsBundle`, 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 `FlagNSoundsBundle`.

> 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.CANADA_FRENCH. 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.

> The AroundTheWorld program defines another version of LabelsBundle, the French language version, of LabelsBundle--LabelsBundle_fr. Note that this bundle is for the French language--it is not for a specific French-speaking country. You'll see why in a moment.

> LabelsBundle_fr is the same as LabelsBundle except that the values in LabelsBundle_fr have been translated into French. Note that the keys have not changed. The keys are used to look up values in the bundle. So, you must use the same keys for the same items in related ResourceBundles.

> When AroundTheWorld creates a LinguaPanel for Locale.FRANCE, `getBundle` searches first for LabelsBundle_fr_FR, which it doesn't find, then searches for, and finds, LabelsBundle_fr. Similarly, when looking for the French Canadian version of LabelsBundle, `getBundle` searches first for LabelsBundle_fr_CA, which it doesn't find, then searches for, and finds, LabelsBundle_fr. Thus the locales for France and French Canada use the same LabelsBundle class: LabelsBundle_fr. This is the proper design for LabelsBundle because the appropriate translations for the labels contained in LabelsBundle are the same for both locales.

> Try this: Figure out how the other two ListResourceBundles, NumbersBundle and FlagNSoundsBundle, 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.

> France and French Canada 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_fr_CA.properties` which gets loaded when the program creates the Locale.CANADA_FRENCH LinguaPanel.

| Writing Global Programs