Back to the Web Developer's Journal Main Page
internet.com
side nav bar

How to use the Java Internationalization API to build server-side code that alters its output based on the location and language of the user. Since the displayed content is not hard-coded, you will not need to write multiple versions of a class for each locale that you want to support. And adding a new language is as easy as creating a new text file of display labels. We will demonstrate the use of the API by building a simple method which displays a product entry for a shopping cart application.
Java Articles at the Web Developer's Journal - Java programming tutorials, applets, beans, servlets and more.
Back to the Web Developer's Journal Main Page
internet.com
side nav bar










We've tried to assemble a collection of articles about Java to help the beginner or the real Java gurus. If you have questions (or answers) concerning Java, please visit our Java Discussion Group.

HOW DID THEY DO THAT???

Find out in:
Amazing HTML



Site Map


Jobs at webdeveloper.com
Check out our Web-based
Discussion Groups:

Check out and join our email-based Mailing Lists for Web developers.

Ask the JavaScript Weenie:

For news and reviews of the latest computer audio tools, visit: The Tapeless Studio
Java Resources for Web Developers

Java Hub

If you have questions about Java development you have arrived at the right place. Scroll down for articles about servlets, product reviews and "how to do it" articles. We also maintain a Java discussion group.

 In This Section

 Java

  • Taking Notes on Java
    Edward Tanguay sings the praises of a very important language.

  • The Bluffer's Guide to Java
    Can't tell your Beans from your Applets? Wondering if a Servlet is a small server waiting to grow up? Read our compact guide to Java and you'll soon be dropping JAR, JVM and JSDK into casual conversations along with the best of them. Nobody will bother listening to you, but they'll still be mightily impressed.


  • Java: Coming to a TV near you!
    The new Java TV API holds the promise of Java-based interactive television using set-top boxes.


  • Java vs Other Web Application Technologies
    (The JavaBoutique) Selena Sol, author of JavaBoutique's Introduction to Java, gives an in-depth comparison of Java and other development languages such as dHTML, ASP, and Perl.
  • Agent Communication
    Agent technology is becoming more prevalent as the availability of network access, and the demand for the end-uses of agents, become greater.

  • Java Web Server in Brief
    A simple, dependable, and inexpensive ecommerce solution for small businesses is proposed.


  • JD WorkShop vs Cafe
    Two Java Tools Compared

 Java Server Pages

  • JSP: The Back Door into Java
    Edward Tanguay discovers JSP, and finds it finally allows him to put his theoretical knowledge of Java to use, and hence, get a foot into the Java programming world.

  • Building Java Server Pages
    A detailed look at building JSP pages. Should you use JSP or servlets? It depends on the ratio of markup to code. Here you'll also find a guide to the different varieties of tag, and details about the main tags such as <jsp:useBean> and <jsp:setProperty>.

  • Site User Logon with XML, Java Beans and JSP
    During this tutorial we will use XML and Java Server Pages to verify a user's logon - and then store the results in a session Java Bean for easy access.

  • Serving Dynamic WAP Content with Java Server Pages
    Here's how to create dynamic content for WAP-enabled mobile phones using the Wireless Markup Language (WML) and Sun Microsystems' Java Server API. Our Java Server Pages application displays regularly updated appointment data for someone on the move, such as an appliance engineer making house calls.

  • Object Persistence Made Easy
    With object serialization, your Java applets and applications can save and load the state of objects to disk or over a network. In this article, we'll examine the benefits of object serialization, and how to implement it in your own programs.

 Servlets

  • Intro to Servlets
    Java servlets are making headlines these days, claiming to solve many of the problems associated with CGI and proprietary server APIs. In this article I will describe the overall servlet architecture and what you need to develop your application with servlets. I will use several code examples to show you how to use the Servlet API, and compare it with CGI and proprietary server APIs where appropriate.

  • Internationalizing Servlets
    How to use the Java Internationalization API to build server-side code that alters its output based on the location and language of the user. We demonstrate the use of the API by building a simple method which displays a product entry for a shopping cart application.

  • Using the HttpSession object of the Servlet API
    The Java Servlet API represents an elegant and powerful way to shift processes from client to server, and offers a number of advantages over CGI. These advantages have certainly been enumerated so that most developers are aware of the servlet advantage. However, some of the details of the servlet architecture may at first seem daunting. Here's a short introduction on one aspect of writing servlets: the HttpSession object.

  • Improved Performance with a Connection Pool
    Establishing a connection once and then using the same connection for subsequent requests can dramatically improve the performance of a database-driven Web application. Since Servlets can keep information between requests, a database connection pool is a straightforward solution.

  • Servlets Are for Real!
    Servlets are on duty now at a Web site near you.

  • Netscape-Flavored Servlets
    How to implement server-side Java using Netscape's implementation of Java within the Enterprise Server.

 Java Discussion Group

  • Java Discussion Group
    Test the experts who hang out here with your toughest Java questions. You can also sign up for our Java E-mail Discussion List.
 

 

 Archive



