9 Building Global Applications

Building a global Internet application that supports different locales requires good development practices. A locale refers to a national language and the region in which the language is spoken. The application itself must be aware of user locale preferences and present content following the cultural convention expected by the user. It is important to present data with appropriate locale characteristics, such as using the correct date and number formats. Oracle Database is fully internationalized to provide a global platform for developing and deploying global applications.

This chapter discusses global application development in a Java and Oracle Database environment. It addresses the basic tasks associated with developing and deploying global Internet applications, including developing locale awareness, constructing HTML content in the user-preferred language, and presenting data following the cultural conventions of the user locale.

This chapter has the following topics:

9.1 Developing Locale Awareness

Global Internet applications must be aware of the user locale. Locale-sensitive functions, such as date, time, and monetary formatting, are built into programming environments such as Java and SQL. Applications can use locale-sensitive functions to format the HTML pages according to the cultural conventions of the user locale.

Different programming environments represent locales in different ways. For example, the French (Canadian) locale is represented as follows:

Environment Representation Locale Explanation
Java Java locale object fr_CA Java uses the ISO language and country code.

fr is the language code defined in the ISO 639 standard. CA is the country code defined in the ISO 3166 standard.

SQL and PL/SQL NLS_LANGUAGE and NLS_TERRITORY parameters NLS_LANGUAGE ="CANADIAN FRENCH"

NLS_TERRITORY ="CANADA"

See also: Chapter 8 "Working in a Global Environment" in the Oracle Database Express Edition 2 Day Developer Guide.

Table 9-1 shows how some of the commonly used locales are defined in Java and Oracle environments.

Table 9-1 Locale Representation in Java, SQL, and PL/SQL Programming Environments

Locale Java NLS_LANGUAGE, NLS_TERRITORY

Chinese (P.R.C)

zh_CN

SIMPLIFIED CHINESE, CHINA

Chinese (Taiwan)

zh_TW

TRADITIONAL CHINESE, TAIWAN

English (U.S.A)

en_US

AMERICAN, AMERICA

English (United Kingdom)

en_GB

ENGLISH, UNITED KINGDOM

French (Canada)

fr_CA

CANADIAN FRENCH, CANADA

French (France)

fr_FR

FRENCH, FRANCE

German (Germany)

de_DE

GERMAN, GERMANY

Italian (Italy)

it_IT

ITALIAN, ITALY

Japanese (Japan)

ja_JP

JAPANESE, JAPAN

Korean (Korea)

ko_KR

KOREAN, KOREA

Portuguese (Brazil)

pt_BR

BRAZILIAN PORTUGUESE, BRAZIL

Portuguese (Portugal)

pt_PT

PORTUGUESE, PORTUGAL

Spanish (Spain)

es_ES

SPANISH, SPAIN


When writing global applications across different programming environments, the user locale settings must be synchronized between environments. For example, Java applications that call PL/SQL procedures should map the Java locales to the corresponding NLS_LANGUAGE and NLS_TERRITORY values and change the parameter values to match the user locale before calling the PL/SQL procedures.

9.1.1 Mapping Between Oracle and Java Locales

The Oracle Globalization Development Kit (GDK) provides the LocaleMapper class. It maps equivalent locales and character sets between Java, IANA, ISO, and Oracle. A Java application may receive locale information from the client that is specified in the Oracle locale name. The Java application must be able to map to an equivalent Java locale before it can process the information correctly.

Example 9-1 shows how to use the LocaleMapper class.

Example 9-1 Mapping from a Java Locale to an Oracle Language and Territory

Locale locale = new Locale("fr", "CA");
String oraLang = LocaleMapper.getOraLanguage(locale);
String oraTerr = LocaleMapper.getOraTerritory(locale);

The GDK is a set of Java application programming interfaces (APIs) that provide Oracle application developers with the framework to develop globalized Internet applications. The GDK complements the existing globalization features in Java. It provides the synchronization of locale behaviors between a middle-tier Java application and the Oracle database server.

9.2 Determining User Locales

In a global environment, your application may have to accept users with different locale preferences. Determine the preferred locale of the user. Once that is known, the application should construct HTML content in the language of the locale, and follow the cultural conventions implied by the locale.

One of the most common methods in determining the user locale, is based on the default ISO locale setting of the browser of the user. Usually a browser sends locale preference settings to the HTTP server with the Accept-Language HTTP header. If this header is set to NULL, then there is no locale preference information available and the application should ideally fall back to a predefined application default locale.

