The Java I18N and L10N API


The primary I18N and L10N Java APIs can be found in the java.util and java.text packages. This section shows some of the commonly used classes and their functions. Figure 8.1 shows the classes in the Java I18n API. If you are already familiar with the Java Internationalization API, you can skip this section and proceed to the next section.


Figure 8.1: TheI18n classes provided by the Java Internationalization API

java.util.Locale

The Locale class represents a specific geographical or cultural region. It contains information about the region and its language and sometimes a variant specific to the user ‚ s system. The variant is vendor specific and can be WIN for a Windows system, MAC for a Macintosh etc. The following examples show you how to create a Locale object for different cases:

A Locale object that describes only a language (French):

 Locale frenchSpeakingLocale = new Locale("fr", ""); 

A Locale object that describes both the spoken language and the country (French Canada):

 Locale canadaLocale = new Locale("fr", "CA"); 

A Locale object that describes the spoken language, country and a variant representing the user ‚ s operating system (French Canada and Windows Operating system):

 Locale canadaLocaleWithVariant = new Locale("fr", "CA", "WIN"); 

Accessing Locale in Servlet Container

On every request the client ‚ s locale preference is sent to the web server as part of the HTTP Header. The ‚“Accept-Language ‚½ header contains the preferred Locale or Locales. This information is also available to the servlet container and hence in your web tier through the HttpServletRequest . ServletRequest , the interface that HttpServletRequest extends defines the following two methods to retrieve Locale

 public java.util.Locale getLocale(); public java.util.Enumeration getLocales(); 