Back to the Web Developer's Journal Contact WDJ   •    Suits!   •    Propheads!   •    Ponytails!
Discuss   •    Subscribe   •    Search

Be a Commerce Partner                       
HOW DID THEY DO THAT???

Find out in:
Amazing HTML



Site Map

Jobs at webdeveloper.com


Check out our Web-based
Discussion Groups:

Check out and join our email-based Mailing Lists for Web developers.


Developer Channel
FlashKit
Jobs.webdeveloper
JavaScript.com
JavaScriptSource
JustSMIL
ScriptSearch
Streaming Media World
WebDeveloper.com
WebReference
XMLFiles
WDVL
Discussion Groups Book Reviews Software Reviews Download Web Tools

An easy way to adapt your site for international users.

Internationalizing Servlets

by Mark Webber

In this article I will show you how to use the Java Internationalization API to build server-side code that alters its output based on the location and language of the user. Since the displayed content is not hard-coded, you will not need to write multiple versions of a class for each locale that you want to support. And adding a new language is as easy as creating a new text file of display labels. We will demonstrate the use of the API by building a simple method which displays a product entry for a shopping cart application. This will make use of a class of mine called ResourceBundleStore which is intended to optimize the display of internationalized data. You are free to use this class in your own projects.
June 6, 2000

The power and ease of use of the internationalization classes are further reasons to choose Java as a server-side language. And don't forget that Java handles text internally in Unicode, so just about every language under the sun can be represented as long as the client browser is capable of displaying the character set and handling any intermediate encodings that may be required.

A Brief Introduction to the API

java.util.Locale

A Locale object represents a geographical, political, or cultural region, and is used with the various Java classes that perform locale-specific operations. Its constructor takes an ISO language code and an ISO country code. It is simply an identifier and holds no information about how the country and language should be represented. The following line of code creates a Locale for British English.

Locale locale = new Locale("en", "GB");

java.text.Format

The Format class is the abstract parent of those classes that perform locale-specific formatting of dates, times, and numbers. The DateFormat class is used for parsing and formatting dates and times, and the NumberFormat class is used to handle things such as decimal points and thousands separators, which is useful for the display of currencies. Our sample method below will use the NumberFormat class for this purpose. NumberFormat is abstract, and an instance of a subclass is normally obtained by one of the NumberFormat.getInstance() methods.

java.util.ResourceBundle