Both JSP pages and Java Servlets can use calls to the Servlet API to retrieve the Accept-Language HTTP header as shown in Example 9-2.

Example 9-2 Determining User Locale in Java Using the Accept-Language Header

String lang = request.getHeader("Accept-Language")
StringTokenizer st = new StringTokenizer(lang, ",")
if (st.hasMoreTokens()) userLocale = st.nextToken();

This code gets the Accept-Language header from the HTTP request, extracts the first ISO locale, and uses it as the user-desired locale.

9.2.1 Locale Awareness in Java Applications

A Java locale object represents the locale of the corresponding user in Java. The Java encoding used for the locale is required to properly convert Java strings to and from byte data. You must consider the Java encoding for the locale if you make the Java code aware of a user locale. There are two ways to make a Java method sensitive to the Java locale and encoding:

  • Using the default Java locale and default Java encoding for the method

  • Explicitly specifying the Java locale and Java encoding for the method

When developing a global application, it is recommended to take the second approach and explicitly specify the Java locale and Java encoding that correspond to the current user locale. You can specify the Java locale object that corresponds to the user locale, identified by user_locale, in the getDateTimeInstance method as in Example 9-3.

Example 9-3 Explicitly Specifying User Locale in Java

DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, user_locale);
dateString = df.format(date); /* Format a date */

9.3 Encoding HTML Pages

The encoding of an HTML page is important information for a browser and an Internet application. You can think of the page encoding as the character set used for the locale that an Internet application is serving. The browser needs to know about the page encoding so that it can use the correct fonts and character set mapping tables to display the HTML pages. Internet applications need to know about the HTML page encoding so they can process input data from an HTML form.

Instead of using different native encodings for the different locales, it is recommended that UTF-8 (Unicode encoding) is used for all page encodings. Using the UTF-8 encoding not only simplifies the coding for global applications, but it allows for multilingual content on a single page.

This section includes the following topics:

9.3.1 Specifying the Page Encoding for HTML Pages

There are two ways to specify the encoding of an HTML page, one is in the HTTP header, and the other is in the HTML page header.

Specifying the Encoding in the HTTP Header

Include the Content-Type HTTP header in the HTTP specification. It specifies the content type and character set as shown in Example 9-4.

Example 9-4 Specifying Page Encoding in the HTTP Specification

Content-Type: text/html; charset=utf-8

The charset parameter specifies the encoding for the HTML page. The possible values for the charset parameter are the IANA names for the character encodings that the browser supports.

Specifying the Encoding in the HTML Page Header

Use this method primarily for static HTML pages. Specify the character encoding in the HTML header as shown in Example 9-5.

Example 9-5 Specifying Page Encoding on an HTML Page

<meta http-equiv="Content-Type" content="text/html;charset=utf-8">

The charset parameter specifies the encoding for the HTML page. As with the Content-Type HTTP Header, the possible values for the charset parameter are the IANA names for the character encodings that the browser supports.

9.3.2 Specifying the Page Encoding in Java Servlets and JSP Pages

You can specify the encoding of an HTML page in the Content-Type HTTP header in a JavaServer Pages (JSP) file using the contentType page directive. For example:

<%@ page contentType="text/html; charset=utf-8" %>

This is the MIME type and character encoding that the JSP file uses for the response it sends to the client. You can use any MIME type or IANA character set name that is valid for the JSP container. The default MIME type is text/html, and the default character set is ISO-8859-1. In the above example, the character set is set to UTF-8. The character set of the contentType page directive directs the JSP engine to encode the dynamic HTML page and set the HTTP Content-Type header with the specified character set.

For Java Servlets, you can call the setContentType method of the Servlet API to specify a page encoding in the HTTP header. The doGet function in Example 9-6 shows how you can call this method.

Example 9-6 Specifying Page Encoding in Servlets Using setContentType

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
 
// generate the MIME type and character set header
response.setContentType("text/html; charset=utf-8");

...

// generate the HTML page
Printwriter out = response.getWriter();
out.println("<HTML>");

...

out.println("</HTML>");
}

You should call the setContentType method before the getWriter method because the getWriter method initializes an output stream writer that uses the character set specified by the setContentType method call. Any HTML content written to the writer and eventually to a browser is encoded in the encoding specified by the setContentType call.

9.4 Organizing the Content of HTML Pages for Translation