The second method contains a set of Locales in the descending order of preference. You can set the request ‚ s Locale preference in the browser. For instance in Internet Explorer, you can add, remove or change the Locales using Tools (Internet Options (Languages.

The < controller > ( RequestProcessor ) setup in the Struts Config file has a locale attribute. If this is set to true, then Struts retrieves the Locale information from the request only the first time and stores it in the HttpSession with the key org.apache.struts.action.LOCALE (Don ‚ t get confused . This is not a class name . It is the actual String used as the Session key.) The default value of the locale attribute is false for which Struts does not store the Locale information in the HttpSession .

A tip from usability perspective: Although it is possible to change the Locale preference from the browser, I18N usability experts suggest that it might still be valuable to explicitly provide the choice to the users and let them decide. Every web site has a navigation bar or menu or something of that sort . You can provide a HTML choice or drop down to let the user ‚ s choose the Locale that shall override all other settings. This is easy from a Struts perspective because the Locale from the HttpServletRequest can be overridden with the setting in the HttpSession and Struts will never bother about the request header.

java.util.ResourceBundle

ResourceBundle is an abstract base class that represents a container of resources. It has two subclasses: ListResourceBundle and PropertiesResourceBundle . When you are localizing your application, all the locale specific resources like text-messages, icons and labels are stored in subclasses of the ResourceBundle . There will be one instance of the ResourceBundle per locale. The getBundle() method in this class retrieves the appropriate ResourceBundle instance for a given locale. The location of the right bundle is implemented using an algorithm explained later.

Let us see how a resource bundle instance is retrieved with a simple example. Consider a custom ResourceBundle subclass called MybankResources that will contain data specific to your application. In this example, you will see how to use PropertyResourceBundles assuming that all the resources to be localized are strings. In order to use PropertyResourceBundle , you will have to create Java Properties files that will hold the data in key = value format. The file name itself identifies the Locale. For instance, if MybankResources.properties contains strings to be localized for the language English in the United States (en_US), then MybankResources_fr_FR..properties contains strings to be localized for the language ‚“fr ‚½ (French) and region of ‚“FR ‚½ (France). In order to use the data in these files, you have to get the ResourceBundle instance as shown in Listing 8.1.

Listing 8.1: Extracting data from a ResourceBundle
 Locale myLocale = new Locale("fr","FR");   // Get the resource bundle for myLocale  ResourceBundle mybankBundle = ResourceBundle.getBundle(   "MybankResources",   myLocale);  // Get the localized strings from this resource bundle   String myHeader =  mybankBundle.getString("header.title");  System.out.println(myHeader); 
 

In order to understand Listing 8.1, assume that the English properties file, MybankResources.properties contains a key value pair: header.title=My Bank. Next assume that the French properties file, MybankResources_fr_FR.properties also contains a key value pair: header.title= Ma Banque . The code snippet in Listing 8.1 produces an output ‚“Ma Banque ‚½. What happens if the MybankResources_fr_FR.properties file was missing? Just to see what happens, rename the file to something else and run the program again. This time the output will be My Bank . But the locale was ‚“fr_FR ‚½!

Here ‚ s what happened . Because the locale was ‚“fr_FR ‚½, the getBundle() method looked up MybankResources_fr_FR.properties . When it did not find this file, it looked for the ‚“next best match ‚½ MybankResources_fr.properties . But this file doesn ‚ t exist either. Finally the getBundle() found the MybankResources.properties file and returned an instance of PropertiesResourceBundle for this file. Accordingly the String myHeader is looked up using the header.title key from the MybankResources.properties file and returned to the user. In general, the algorithm for looking up a Properties file is:

 MybankResources  _   language_country_variant   .  properties   MybankResources  _   language_country  .properties   MybankResources  _   language  .properties   MybankResources.properties 

Java Properties files are commonly used for web tier localization in Struts web applications. Hence we have shown you how to use them for localizing string data. If your requirement involves extracting locale specific resources besides strings, you might want to use the ListResourceBundle class.

Note ‚  

When the above program runs from the command line, the properties file is located and loaded by the default command line class loader ‚ the System Classpath Class Loader. Similarly in a web application, the properties file should be located where the web application class loader can find it.

java.text.NumberFormat

NumberFormat is an abstract base class that is used to format and parse numeric data specific to a locale. This class is used primarily to format numbers and currencies. A sample example that formats currencies is shown in Listing 8.2. A currency format for French Locale is first obtained. Then a double is formatted and printed using the currency format for French Locale. The output is: Salary is: 5 ‚  124,75

Listing 8.2: Formatting currencies using NumberFormat
 Locale frLocale = new Locale ("fr","FR");    // get instance of NumberFormat NumberFormat currencyFormat =        NumberFormat.getCurrencyInstance(frLocale); double salaryAmount = 5124.75; // Format the amount for the French locale String salaryInFrench = currencyFormat.format(salaryAmount); System.out.println ("Salary is: " + salaryInFrench); 
 

In the above example, the double amount was hard coded as a decimal in en_US format and printed as in the French format. Sometime you will have to do the reverse while processing user input in your web applications. For instance, a user in France enters a currency in the French format into a text field in the web application and you have to get the double amount for the business logic to process it. The NumberFormat class has the parse() method to do this. Listing 8.3 shows this. The output of the program is: Salary is: 5124.75

Listing 8.3: Formatting currencies using NumberFormat
 // get the amount from a text field (5124,75) String salaryInFrench = salaryField.getText(); // Print it back into a regular number System.out.println("Salary is: " +       CurrencyFormat.parse(salaryInFrench); 
 

There is a subclass of the NumberFormat called DecimalFormat that can be used to format locale specific decimal numbers with the additional capability of providing patterns and symbols for formatting. The symbols are stored in a DecimalFormatSymbols . When using the NumberFormat factory methods, the patterns and symbols are read from localized resource bundles.

java.text.DateFormat

DateFormat is an abstract class that is used to format dates and times. When a locale is specified it formats the dates accordingly. The following code formats a date independent of locale

 Date now = new Date();    String dateString = DateFormat.getDateInstance().format(now); 

To format a date for a given locale:

 DateFormat dateFormat =        DateFormat.getDateInstance(Locale.GERMANY);    dateFormat.format(now); 

java.text.MessageFormat

MessageFormat is used to create concatenated messages in a language neutral way. It takes a set of input objects, formats them and inserts the formatted strings into specific places in a given pattern. Listing 8.4 shows how to create a meaningful message by inserting string objects into specific locations in the already existing message. When you run the program, you will get the following output: John Doe logged in at 8/28/03 2:57 PM

Listing 8.4: Using MessageFormat to create message
 Object[] myObjects = { "John",                        "Doe",                 new java.util.Date(System.currentTimeMillis())                       }; String messageToBeDisplayed = "{0} {1} logged in at {2}"; String message =  java.text.MessageFormat.format(messageToBeDisplayed, myObjects); System.out.println(message); 
 



Struts Survival Guide. Basics to Best Practices
Struts Survival Guide: Basics to Best Practices (J2ee Survival Series)
ISBN: 0974848808
EAN: 2147483647
Year: 2004
Pages: 96

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net