A ResourceBundle is a container that a program can use to retrieve an object for a particular Locale. When a program needs locale-specific objects it makes a call to ResourceBundle.getBundle(). This first searches for subclasses of ResourceBundle with a name that points to the specified Locale. If none are found it goes on to search for properties files in the classpath that are named for the Locale. If it still can't find anything then it throws a MissingResourceException. The ResourceBundle class is abstract and you can either rely on it to use one of its own subclasses or you can subclass it yourself. The latter approach would be taken if you wanted to store locale-specific objects in a class. However, since we are only interested in displaying Strings we will take a far simpler approach and make use of the PropertyResourceBundle class, which is designed to load textual data from properties files. We never have to handle this class directly since the call to ResourceBundle.getBundle() will create an instance of it to store the Strings. The name of the properties file is very important and will be in the order <basename>_<language>_<country>. The call to ResourceBundle.getBundle("MyBaseName", new Locale("fr", "FR")) will attempt to retrieve the PropertyResourceBundle for the file with the name "MyBaseName_fr_FR.properties". (Actually there is far more to the lookup mechanism than this because it uses a search order and can settle for a default class or file if one exists. This is part of the real power of the API and you should consult the documentation for specific details on the naming patterns and search order.) The file is a standard properties file with name=value pairs, one per line, and it should be visible on the classpath otherwise it will not be found. Once the PropertyResourceBundle is loaded you can use getString(String key) to retrieve the required value.

The Drawbacks of Using PropertyResourceBundle in Servlets

There are two issues to be considered when using a PropertyResourceBundle in a servlet which my ResourceBundleStore class will address. The first is that file access is required to load the text, and we don't want this to occur at each client request. The second is that if you examine the source code of the class, you'll see that it stores the name-value pairs in a java.util.Properties object which is a subclass of java.util.Hashtable. The Collections Framework, new to Java 1.2, offers improved performance over older classes such as Vector and Hashtable by providing alternatives like ArrayList and HashMap that have unsynchronized access methods.

In a multi-threaded environment such as a servlet engine, threads have to wait to obtain a lock on a Hashtable before they can access its contents. With a busy web site and a large quantity of internationalized labels this would cause a degradation in performance. But by using a HashMap instead of a Hashtable we can avoid this problem. Our ResourceBundleStore class will therefore transfer the contents of the Hashtable to a HashMap. As long as the HashMap is not structurally modified it is safe to have multiple concurrent access. The problems arise when a key is added or removed while another thread is iterating over the contents of the map. But our ResourceBundleStore class simply accesses single mappings so there is no danger of a ConcurrentModificationException being thrown.

The ResourceBundleStore class

We could of course write our own simple lookup mechanism, but the ResourceBundle classes are powerful and extensible and so they should be utilized. The ResourceBundleStore is simply a wrapper around the PropertyResourceBundle which eliminates the performance worries of retreiving Strings while keeping the lookup functionality of the ResourceBundle API. It should be instantiated in the init() method of the servlet and given class scope so that each request does not create it anew. If you are using JSP, it should be used as a bean and given application scope.

ResourceBundleStore.java

import java.util.*;
import javax.servlet.*;

public class ResourceBundleStore {

private String strBaseName;
private HashMap localeDataHash; // The top level hash containing
//the second-level
// hashes for each Locale. The top-level key is
// the Locale object.

public ResourceBundleStore() {
localeDataHash = new HashMap();
}

public void setBaseName(String strBaseName) {
this.strBaseName = strBaseName;
}

// If the key is not found in the bundle, this method will return null.
public String getString(String strServletName,
String strKey,
Locale locale) throws ServletException {

// Check to see if the PropertyResourceBundle for this Locale has
//been loaded.
if(!localeDataHash.containsKey(locale)) {
try {
loadLocale(locale);
}
catch(MissingResourceException mre) {
throw new ServletException("The attempt to locate a resource file failed. ",
mre);
}
}
return (String)((HashMap)localeDataHash.get(locale)).get(strServletName + "." + strKey);

}

// This will load the resource bundle and add the data it contains
//to our top-level hash.
private void loadLocale(Locale locale) throws MissingResourceException {
ResourceBundle bundle = ResourceBundle.getBundle(this.strBaseName, locale);
HashMap secondaryHash = new HashMap();
Enumeration enum = bundle.getKeys();
while(enum.hasMoreElements()) {
String strKey = (String)enum.nextElement();
secondaryHash.put(strKey, bundle.getString(strKey));
}
// Now add the newly-created hash to our top-level hash.
localeDataHash.put(locale, secondaryHash);

}

}