Making the user interface available in the local language of the user is one of the fundamental tasks related to globalizing an application. Translatable sources for the content of an HTML page belong to the following categories:

  • Text strings hard-coded in the application code

  • Static HTML files, images files, and template files such as CSS

  • Dynamic data stored in the database

This section discusses externalizing translatable content in the following:

9.4.1 Strings in Java Servlets and JSP Pages

You should externalize translatable strings within Java Servlets and JSP pages into Java resource bundles so that these resource bundles can be translated independent of the Java code. After translation, the resource bundles carry the same base class names as the English bundles, but with the Java locale name as the suffix. You should place the bundles in the same directory as the English resource bundles for the Java resource bundle look-up mechanism to function properly.

See Also:

Sun Microsystems documentation about Java resource bundles at

http://java.sun.com/j2se/1.4.2/docs/api/java/util/ResourceBundle.html

Because the user locale is not fixed in multilingual applications, they should call the getBundle method by explicitly specifying a Java locale object that corresponds to the user locale. The Java locale object is called user_locale in the following example:

ResourceBundle rb = ResourceBundle.getBundle("resource", user_locale);
String helloStr = rb.getString("hello");

The above code will retrieve the localized version of the text string, hello, from the resource bundle corresponding to the desired locale of the user.

See Also:

For more information on creating resource bundles in Java, refer to Localizing Text on JSP Pages in JDeveloper.

9.4.2 Static Files

Static files such as HTMLs and GIFs are readily translatable. When these files are translated, they should be translated into the corresponding language with UTF-8 as the file encoding. To differentiate between the languages of the translated files, the static files of different languages can be staged in different directories or with different file names.

9.4.3 Data from the Database

Dynamic information such as product names and product descriptions are most likely stored in the database regardless of whether you use JSP pages or Java Servlets. In order to differentiate between various translations, the database schema holding this information should include a column to indicate the language of the information. To select the translated information, you must include the WHERE clause in your query to select the information in the desired language of the query.

9.5 Presenting Data by User Locale Convention

Data in the application needs to be presented in a way that conforms to user expectation, if not, the meaning of the data can sometimes be misinterpreted. For example, '12/11/05' implies '11th December 2005' in the United States, whereas in the United Kingdom it means '12th November 2005'. Similar confusion exists for number and monetary formats, for example, the period (.) is a decimal separator in the United States, whereas in Germany, it is used as a thousand separator.

Different languages have their own sorting rules, some languages are collated according to the letter sequence in the alphabet, some according to stroke count in the letter, and there are some languages which are ordered by the pronunciation of the words. Presenting data that is not sorted according to the linguistic sequence that your users are accustomed to can make searching for information difficult and time-consuming.

Depending on the application logic and the volume of data retrieved from the database, it may be more appropriate to format the data at the database level rather than at the application level. Oracle Database offers many features that help you to refine the presentation of data when the user locale preference is known. The following sections include examples of locale-sensitive operations in SQL:

9.5.1 Oracle Date Formats

There are three different date presentation formats in Oracle Database. These are standard, short, and long dates. Example 9-7 illustrates the difference between the short data and long date formats for both United States and Germany.

Example 9-7 Difference Between Date Formats by Locale (United States and Germany)

SQL> ALTER SESSION SET NLS_TERRITORY=america NLS_LANGUAGE=american;
 
Session altered.
 
SQL> SELECT employee_id EmpID,
  2  SUBSTR(first_name,1,1)||'.'||last_name "EmpName",
  3  TO_CHAR(hire_date,'DS') "Hiredate",
  4  TO_CHAR(hire_date,'DL') "Long HireDate"
  5  FROM employees
  6* WHERE employee_id <105;
 
     EMPID EmpName                     Hiredate   Long HireDate
---------- --------------------------- ---------- -----------------------------
       100 S.King                      06/17/1987 Wednesday, June 17, 1987
       101 N.Kochhar                   09/21/1989 Thursday, September 21, 1989
       102 L.De Haan                   01/13/1993 Wednesday, January 13, 1993
       103 A.Hunold                    01/03/1990 Wednesday, January 3, 1990
       104 B.Ernst                     05/21/1991 Tuesday, May 21, 1991
 
 
SQL> ALTER SESSION SET SET NLS_TERRITORY=germany NLS_LANGUAGE=german;
 
Session altered.
 
