Skip Headers
Oracle® Application Development Framework Developer's Guide
10g Release 3 (10.1.3)
B25386-01
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

14.4 Internationalizing Your Application

When your application will be viewed by users in more than one country, you can configure your application to different locales so that it displays the correct language for the language setting of a user's browser. For example, if you know your application will be viewed in Germany, you can localize your application so that when a user's browser is set to use the German language, text strings in the application will appear in German.

ADF Faces components provide automatic translation. The resource bundle used for the components' skin (which determines look and feel, as well as the text within the component) is translated into 28 languages. If a user sets the browser to use the German (Germany) language, any text contained within the components will automatically display in German. For more information on skins and this resource bundle, see Section 14.3.1, "How to Use Skins". For a complete list of all text included in ADF Faces components, see the "Reference: Keys for Resource Bundle Used by Skins" topic of the JDeveloper online help.

For any text you add to the application, you need to provide a resource bundle that holds the actual text, and load that bundle into the page using the JSF loadBundle tag. Then, instead of directly entering the text on the JSF page or entering the text as a value for the Text attribute of an object, you bind that attribute to a key in the resource bundle. You then create a version of the resource bundle for each locale.


Note:

Any text retrieved from the database is not translated. This document covers how to localize static text, not text that is stored in the database.

Figure 14-5 shows the SRList page from the SRDemo application in a browser set to use the English (United States) language.

Figure 14-5 The SRList Page in English

The SRList page displays all text in English by default.

Although the title of this page is "My Service Requests," instead of having "My Service Requests" as the value for the title attribute of the PanelPage component, the value is bound to a key in a resource bundle. The UIResources resource bundle is loaded into the page using the loadBundle tag, as shown in Example 14-7. The resource bundle is given a variable name (in this case res) that can then be used in EL expressions. The title attribute of the panelPage component is then bound to the srlist.pageTitle key in that resource bundle.

Example 14-7 Resource Bundles Used in a JSF Page

<f:view>
  <f:loadBundle basename="oracle.srdemo.view.resources.UIResources"
                  var="res"/>
  <af:document title="#{res['srdemo.browserTitle']}"
               initialFocusId="viewButton">
    <af:form>
      <af:panelPage title="#{res['srlist.pageTitle']}">

The UIResources resource bundle has an entry in the English language for all static text displayed on each page in the SRDemo application, as well as text for messages and global text, such as generic labels. Example 14-8 shows the keys for the SRList page.

Example 14-8 Resource Bundle Keys for the SRList Page Displayed in English

#SRList Screen
srlist.pageTitle=My Service Requests
srlist.menubar.openLink=Open Requests
srlist.menubar.pendingLink=Requests Awaiting Customer
srlist.menubar.closedLink=Closed Requests
srlist.menubar.allRequests=All Requests
srlist.menubar.newLink=Create New Service Request
srlist.selectAnd=Select and 
srlist.buttonbar.view=View
srlist.buttonbar.edit=Edit
srlist.buttonbar.assign=Assign

Figure 14-6 also shows the SRList page, but with the browser set to use the German (Germany).

Figure 14-6 The SRList Page in German

SRList page using the German locale displays text in German

Note:

The column headings were not translated because the values are bound to the label property of the binding object. This value is set as a control hint in the entities structure XML file. Whenever any values are set for the label, a resource bundle is automatically created. To translate these, you must create localized versions of these resource bundles.

Example 14-9 shows the resource bundle version for the German (Germany) language, UIResource.de. Note that there is not an entry for the selection facet's title, yet it was translated from "Select" to "Auswahlen" automatically. That is because this text is part of the ADF Faces table component's selection facet.

Example 14-9 Resource Bundle Keys for the SRList Page Displayed in German

#SRList Screen
srlist.pageTitle=Meine Service Anfragen
srlist.menubar.openLink=Offene Anfragen
srlist.menubar.pendingLink=Anfrage wartet auf Kunden
srlist.menubar.closedLink=Geschlossene Anfragen
srlist.menubar.allRequests=Alle Anfragen
srlist.menubar.newLink=Erstelle neue Service Anfrage
srlist.selectAnd=Kommentare wählen und
srlist.buttonbar.view=Ansich

