Contents


Create internationalized JSP applications

Understand the unique challenges for server-side applications

Comments

The increasing globalization of the world economy has driven the need for Web-based software that a multinational body of users can access. These users might have widely different language, display, data-entry, presentation, and cultural needs. Internationalization (i18n for short) is the art of creating applications that will work for such a diverse body of users.

Perhaps surprisingly, J2SE's built-in support for internationalization falls short when it's used without custom modifications on the server side. In general, internationalization of server-side applications is still an art rather than a science, often involving proprietary or roll-your-own solutions.

This article differentiates the internationalization needs of a server-side JSP-based application from those of a J2SE application. I'll explore the various client/server topologies that lead to the significantly different server-side requirements. Then, you'll examine working code that illustrates two widely used solutions to the basic problem.

Beyond J2SE locales

J2SE uses the concept of a locale (see Notation for a locale) for internationalization. On a single machine, the locale indicates the user's preference for the language displayed (for example, English or Spanish), as well as formatting conventions for date, time, currency, and so on. Typically, the underlying operating system manages the locale preference and passes it to J2SE during runtime.

The concept of a machine-specific locale works great if you're running a server on your local machine, or if the server is another machine on your local-area network. All of the client and server machines involved have the same locale, so they all use the same display language, date conventions, and so on. Neither of these scenarios presents any tricky internationalization problems. But the situation becomes less straightforward when you want to use the same server to service users in multiple international locations.

The server-side internationalization problem

When a server application is deployed for access internationally, it must provide simultaneous support for different locales. Figure 1 shows a possible scenario. Each machine -- the server, and the clients that might access the server at any time -- can have its own locale setup, and these locales are likely to be different.

Figure 1. A server servicing users with different locales
A server servicing users with different locales
A server servicing users with different locales

In Figure 1, the server machine is in San Francisco with a machine-specific locale of en_US (English in the United States). The users from New York and Dallas all use the en_US locale and so have no additional internationalization needs. However, the user coming in from Seoul expects to see the application prompts in Korean, with a locale of ko_KR. Meanwhile, the user from Shanghai wants to see the application text in Chinese, with a locale of zh_CN. A user from Tokyo expects the application to appear in Japanese, with a locale of ja_JP. All of these users' requirements must be satisfied from the JSP application running on the San Francisco server.

At the server end, you have total control over the server machine's own locale, but you can't do anything to change or force the client into specific locale. Instead, your application must find each user's locale and make sure the JSP pages are presented using the proper localization (see Detecting client locale).

More locale-determination complications

