Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ganesh_JavaSE7_Programming_1z0-804_study_guide.pdf
Скачиваний:
94
Добавлен:
02.02.2015
Размер:
5.88 Mб
Скачать

Chapter 12 Localization

 You create resource bundles by extending the ListResourceBundle class, whereas with PropertyResourceBundle, you create the resource bundle as property files. Furthermore, when extending­ ListResourceBundle, you can have any type of objects as values, whereas values in a properties file can only be Strings.

Loading a Resource Bundle

You’ve already loaded resource bundles in the programs you’ve written using ResourceBundle or its two derived classes. You need to understand this loading process thoroughly, and we’ll cover it in more detail in this section.

The process of finding a matching resource bundle is same for classes extended from ListResourceBundles as for property files defined for PropertyResourceBundles.

 For the resource bundles implemented as classes extended from ListResourceBundles, Java uses the reflection mechanism to find and load the class. You need to make sure that the class is public so that the reflection mechanism will find the class.

Naming Convention for Resource Bundles

Java enforces a predefined naming convention to be followed for creating resource bundles. Only through the names of the property bundles does the Java library load the relevant locales. Hence, it is important to understand and follow this naming convention when creating the property bundles for localizing Java applications.

You already saw how a locale name is encoded. Understanding this locale name encoding is important for naming the resource bundles because it makes use of the same encoding scheme. A fully qualified resource bundle has the following form:

packagequalifier.bundlename + "_" + language + "_" + country + "_" + (variant + "_#" | "#") + script + "-" + extensions

Here is the description of the elements in this fully qualified name:

packagequalifier: The name of the package (or the subpackages) in which the resource bundle is provided.

bundlename: The name of the resource bundle that you’ll use in the program to refer and load it.

language: A two-letter abbreviation typically given in lowercase for the locale’s language (in rare cases, it could be three letters as well).

country: A two letter abbreviation typically given in uppercase for the locale’s country (in rare cases, it could be three letters as well).

variant: An arbitrary list of variants (in lowercase or uppercase) to differentiate locales when you need more than one locale for a language and country combination.

We’ve omitted describing script and extension since they are rarely used.

372

Chapter 12 Localization

For example, consider this fully qualified name:

localization.examples.AppBundle_en_US_Oracle_exam

In this case, localization.examples is the package, AppBundle is the name of the resource bundle, en is language (which stands for English), US is the country, and Oracle_exam is the variant.

The two (or sometimes three) letter abbreviations for the locale’s language and country are predefined since they are based on international standards. We don’t provide the detailed list and there is also no need to know or remember all of them. You can look at the documentation of the Locale class to understand that.

 On the OCPJP 7 exam, you’re not expected to memorize language codes or country codes that are used for naming resource bundles. However, you are expected to remember the naming convention and recognize the constituents of a fully qualified resource bundle name.

Given that there could be many resource bundles for a bundle name, what is the search sequence to determine the resource bundle to be loaded? To clarify, we present the sequence as a series of steps. The search starts from Step 1. If at any step the search finds a match, the resource bundle is loaded. Otherwise, the search proceeds to the next step.

Step 1: The search starts by looking for an exact match for the resource bundle with the full name.

Step 2: The last component (the part separated by _) is dropped and the search is repeated with the resulting shorter name. This process is repeated till the last locale modifier is left.

Step 3: The search is restarted using the full name of the bundle for the default locale.

Step 4: Search for the resource bundle with just the name of the bundle.

Step 5: The search fails, throwing a MissingBundleException.

The search starts with the given locale details and if not found, proceeds with checking for default locale, as in:

BundleName + "_" + language + "_" + country + "_" + variant

BundleName + "_" + language + "_" + country

BundleName + "_" + language

BundleName + "_" + defaultLanguage + "_" + defaultCountry

BundleName + "_" + defaultLanguage

Consider an example to find out how the matching resource bundle is found, and it will become clear to you. Assume that you have the following five entries in the search path, and your default locale is US English.

 

ResourceBundle.properties

-- Global bundle

ResourceBundle_ar.properties

-- Arabic language bundle

ResourceBundle_en.properties

-- English bundle (assuming en_US is the default locale)

ResourceBundle_it.properties

-- Italian language bundle

ResourceBundle_it_IT_Rome.properties

-- Italian (Italy, Rome, Vatican) bundle

373

Chapter 12 Localization

 The getBundle() method takes a ResourceBundle.Control object as an additional parameter.