The resource bundles for the application can be either Java classes or property files. The abstract class ResourceBundle has two subclasses: PropertyResourceBundle and ListResourceBundle. A PropertyResourceBundle is stored in a property file, which is a plain-text file containing translatable text. Property files can contain values only for String objects. If you need to store other types of objects, you must use a ListResourceBundle instead. The contents of a property file must be encoded as ISO 8859-1. Any characters not in that character set must be stored as escaped Unicode.

To add support for an additional locale, you simply replace the values for the keys with localized values and save the property file appending a language code (mandatory), and an optional country code and variant as identifiers to the name, for example, UIResources_de.properties. The SRDemo application uses property files.


Note:

Property files must contain characters in the IS0 8859-1 character set. If you need to use other characters, use a ListResourceBundle class instead.

All non-8859-1 character sets must be converted to escaped UTF-8 characters, or they will not display correctly.


The ListResourceBundle class manages resources in a name, value array. Each ListResourceBundle class is contained within a Java class file. You can store any locale-specific object in a ListResourceBundle class. To add support for an additional locale, you subclass the base class, save it to a file with an locale / language extension, translate it, and compile it into a class file.

The ResourceBundle class is flexible. If you first put your locale-specific String objects in a PropertyResourceBundle file, you can still move them to a ListResourceBundle class later. There is no impact on your code, since any call to find your key will look in both the ListResourceBundle class as well as the PropertyResourceBundle file.

The precedence order is class before properties. So if a key exists for the same language in both a class file and in a property file, the value in the class file will be the value presented to the user. Additionally, the search algorithm for determining which bundle to load is as follows:

  1. (baseclass)+(specific language)+(specific country)+(specific variant)

  2. (baseclass)+(specific language)+(specific country)

  3. (baseclass)+(specific language)

  4. (baseclass)+(default language)+(default country)+(default variant)

  5. (baseclass)+(default language)+(default country)

  6. (baseclass)+(default language)

For example, if a user's browser is set to the German (Germany) locale and the default locale of the application is US English, the application will attempt to find the closest match, looking in the following order:

  1. de_Germany

  2. de

  3. en_US

  4. en

  5. The base class bundle


Tip:

The getBundle method used to load the bundle looks for the default locale classes before it returns the base class bundle. If it fails to find a match, it throws a MissingResourceException error. A base class with no suffixes should always exist in order to avoid throwing this exception

14.4.1 How to Internationalize an Application

To internationalize your application, you need to do the following:


Tip:

These procedures will allow the application to display the correct language based on the browser settings of the user. You may also want to create your application in a way that allows the user to manually set the locale they wish to use. The current locale is stored in the viewRoot of FacesContext.

  1. Create a base resource bundle that contains all the text strings that are not part of the components themselves. This bundle should be in the default language of the application.


    Tips:

    • Instead of creating one resource bundle for the entire application, you can create multiple resource bundles. For example, in a JSF application, you must register the resource bundle that holds error messages with the application in the faces-config.xml file. For this reason, you may want to create a separate bundle for messages.

    • Create your resource bundle as a Java class instead of a property file if you need to include values for objects other than Strings, or if you need slightly enhanced performance.

    • The getBundle method used to load the bundle looks for the default locale classes before it returns the base class bundle. However if it fails to find a match, it throws a MissingResourceException error. A base class with no suffixes should always exist in order to avoid throwing this exception


  2. Use the base resource bundle on the JSF pages by loading the bundle and then binding component attributes to keys in the bundle.

  3. Create a localized resource bundle for each locale supported by the application.

  4. Register the locales with the application.

  5. Register the bundle used for application messages.


Note:

If you use a custom skin and have created a custom resource bundle for the skin, you must also create localized versions of that resource bundle. Similarly if your application uses control hints on data controls to set any text, you must create localized versions of the generated resource bundles for that text.

Detailed procedures for each step follow.

