[ Team LiB ] Previous Section Next Section

Using Resource Bundles in Web Pages

Java's I18N support includes objects known as resource bundles. When you create a multilingual application or Web site, you don't always want to make separate screens or pages for each language. For example, when you create an HTML form, the prompt strings can be in different languages, but the HTML for defining the form itself is the same no matter what language you use.

By using resource bundles, you can group various prompt strings and other objects that are locale dependent. When you create a resource bundle class, you decide on a base classname and then define each locale's resources in a class whose name is formed by adding the locale to the end of the classname.

For example, you might store some resources in a class called SomeResources. The French version of the resources would be in a class called SomeResources_fr, and the German version would be in a class called SomeResources_de. If you need to make a special German version of the resources tailored to Austria, you can put them in a class called SomeResources_de_AT.

Because writing resource bundles can be tedious, Java gives you some prebuilt framework classes. The ListResourceBundle class allows you to store the resources in an array of objects. Listing 22.4 shows an example ListResourceBundle. Notice that there is no locale at the end of the classname. That makes this class the default bundle if there is no bundle for the browser's locale.

Listing 22.4 Source Code for TestResources.java
package usingjsp;

import java.text.*;
import java.util.*;

public class TestResources extends ListResourceBundle
{
    public Object[][] getContents()
    {
        return contents;
    }

    final Object[][] contents =
    {
        { "namePrompt", "What is your name: " },
        { "agePrompt", "How old are you: " },
        { "placePrompt", "Where do you live: " },
        { "greetHeading", "Hello!" },
        { "welcomeText",
            "Welcome to our web site. Please take a moment to "+
            "fill out our survey" },
        { "submitButtonText", "Submit" }
    };
}

Listing 22.5 shows the German version of the TestResources resource bundle.

Listing 22.5 Source Code for TestResources_de.java
package usingjsp;

import java.util.*;
import java.text.*;

public class TestResources_de extends ListResourceBundle
{
    public Object[][] getContents()
    {
        return contents;
    }

    final Object[][] contents =
    {
        { "namePrompt", "Wie hei[gb]en Sie" },
        { "agePrompt", "Wie alt sind Sie: " },
        { "placePrompt", "Wo wohnen Sie: " },
        { "greetHeading", "Guten Tag!" },
        { "welcomeText",
            "Willkommen bei unserer Web-Site. Bitte, dauern Sie einen "+
            "Moment Um unsere Umfrage auszufüllen" },
        { "submitButtonText", "Senden" }
    };
}

Listing 22.6 shows a JSP that displays an HTML form using the prompts from the TestResources resource bundle. Notice that you don't need separate pages for each language. Only the prompts need to change.

Listing 22.6 Source Code for ResourceBundles.jsp
<%@ page language="java" import="java.text.*,java.util.*" %>
<%

// Get the default locale in case you can't determine the
// user's locale.
    Locale locale = Locale.getDefault();

// Get the browser's preferred language.
    String acceptLangString = request.getHeader("ACCEPT-LANGUAGE");

// Allow the user to override the browser's language setting. This
// lets you test with tools such as Babelfish (which isn't that great
// at translating to begin with).
    String override = request.getParameter("langOverride");

    if (override != null)
    {
        acceptLangString = override;
    }

// If there is an ACCEPT-LANGUAGE header, parse it.
    if (acceptLangString != null)
    {

// The accepted languages should be separated by commas, but also
// add space as a separator to eliminate whitespace.
        StringTokenizer localeParser = new StringTokenizer(
            acceptLangString, " ,");

// See whether a language is in the list (you need only the first one).
        if (localeParser.hasMoreTokens())
        {
// Get the locale.
            String localeStr = localeParser.nextToken();

// The locale should be in the format ll-CC where ll is the language
// and CC is the country, like en-US for English in the U.S. and
// de-DE for German in Germany. Allow the browser to use _ instead
// of -, too.
            StringTokenizer localeSplitter = new StringTokenizer(
                localeStr, "_-");

// Assume both values are blank.
            String language = "";
            String country = "";

// See where a language is specified.
            if (localeSplitter.hasMoreTokens())
            {
                language = localeSplitter.nextToken();
            }

// See whether a country is specified (there won't always be one).
            if (localeSplitter.hasMoreTokens())
            {
                country = localeSplitter.nextToken();

            }

// Create a locale based on this language and country (if country is
// blank, you'll still get locale-based text, but currencies won't
// display correctly).
locale = new Locale(language, country);
        }
    }

// Get the bundle of resource strings for this locale.
    ResourceBundle resources = ResourceBundle.getBundle(
        "usingjsp.TestResources", locale);
%>
<html>
<body>
<h1><%= resources.getString("greetHeading")%></h1>
<p>
<%= resources.getString("welcomeText")%>:
<p>
<form action="your_form_handler_here" method="post">

<%=resources.getString("namePrompt")%>
<input type="text" name="name"><br>

<%=resources.getString("agePrompt")%>
<input type="text" name="age"><br>

<%=resources.getString("placePrompt")%>
<input type="text" name="place"><br>

<p>
<input type="submit" value="<%=resources.getString("submitButtonText")%>">
</form>
</body>
</html>

Figure 22.6 shows the ResourceBundles JSP running in a browser with a preferred language of English.

Figure 22.6. Resource bundles let you customize parts of a JSP or servlet.

graphics/22fig06.gif

Figure 22.7 shows the ResourceBundles JSP running in a browser with a preferred language of German.

Figure 22.7. The ResourceBundle class locates a resource bundle for a particular locale.

graphics/22fig07.gif

Although the ListResourceBundle class makes it easy to customize various items in a Web page, the PropertyResourceBundle class makes it even easier. The PropertyResourceBundle class lets you store locale-specific strings in a properties file rather than a Java class, making it much easier to customize the resources. All you need to do to use the PropertyResourceBundle class is to create a properties file with lines of the form name=value. Listing 22.7 shows a properties file defining the same resource names as TestResources.java. Make sure the properties file ends with .properties. The ResourceBundle class specifically looks for files with the .properties extension.

Listing 22.7 Source Code for TestResourceProps.properties
namePrompt=What is your name:
agePrompt=How old are you:
placePrompt=Where do you live:
greetHeading=Hello!
welcomeText=Welcome to our Web site.
        Please take a moment to fill out our survey
submitButtonText=Submit

Listing 22.8 shows the German version of the properties file. Notice that you just need to append the language to the end of the name of the properties file, right before the .properties extension.

Listing 22.8 Source Code for TestResourceProps_de.properties
namePrompt=Wie hei[gb]en Sie:
agePrompt=Wie alt sind Sie:
placePrompt=Wo wohnen Sie:
greetHeading=Guten Tag!
welcomeText= Willkommen bei unserer Web-Site.
        Bitte, dauern Sie einen Moment Um unsere Umfrage auszufüllen
submitButtonText=Senden

The beauty of the PropertyResourceBundle class is that it treats the files as if they were classnames. That is, you just need to put the properties files somewhere in your classpath and call ResourceBundle.getBundle by using the base name of the properties file (such as TestResourceProps).

Instead of using the TestResources class, you need to change the getBundle statement in ResourceBundles.jsp to support properties files:


ResourceBundle resources = ResourceBundle.getBundle(
    "TestResourceProps", locale);

Class Comes Before Precedence

graphics/bytheway_icon.gif

If you have a properties file named TestResourceProps.properties and a class named TestResourceProps, the class takes precedence over the properties file. The ResourceBundle class loads the TestResourceProps class rather than the properties file.


    [ Team LiB ] Previous Section Next Section