SQL> SELECT employee_id EmpID,
  2  SUBSTR(first_name,1,1)||'.'||last_name "EmpName",
  3  TO_CHAR(hire_date,'DS') "Hiredate",
  4  TO_CHAR(hire_date,'DL') "Long HireDate"
  5  FROM employees
  6* WHERE employee_id <105;
 
 
     EMPID EmpName                     Hiredate Long HireDate
---------- --------------------------- -------- ------------------------------
       100 S.King                      17.06.87 Mittwoch, 17. Juni 1987
       101 N.Kochhar                   21.09.89 Donnerstag, 21. September 1989
       102 L.De Haan                   13.01.93 Mittwoch, 13. Januar 1993
       103 A.Hunold                    03.01.90 Mittwoch, 3. Januar 1990
       104 B.Ernst                     21.05.91 Dienstag, 21. Mai 1991

9.5.2 Oracle Number Formats

Example 9-8 illustrates the differences in the decimal character and group separator between the United States and Germany.

Example 9-8 Difference Between Number Formats by Locale (United States and Germany)

SQL> ALTER SESSION SET SET NLS_TERRITORY=america;
 
Session altered.
 
SQL> SELECT employee_id EmpID,
  2  SUBSTR(first_name,1,1)||'.'||last_name "EmpName",
  3  TO_CHAR(salary, '99G999D99') "Salary"
  4  FROM employees
  5* WHERE employee_id <105
 
     EMPID EmpName                     Salary
---------- --------------------------- ----------
       100 S.King                       24,000.00
       101 N.Kochhar                    17,000.00
       102 L.De Haan                    17,000.00
       103 A.Hunold                      9,000.00
       104 B.Ernst                       6,000.00
 
SQL> ALTER SESSION SET SET NLS_TERRITORY=germany;
 
Session altered.
 
SQL> SELECT employee_id EmpID,
  2  SUBSTR(first_name,1,1)||'.'||last_name "EmpName",
  3  TO_CHAR(salary, '99G999D99') "Salary"
  4  FROM employees
  5* WHERE employee_id <105
 
     EMPID EmpName                     Salary
---------- --------------------------- ----------
       100 S.King                       24.000,00
       101 N.Kochhar                    17.000,00
       102 L.De Haan                    17.000,00
       103 A.Hunold                      9.000,00
       104 B.Ernst                       6.000,00

9.5.3 Oracle Linguistic Sorts

Spain traditionally treats 'ch', 'll' as well as 'ñ' as letters of their own, ordered after c, l and n respectively. Example 9-9 illustrates the effect of using a Spanish sort against the employee names Chen and Chung.

Example 9-9 Variations in Linguistic Sorting (Binary and Spanish)

SQL> ALTER SESSION SET NLS_SORT=binary;
 
Session altered.
 
SQL> SELECT employee_id EmpID,
  2         last_name "Last Name"
  3  FROM employees
  4  WHERE last_name LIKE 'C%'
  5* ORDER BY last_name
 
     EMPID Last Name
---------- -------------------------
       187 Cabrio
       148 Cambrault
       154 Cambrault
       110 Chen
       188 Chung
       119 Colmenares
 
6 rows selected.
 
SQL> ALTER SESSION SET NLS_SORT=spanish_m;
 
Session altered.
 
SQL> SELECT employee_id EmpID,
  2         last_name "Last Name"
  3  FROM employees
  4  WHERE last_name LIKE 'C%'
  5* ORDER BY last_name
 
     EMPID Last Name
---------- -------------------------
       187 Cabrio
       148 Cambrault
       154 Cambrault
       119 Colmenares
       110 Chen
       188 Chung
 
6 rows selected.

9.5.4 Oracle Error Messages

The NLS_LANGUAGE parameter also controls the language of the database error messages that are returned from the database. Setting this parameter prior to submitting your SQL statement will ensure that local language-specific database error messages will be returned to the application.

Consider the following server message:

ORA-00942: table or view does not exist

When the NLS_LANGUAGE parameter is set to French, the server message appears as follows:

ORA-00942: table ou vue inexistante

See Also:

"Working in a Global Environment" chapter in the Oracle Database Express Edition 2 Day DBA for a discussion of globalization support features within Oracle Database.

9.6 Localizing Text on JSP Pages in JDeveloper

Your Java application can make use of resource bundles, to provide different localized versions of the text used on your JSP pages.