To create a resource bundle as a property file:

  1. In JDeveloper, create a new simple file.

    1. In the Application Navigator, right-click where you want the file to be placed and choose New to open the New Gallery.


      Note:

      If you are creating a localized version of the base resource bundle, save the file to the same directory as the base file.

    2. In the Categories tree, select Simple Files, and in the Items list, select File.

    3. Enter a name for the file, using the extension .properties.


      Note:

      If you are creating a localized version of a base resource bundle, you must append the ISO 639 lowercase language code to the name of the file. For example, the German version of the UIResources bundle is UIResources_de.properties. You can add the ISO 3166 uppercase country code (for example de_DE) if one language is used by more than one country. You can also add an optional non standard variant (for example, to provide platform or region information).

      If you are creating the base resource bundle, no codes should be appended.


  2. Create a key and value for each string of static text for this bundle. The key is a unique identifier for the string. The value is the string of text in the language for the bundle. If you are creating a localized version of the base resource bundle, any key not found in this version will inherit the values from the base class.


    Note:

    All non-ASCII characters must be either UNICODE escaped or the encoding must be explicitly specified when compiling, for example:
    javac -encoding ISO8859_5 UIResources_de.java
    

    For example the key and value for the title of the SRList page is:

    srlist.pageTitle=My Service Requests
    
    

    Note:

    All non-8859-1 character sets must be converted to escaped UTF-8 characters, or they will not display correctly.

To create a resource bundle as a Java Class:

  1. In JDeveloper, create a new simple Java class:

    • In the Application Navigator, right-click where you want the file to be placed and choose New to open the New Gallery.


      Note:

      If you are creating a localized version of the base resource bundle, this must reside in the same directory as the base file.

    • In the Categories tree, select Simple Files, and in the Items list, select Java Class.

    • Enter a name and package for the class. The class must extend java.util.ListResourceBundle.


      Note:

      If you are creating a localized version of a base resource bundle, you must append the ISO 639 lowercase language code to the name of the class. For example, the German version of the UIResources bundle might be UIResources_de.java. You can add the ISO 3166 uppercase country code (for example de_DE) if one language is used by more than one country. You can also add an optional non standard variant (for example, to provide platform or region information).

      If you are creating the base resource bundle, no codes should be appended.


  2. Implement the getContents() method, which simply returns an array of key-value pairs. Create the array of keys for the bundle with the appropriate values. Example 14-10 shows a sample base resource bundle java class.


    Note:

    Keys must be Strings. If you are creating a localized version of the base resource bundle, any key not found in this version will inherit the values from the base class.

    Example 14-10 Base Resource Bundle Java Class

    package sample;import java.util.ListResourceBundle;public class MyResources extends ListResourceBundle {  public Object[][] getContents() {    return contents;  }  static final Object[][] contents = {    {"button_Search", "Search"},    {"button_Reset", "Reset"},  };}
    

To use a base resource bundle on a page:

You need to load only the base resource bundle on the page. The application will automatically use the correct version based on the user's locale setting in their browser.

  1. Set your page encoding and response encoding to be a superset of all supported languages. If no encoding is set, the page encoding defaults to the value of the response encoding set using the contentType attribute of the page directive. Example 14-11 shows the encoding for the SRList page.

    Example 14-11 Page and Response Encoding

    <?xml version='1.0' encoding='windows-1252'?>
    <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0"
              xmlns:h="http://java.sun.com/jsf/html"
              xmlns:f="http://java.sun.com/jsf/core"
              xmlns:af="http://xmlns.oracle.com/adf/faces"
              xmlns:afh="http://xmlns.oracle.com/adf/faces/html"
              xmlns:afc="http://xmlns.oracle.com/adf/faces/webcache">
      <jsp:output omit-xml-declaration="true" doctype-root-element="HTML"
                  doctype-system="http://www.w3.org/TR/html4/loose.dtd"
                  doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"/>
      <jsp:directive.page contentType="text/html;charset=UTF-8"/>
      <f:view>
    
    

    Tip:

    By default JDeveloper sets the page encoding to windows-1252. To set the default to a different page encoding:
    1. From the menu, choose Tools > Preferences.

    2. In the left-hand pane, select Environment if it is not already selected.

    3. Set Encoding to the preferred default.


  2. Load the base resource bundle onto the page using the loadBundle tag, as shown in Example 14-12. The basename attribute specifies the fully qualified name of the resource bundle to be loaded. This resource bundle should be the one created for the default language of the application. The var attribute specifies the name of a request scope attribute under which the resource bundle will be exposed as a Map, and will be used in the EL expressions that bind component attributes to a key in the resource bundle.

    Example 14-12 The loadBundle Tag

    <f:loadBundle basename="oracle.srdemo.view.resources.UIResources"
                  var="res"/>
    
    
  3. Bind all attributes that represent strings of static text displayed on the page to the appropriate key in the resource bundle, using the variable created in the previous step. Example 14-13 shows the code for the View button on the SRList page.

    Example 14-13 Binding to a Resource Bundle

    <af:commandButton text="#{res['srlist.buttonbar.view']}"
                      action="#{backing_SRList.viewButton_action}"
                      id="viewButton"/>
    
    