By extending this ResourceBundle.Control class and passing the instance of that extended class to the getBundle() method, you can change the default resource bundle search process or read from non-standard resource bundle formats (such as XML files).

So, you’ll extend this ResourceBundle.Control class and override the getCandidateLocales() method.

This is to programmatically list the candidate locales and finally display the matching locale. The program is given in Listing 12-7.

Listing 12-7.  CandidateLocales.java

import java.util.*;

//Extend ResourceBundle.Control and override getCandidateLocales method

//to get the list of candidate locales that Java searches for

class TalkativeResourceBundleControl extends ResourceBundle.Control {

//override the default getCandidateLocales method to print

//the candidate locales first

public List < Locale > getCandidateLocales(String baseName, Locale locale) { List < Locale > candidateLocales = super.getCandidateLocales(baseName, locale); System.out.printf("Candidate locales for base bundle name %s and locale %s %n", baseName, locale.getDisplayName());

for(Locale candidateLocale : candidateLocales) { System.out.println(candidateLocale);

}

return candidateLocales;

}

}

// Use a helper method loadResourceBundle to load a bundle given the bundle name and locale class CandidateLocales {

public static void loadResourceBundle(String resourceBundleName, Locale locale) {

//Pass an instance of TalkativeResourceBundleControl

//to print candidate locales

ResourceBundle resourceBundle = ResourceBundle.getBundle(resourceBundleName, locale, new TalkativeResourceBundleControl());

String rbLocaleName = resourceBundle.getLocale().toString();

//if the resource bundle locale name is empty,

//it means default property file if(rbLocaleName.equals("")) {

System.out.println("Loaded the default property file with name: " + resourceBundleName);

} else {

System.out.println("Loaded the resource bundle for the locale: " + resourceBundleName + "." + rbLocaleName);

}

}

374

Chapter 12 Localization

public static void main(String[] args) {

// trace how ResourceBundle_it_IT_Rome.properties is resolved loadResourceBundle("ResourceBundle", new Locale("it", "IT", "Rome"));

}

}

It prints the following:

Candidate locales for base bundle name ResourceBundle and locale Italian (Italy, Rome) it_IT_Rome

it_IT it

Loaded the resource bundle for the locale: ResourceBundle.it_IT_Rome

Now, before trying with other locales, consider how the program works. To trace how Java resolves the resource bundle to be finally loaded, you need to get the list of candidate locales. With the ResourceBundle.getBundle() method, you can pass an additional argument that is an instance of the ResourceBundle.Control class. For this reason, you define the TalkativeResourceBundleControl class.

The TalkativeResourceBundleControl class extends the ResourceBundle.Control class and overrides the getCandidateLocales() method. This getCandidateLocales() method returns a List < Locale > instance that contains the list of candidate locales for the given locale. You invoke super.getCandidateLocales() and traverse the resulting List < Locale > object to print the candidate locales so that you can examine the output

later. From this overridden getCandidateLocales() method, you simply return this List < Locale > object. So, the behavior of TalkativeResourceBundleControl is identical to ResourceBundle.Control except that the overridden getCandidateLocales() in TalkativeResourceBundleControl prints the candidate locales.

The CandidateLocales class makes use of the TalkativeResourceBundleControl. It has a helper method called loadResourceBundle() that takes the resource bundle name and the name of the locale as arguments. This method simply passes these argument values to the ResourceBundle.getBundle() method; additionally it instantiates TalkativeResourceBundleControl and passes that object as the third argument to this method. The getBundle() method returns a ResourceBundle object. If the locale of the ResourceBundle.getLocale() name is empty, it means Java has loaded the global resource bundle. (Remember that the global resource bundle for that bundle name does not have any associated locale details.) If the name of the locale is not empty, it means Java has resolved to that particular locale.

Now, consider the code in the main() method. It calls loadResourceBundle() for the locale it_IT_Rome. There are three candidate locales and of that it correctly loaded the matching property file for the locale it_IT_Rome. So you know that it loaded the property file ResourceBundle_it_IT_Rome.properties correctly.

To continue this experiment, let’s change the code inside the main() method of Listing 12-7 to this code:

loadResourceBundle("ResourceBundle", new Locale("fr", "CA", ""));

Now the program prints the following:

Candidate locales for base bundle name ResourceBundle and locale French (Canada) fr_CA

fr

Candidate locales for base bundle name ResourceBundle and locale English (United States) en_US

en

Loaded the resource bundle for the locale: ResourceBundle.en

375

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]