Resource bundles contain locale-specific objects. When your program needs a locale-specific resource, such as some text to display on a page, your program can load it from the resource bundle that is appropriate for the current user locale. In this way, you can write program code that is largely independent of the user locale isolating the actual text in resource bundles.

In outline, the resource bundle technology has the following features:

  • Resource bundles belong to families whose members share a common base name, but whose names also have additional components that identify their locales. For example, the base name of a family of resource bundles might be MyResources. A locale-specific version for German, for example, would be called MyResources_de.

  • Each resource bundle in a family contains the same items, but the items have been translated for the locale represented by that resource bundle. For example, a String used on a button might in MyResources be defined as Cancel, but in MyResources_de as Abbrechen.

  • You can make specializations for different resources for different countries, for example, for the German language (de) in Switzerland (CH).

To use resource bundles in your application, you must do the following:

  1. Create the resource bundles.

  2. In pages that have visual components, identify the resource bundles you will be using on the page.

  3. For each item of text you want to display on your pages, retrieve the text from the resource bundle instead of using hard-coded text.

See Also:

Sun Microsystems documentation on resource bundles at

http://java.sun.com/j2se/1.4.2/docs/api/java/util/ResourceBundle.html

In the sample application, resource bundles can be used in the following places:

  • Headings and labels on JSP pages. In this case, rather than entering text directly on the pages, you can use a scriptlet to find the text.

  • Values for buttons and other controls. In this case, set the value property of the button to an expression that retrieves the text from the resource bundle

This section covers the following tasks:

9.6.1 Creating a Resource Bundle

To create a default resource bundle:

  1. Create a new Java class called MyResources.java, that extends class java.util.ListResourceBundle.

  2. Define the resource bundle class and methods to return contents as follows:

    public class MyResources extends ListResourceBundle 
    {
      public Object[][] getContents() {
        return contents;
      }
      static final Object[][] contents = {
      };
    }
    
  3. Add an entry for each item of text you need on your pages, giving a key and the text for that key. For example, in the following example, the comments indicate the strings that must be translated into other languages:

      static final Object[][] contents = {
        // LOCALIZE THIS
        {"CompanyName", "AnyCo Corporation"},
        {"SiteName", "HR Application"},
        {"FilterButton", "Filter"},
        {"UpdateButton", "Update"},
        // END OF MATERIAL TO LOCALIZE
      };
    

    The complete resource bundle class should look similar to that shown in Example 9-10.

    Example 9-10 Creating a Resource Bundle Class

    public class MyResources extends ListResourceBundle 
    {
      public Object[][] getContents() {
        return contents;
      }
      static final Object[][] contents = {
        // LOCALIZE THIS
        {"CompanyName", "AnyCo Corporation"},
        {"SiteName", "HR Application"},
        {"FilterButton", "Filter"},
        {"UpdateButton", "Update"},
        // END OF MATERIAL TO LOCALIZE
      };
    }
    

    To globalize your application, you must create the locale-specific versions of the resource bundle for the different locales you are supporting, containing text for the items in each language.

9.6.2 Using Resource Bundle Text on JSP Pages

To use the text defined in a resource bundle on your JSP pages:

  1. Open the JSP page you want to work on in the Visual Editor, such as edit.jsp.

  2. Create a new line at the top of the page before the first heading and set the Style of the line to None. Add a jsp:usebean tag to the new line. Enter myResources as the ID, and hr.MyResources as the Class. Set the Scope to session, and click OK.

  3. Drag a jsp:scriptlet to the page, where you want the resource bundle text to be displayed, for example in the heading for the page.

    In the Insert Scriptlet dialog, enter the script for retrieving text from the resource bundle:

      out.println(myResources.getString("CompanyName") + ": " + 
      myResources.getString("SiteName"));
    
  4. If there was text already displayed in the heading, you can remove it now.

  5. If you select the Source tab below the Visual Editor, you should see code for the page similar to the following:

    <h2 align="center">
      <% = myResources.getString("CompanyName") + ": " + 
                  myResources.getString("SiteName"));
      %>
    </h2>
    
  6. To use resource bundle text as the label for a button, double-click the button in the Visual Editor. In the button properties dialog, for the Value parameter of the button, enter a script similar to the following:

    <% out.println(myResources.getString("UpdateButton"));%>
    
  7. If you view the Source code for the page, you will see code similar to the following:

    <input type="submit" 
      value=<% out.println(myResources.getString("UpdateButton"));%> />
    

If you now run your application, you will see the text you defined in your resource bundle displayed on the page.