To register locales:

  1. Open the faces-config.xml file and select the Overview tab in the editor window. The faces-config.xml file is located in the <View_Project>/WEB-INF directory.

  2. In the JSF Configuration Editor, select Application.

  3. If not already displayed, click the Local Config's triangle to display the Default Locale and Supported Locales fields.

  4. For Default Locale, enter the ISO locale identifier for the default language to be used by the application. This identifier should represent the language used in the base resource bundle.

  5. Add additional supported locales by clicking New. Click Help or press F1 for additional help in registering the locales.

To register the message bundle:

  1. Open the faces-config.xml file and click on the Overview tab in the editor window. The faces-config.xml file is located in the <View_Project>/WEB-INF directory.

  2. In the window, select Application.

  3. For Message Bundle, enter the fully qualified name of the base bundle that contains messages to be used by the application.

14.4.2 How to Configure Optional Localization Properties for ADF Faces

Along with providing text translation, ADF Faces also automatically provides other types of translation, such as text direction and currency codes. The application will automatically display appropriately based on the user's selected locale. However, you can also manually set the following localization settings for an application in the adf-faces-config.xml file.

  • <currency-code>: Defines the default ISO 4217 currency code used by oracle.adf.view.faces.converter.NumberConverter to format currency fields that do not specify a currency code in their own converter.

  • <number-grouping-separator>: Defines the separator used for groups of numbers (for example, a comma). ADF Faces automatically derives the separator from the current locale, but you can override this default by specifying a value in this element. If set, this value is used by oracle.adf.view.faces.converter.NumberConverter while it parses and formats.

  • <decimal-separator>: Defines the separator (for example, a period or a comma) used for the decimal point. ADF Faces automatically derives the separator from the current locale, but you can override this default by specifying a value in this element. If set, this value is used by oracle.adf.view.faces.converter.NumberConverter while it parses and formats.

  • <right-to-left>: ADF Faces automatically derives the rendering direction from the current locale, but you can explicitly set the default page rendering direction by using the values true or false.

  • <time-zone>: ADF Faces automatically uses the time zone used by the client browser. This value is used by oracle.adf.view.faces.converter.DateTimeConverter while it converts Strings to Date.

To configure optional localization properties:

  1. Open the adf-faces-config.xml file. The file is located in the <View_Project>/WEB-INF directory.

  2. From the Component Palette, drag the element you wish to add to the file into the Structure window. An empty element is added to the page.

  3. Enter the desired value.

Example 14-14 shows a sample adf-faces-config.xml file with all the optional localization elements set.

Example 14-14 Configuring Currency Code and Separators for Numbers and Decimal Point

<!-- Set the currency code to US dollars. -->
<currency-code>USD</currency-code>

<!-- Set the number grouping separator to period for German -->
<!-- and comma for all other languages -->
<number-grouping-separator>
 #{view.locale.language=='de' ? '.' : ','}
</number-grouping-separator>

<!-- Set the decimal separator to comma for German -->
<!-- and period for all other languages -->
<decimal-separator>
 #{view.locale.language=='de' ? ',' : '.'}
</decimal-separator>

<!-- Render the page right-to-left for Arabic -->
<!-- and left-to-right for all other languages -->
<right-to-left>
 #{view.locale.language=='ar' ? 'true' : 'false'}
</right-to-left>

<!-- Set the time zone to Pacific Daylight Savings Time -->
<time-zone>PDT</time-zone>