Just when you might think it's safe simply to determine the client's locale (and present the JSP accordingly, you encounter a new twist. Consider the following very realistic scenario.

A visiting staff member from Tokyo is using a machine at the sales office in Shanghai, China that has a locale of zh_CN. Not being fluent in written Chinese, she wants to access your Web application in Japanese. See Figure 2 (a) for an illustration of this situation.

Figure 2. Users desiring locales different from client machine
Users desiring locales different from client machine
Users desiring locales different from client machine

In Figure 2 (a), the San Francisco server has a locale of en_US. The client machine in Shanghai has a locale of zh_CN. But the JSP application needs to display in the ja_JP locale in order to be useful for the user.

Take another (more bizarre but nevertheless possible) scenario. As a developer of an internationalized JSP application, you are debugging. On a client system that has the en_US locale, you open three browser instances running your JSP application. The server machine is on the LAN and also has an en_US locale. However, you are testing the application's handling for Chinese and Japanese users. So on your single en_US client machine, one browser instance is in English (en_US), one in Japanese (ja_JP), and one is in Chinese (zh_CN). Figure 2 (b) illustrates this situation.

The fundamental internationalization problem should be clear by now: Neither the client locale or the server locale has any bearing on the actual desired locale for displaying any particular instance of an internationalized application. Only the user can tell you which locale to display the page for.

Thankfully, it's usually safe to assume that users don't want the displayed language to change while they're working with the application. Therefore the locale can typically be associated with the session.

Solving the locale-dependent language-display problem

At least two commonly accepted ways to handle the display of different languages for JSP applications are available:

  • Store multiple sets of JSPs, each set encoded in a different language, then switch among these sets depending on the user's locale selection.
  • Isolate all use of text strings, and obtain a locale-specific string from a resource bundle instead. (This approach uses the J2SE locale-specific resource bundle handling.)

I'll present two versions of example code, one for each alternative. The example application is the login screen for a fictional e-mail service, called developerWorks Email. Users of this e-mail system will first be prompted with a language-selection screen that determines their desired locale for the current session. The selection includes English, Korean, Japanese, and Chinese, as shown in Figure 3. If you are trying out the code, use the URL http://<server address>/dwi18n/multdir/index.jsp to access this page.

Figure 3. Language-selection screen for explicit locale selection
Four different locales on the same machine
Four different locales on the same machine

In Figure 3, the language-selection screen uses four images to present the four locale selections (see Using images for initial language selection). The login screen displays using the language the user selects here. Figure 4 shows the login screen in Japanese.

Figure 4. Sign-on screen in Japanese
Sign on screen in Japanese
Sign on screen in Japanese

Using multiple redundant sets of language-specific JSPs

The first version of this example, located in the webapps/dwi18n/multdir/ directory of the sample code distribution, makes use of multiple sets of JSP pages. Figure 5 shows the directory hierarchy for this application.

Figure 5. Directory hierarchy of dwi18n/multdir showing locale-specific directories
Directory hierarchy of dwi18n/multdir showing language specific directories

In Figure 5, each of the locales has a corresponding subdirectory. The English-encoded JSPs for the en_EN locale are in the en subdirectory. The Korean-encoded JSPs corresponding to the ko_KR locale are in the ko subdirectory. For the ja_JP locale, the Japanese encoded JSPs are in the ja subdirectory. The zh_CN locale is represented by the Chinese-encoded JSPs in the zh subdirectory. Each of these subdirectories contains both a sign-on screen JSP (login.jsp) and a data-confirmation JSP (confirm.jsp).

The data-confirmation JSP simply displays the data that's entered in this simple example. For example, if you were to enter your information on the Chinese sign-in screen and then click the button, the data-confirmation JSP would display the entered data, as in Figure 6.

Figure 6. Confirmation page in Chinese
Confirmation page in Chinese
Confirmation page in Chinese

Coding the JSPs

The locale-selection JSP, called index.jsp, directly links to one of the sets of language-specific JSPs. The code for this version of index.jsp is in Listing 1:

Listing 1. Locale-selection JSP linking directly to language-specific pages
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Select a language</title>
</head>
<body>
<table>
<tr>
<td colspan=4 bgcolor="black">
<br/>
<center><font face="arial" size=+2 color="white">
    <b><i>developer</i>Works Email</b></font>
</center>
<br/>

</td>
</tr>
 <tr><td>
 <c:url value="en/login.jsp" var="englishURL"/>
 <a href="${englishURL}">
    <img src="english.gif"/>
 </a>
</td>
<td>
 <c:url value="ja/login.jsp" var="japaneseURL"/>
  <a href="${japaneseURL}">
       <img src="japanese.gif"/>
  </a>
</td>
<td>
  <c:url value="ko/login.jsp" var="koreanURL"/>
  <a href="${koreanURL}">
       <img src="korean.gif"/>
  </a>
</td>
<td>
  <c:url value="zh/login.jsp" var="chineseURL"/>
  <a href="${chineseURL}">
       <img src="chinese.gif"/>
  </a>
</td>
</tr>
</table>
</body>
</html>

In Listing 1, note the use of the <c:url> tag from the JSP Standard Tag Library (JSTL) to create the linking URL. This ensures that session management is handled properly. (See Related topics for more information on JSTL and the <c:url> tag.)

Each set of login.jsp and confirm.jsp is coded in the language specific to a locale. Listing 2 shows login.jsp for the ja_JP locale (corresponding to Figure 4):

Listing 2. Sign-on page (login.jsp) for the ja_JP locale
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<title>developerWorks 電子メール</title>
</head>
<body>
<c:url value="confirm.jsp" var="actionURL"/>
<form action="${actionURL}" method="post">
<table>
<tr>
<td colspan=2 bgcolor="black">
<br/>
<center><font face="arial" size=+2 color="white">
    <b><i>developer</i>Works 電子メール</b></font>
</center>
<br/>

</td>
</tr>

<tr>
<td>ユーザ ID</td>
<td><input type="text" name="userid" size="40"/></td>
</tr>

<tr>
<td>パスワード</td>
<td><input type="password" name="pass" size="40"/></td>
</tr>

<tr>
<td colspan="2" align="center">
<input type="submit" value="ログイン"/></td>
</tr>


</table>

</form>

</body>
</html>

Similarly, for the zh_CN locale, confirm.jsp (corresponding to Figure 6) is encoded in Chinese, as shown in Listing 3:

Listing 3. Data-confirmation page (confirm.jsp) for the zh_CN locale
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<title>developerWorks 电邮</title>
</head>
<body>

<table border="1">
<tr>
<td colspan=2 bgcolor="black">
<br/>
<center><font face="arial" size=+2 color="white">
     <b><i>developer</i>Works 电邮</b></font>
</center>
<br/>

</td>
</tr>


<tr>
<td>用户帐号</td>
<td>${param.userid}</td>
</tr>

<tr>
<td>密码</td>
<td>${param.pass}</td>
</tr>




</table>


</body>
</html>

The multiple-redundant-sets approach I've just shown you is a practical solution for applications that:

  • Are mainly accessed in one language, and only occasionally accessed from another locale
  • Have underlying presentation-layer JSPs that don't change frequently

Using a J2SE resource bundle

The biggest drawback to the solution in the preceding section, Using multiple redundant sets of language-specific JSPs, is that when an update to any language-specific set of JSPs is required, the update must be performed to all the redundantly coded set of JSPs. With even a medium-sized project, this can necessitate tedious and error-prone updates.

The solution I'll show you now looks and works like the previous one, but in this case you use only one set of login.jsp and confirm.jsp. The solution exploits J2SE support for locale in a resource bundle to pull in the locale-specific text string when required (see Related topics for more information on J2SE resource bundles). The example code for this solution is located under the webapps\dwi18n\javares directory. If you deploy the sample code, use the URL http://<server address>/dwi18n/javares/index.jsp.

Figure 7 shows four browser sessions running on the same client machine, each session having requested a different locale.

Figure 7. Four different locales on the same machine
Four different locales on the same machine
Four different locales on the same machine

In Figure 7, you can see clearly how an internationalized JSP application can handle multiple locales simultaneously.

Coding the JSPs

The index.jsp is slightly different in this case, since it is now linked to a single login.jsp. Listing 4 shows the code for this version of index.jsp:

Listing 4. Locale-selection page linking to a single login.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Select Language</title>
</head>
<body>
<table>
<tr>
<td colspan=4 bgcolor="black">
<br/>
<center><font face="arial" size=+2 color="white">
    <b><i>developer</i>Works Email</b></font>
    </center>
<br/>

</td>
</tr>
 <tr><td>

 <c:url value="login.jsp" var="englishURL">
   <c:param name="locale" value="en_US"/>
 </c:url>

 <a href="${englishURL}">
    <img src="english.gif"/>
 </a>
</td>
<td>
  <c:url value="login.jsp" var="japaneseURL">
     <c:param name="locale" value="ja_JP"/>
  </c:url>

  <a href="${japaneseURL}">
       <img src="japanese.gif"/>
  </a>
</td>
<td>
  <c:url value="login.jsp" var="koreanURL">
     <c:param name="locale" value="ko_KR"/>
  </c:url>

  <a href="${koreanURL}">
       <img src="korean.gif"/>
  </a>
</td>
<td>
  <c:url value="login.jsp" var="chineseURL">
     <c:param name="locale" value="zh_CN"/>
  </c:url>

  <a href="${chineseURL}">
       <img src="chinese.gif"/>
  </a>
</td>
</tr>
</table>
</body>
</html>

In Listing 4, note the use of the JSTL <c:param> tag to set a URL request parameter called locale. This parameter is passed to login.jsp when the user clicks on the language selection. Listing 5 shows the code for login.jsp:

Listing 5. Sign-in page (login.jsp) using J2SE resource bundle
<%@ page pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<c:set var="loc" value="en_US"/>
<c:if test="${!(empty param.locale)}">
  <c:set var="loc" value="${param.locale}"/>
</c:if>
<fmt:setLocale value="${loc}" />


<fmt:bundle basename="app">
<head>
<title>developerWorks <fmt:message key="email"/></title>
</head>
<body>

<c:url value="confirm.jsp" var="formActionURL" />

<form action="${formActionURL}" method="post">
<table>
<tr>
<td colspan=2 bgcolor="black">
<br/>
<center><font face="arial" size=+2 color="white"><b>
       <i>developer</i>Works <fmt:message key="email"/>
         </b></font></center>
<br/>

</td>
</tr>
<tr>
<td><fmt:message key="userid"/></td>
<td>

<input type="hidden" name="locale" value="${loc}"/>
<input type="text" name="userid" size="40"/></td>
</tr>

<tr>
<td><fmt:message key="password"/></td>
<td><input type="text" name="pass" size="40"/></td>
</tr>


<tr>
<td colspan="2" align="center">
<input type="submit" value="<fmt:message key='login'/>"/></td>
</tr>

</table>

</form>

</body>
</fmt:bundle>

</html>

Listing 5 uses the JSTL internationalization helper tag library (see Related topics). The locale is set to en_US by default if the incoming param.locale is empty. You use the <fmt:setLocale> tag to set the locale when you're working with the resource bundle.

Once the locale is set, the <fmt:message> tag pulls the text, corresponding to a specified key, from a properties file in the bundle. The base name for the bundle is set to app using the <fmt:bundle> JSTL tag. If you look under the dwi18n/WEB-INF/classes directory, you'll see all the properties files (and other files) in the resource bundle there. Table 1 describes these files. See Related topics for more information on working with J2SE resource bundles.

Table 1. Files in the resource bundle
FilenameDescription
app.propertiesDefault properties file to use. Corresponds to en_US locale.
app_zh.propertiesProperties file for zh_CN locale. Contains the Chinese-encoded strings.
app_ko.propertiesProperties file for ko_KR locale. Contains the Korean-encoded strings.
app_ja.propertiesProperties file for ja_JP locale. Contains the Japanese-encoded strings.
*.ucdUnicode source files to create the properties files.
convacii.batBatch file to convert the ucd files to properties files.

As an example, the content for the app_ko.properties file is shown in Listing 6:

Listing 6. The app_ko.properties file from the resource bundle
email=\uc774\uba54\uc77c
userid=\uc544\uc774\ub514
password=\ube44\ubc00\ubc88\ud638
login=\ub85c\uadf8\uc778

In Listing 6, note that all the Unicode characters are escaped. You must do this because the Java resource bundle mechanism accepts only ASCII-encoded property files. To create this file, you can either use a string resource editor from an IDE, or create a Unicode file using a Unicode editor, then convert it using the JDK's nativetoascii utility. In this case, the convascii.bat file handled the conversion.

Conclusion

You need to be aware of unique requirements when you design internationalized JSP applications. Your applications must be prepared to support multiple concurrent access by users with differing locale requirements. This article has presented two solutions to the problem of displaying locale-specific language text for internationalized JSP applications. But I've only scratched the surface of the fascinating art of creating internationalization-ready server-side applications. Other important issues include working with different date and currency formats, managing GUI layouts, and dealing with specialized Input Method Editors (IMEs, utility software for entering foreign characters). See Related topics for information that can help you explore internationalization further.


Downloadable resources


Related topics

  • To learn about all the JSTL tags, check out the A JSTL primer series on developerWorks.
  • Find out more about J2SE resource bundles, how to create them, and where to place them by reading the javadoc of the java.util.ResourceBundle class. You can also read the javadoc online here.
  • The tutorial Java internationalization basics (developerWorks, April 2002) is a great resource for learning about all the available J2SE internationalization support mechanisms, enabling you to apply them creatively in your server-side applications.
  • The International Components for Unicode is a mature, widely used set of libraries for Unicode support, software internationalization, and globalization. ICU is an open source development project sponsored, supported, and used by IBM.
  • Explore internationalization and localization further with Sing Li in the book Beginning JavaServer Pages (John Wiley & Sons, 2005).

Comments

Sign in or register to add and subscribe to comments.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java development
ArticleID=56955
ArticleTitle=Create internationalized JSP applications
publish-date=03292005