Each ResourceBundleStore object holds all of the locale-specific data for a single web application (if the application is large it may be more convenient to break this down further and have one store per servlet). Each individual properties file contains all of the application's labels for a single Locale. The label identifiers are in the form <servlet_name>.<label_name>. The class is in the form of a bean with a no-argument constructor and a public SET method. On the first call to getString() for a particular Locale, all of its data is loaded and stored. Subsequent calls simply retrieve the String from the store and not via another call to the bundle. The PropertiesResourceBundle functionality is in the loadLocale() method, which uses the standard call to getBundle() and then enumerates through all of the keys and puts them along with their values into a HashMap which itself is put into the top-level HashMap with the Locale object as key.

A Sample Application

Let's look at how ResourceBundleStore can be used. Below is the code for a method that is part of a servlet which displays a list of items in a shopping basket. The method is passed the single instance of the ResourceBundleStore which it uses to retrieve two text labels. It also uses the NumberFormat class for displaying the currency.

private String getProductEntry(String strProductName,
double dblPrice,
int intQuantity,
Locale locale,
ResourceBundleStore rbs) throws ServletException {
StringBuffer sb = new StringBuffer();
sb.append("<TR><TD>");
sb.append(strProductName);
sb.append("</TD></TR>");
sb.append("<TR><TD>");
sb.append(rbs.getString(this.getClass().getName(),
"price_label",
locale));
sb.append(": ");
sb.append(NumberFormat.getCurrencyInstance(locale).format(dblPrice));
sb.append("</TD></TR>");
sb.append("<TR><TD>");
sb.append(rbs.getString(this.getClass().getName(),
"quantity_label",
locale));
sb.append(": " + intQuantity);
sb.append("</TD></TR>");
return sb.toString();

}

This is a rather artificial example. It is certainly not wise to create a new NumberFormat instance for each invocation of the method as I have done here, since this would introduce too much of a performance hit. The purpose of the code is to demonstrate the use of the class. And you would probably also want to convert the £ sign to its HTML character entity equivalent.

The contents of two sample properties files on the classpath are as follows.

MyApplication_en_GB.properties:

SampleServlet.price_label=price
SampleServlet.quantity_label=quantity

MyApplication_fr_FR.properties:

SampleServlet.price_label=prix
SampleServlet.quantity_label=quantité

Calling the method as getProductEntry("Product A", 9.99, 2, new Locale("en", "GB"), rbs) produces the following output (where rbs is the reference to the ResourceBundleStore instance):

Product A
price: £9.99
quantity: 2

And using getProductEntry("Product A", 9.99, 2, new Locale("fr", "FR"), rbs) results in:

Product A
prix: 9,99 F
quantité: 2

And that's how easy it is! The only difference between these two method invocations is the Locale object. It would be a good idea to store the Locale object as session object which is set when the user first enters the web application. And in a JSP you would include the labels in the HTML with a call like the following (where rbs is the reference to the bean instance of ResourceBundleStore):

<%= rbs.getString( . . .) %>

This article has demonstrated some of the advantages in using the Java internationaliation classes in servlets. We have only touched on a few possibilities, and we also have seen how it is sometimes necessary to adapt core classes before they are used in the context of server-side code, where performance is all-important.



Mark Webber is a Web Developer with Demon Internet, a brand of Thus plc. He is a Sun Certified Java Programmer.
Back to the Web Developer's Journal
Contact WDJ   •    Suits!   •    Propheads!   •    Ponytails!
Discuss   •    Subscribe   •    Search


internet.com

IT | Developer | Internet News | Small Business | Personal Technology | International | Search internet.com | Advertise | Corporate Info
Newsletters | Tech Jobs | E-mail Offers

internet.commerce
Be a Commerce Partner                                
  


The Network for Technology Professionals

Search:

About Internet.com

Legal Notices, Licensing, Permissions, Privacy Policy.
Advertise | Newsletters | E-mail Offers