Chapter 11. Localization

Table of Contents

Home Page
Change page
Other Options for Localization

One of the most powerful and useful features of the Tapestry framework is the way in which it assists with localization of a web application. This is normally an ugly area in web applications, with tremendous amounts of ad-hoc coding necessary.

Because Tapestry does such a strong job of seperating the presentation of a component (its HTML template) from its control logic (its specification and Java class) it becomes easy for it to perform localization automatically. It's as simple as providing additional localized HTML templates for the component, and letting the framework select the proper one.

However, the static text of an application, provided by the HTML templates, is not all.

Applications also have assets (images, stylesheets and the like) that must also be localized: that fancy button labeled "Search" is fine for your English clients, but your French clients will require a similar button labeled "Recherche".

Again, the framework assists, because it can look for localized versions of the assets as it runs.

The locale application demostrates this. It is a very simply application that demonstrates changing the locale of a running application [7]

The Home page of the application allows you to select a new language for the application:

Figure 11.1. Locale Home Page

Selecting "German" from the list and clicking the "Change" button brings you to a new page that acknowledges your selection:

Figure 11.2. Locale Changed (German)

Clicking the button (it's labeled "Select Another" in German) returns you to the Home page to select a new language:

Figure 11.3. Locale Home Page (German)

The neat thing here is that the Home page has been localized into German as well; it shows equivalent German text, the options in the popup list are in German, and the "Change" button has been replaced with a German equivalent.

Home Page

The Home page consists of a single component specification, four versions of the HTML template and four image assets.

Figure 11.4. Home.jwc

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE specification PUBLIC 
  "-//Howard Ship//Tapestry Specification 1.1//EN" 
  "http://tapestry.sf.net/dtd/Tapestry_1_1.dtd">
<specification class="tutorial.locale.Home">

  <component id="border" type="Border"/>

  <component id="form" type="Form">
    <binding name="listener" property-path="formListener"/>
    <field-binding name="stateful" field-name="Boolean.FALSE"/>
  </component>

  <component id="inputLocale" type="PropertySelection">
    <binding name="value" property-path="selectedLocale"/>
    <binding name="model" property-path="localeModel"/>
  </component>

  <component id="changeButton" type="ImageSubmit">
    <binding name="image" property-path="assets.change-button"/>
  </component>

  <private-asset name="change-button" resource-path="/tutorial/locale/Change.gif"/>

</specification>

The changeButton component is an ImageSubmit, a Tapestry version of an <input type="image"> HTML form element. We provide it with an image, an asset that will be used as the src attribute of the HTML tag

The property path assets.change-button is a convienience; each component may have a number of named assets and has an assets property that is a Map of those assets.

We also must define the asset, naming it change-button. We declare it as a private asset, an asset that is not directly visible to the servlet container, but is instead packaged with the Java classes in a JAR or in the WEB-INF/classes directory of a WAR.

In fact, there are four files in that directory, named Change.gif, Change_de.gif, Change_fr.gif and Change_it.gif. Those suffixes (_de, _fr, etc.) identify the locale for which the image is appropriate.

More information on those suffixes is available from the java.util.Locale documentation.

When Tapestry is rendering the page, it knows what locale is currently selected (it's a property of the engine object) and chooses the correct file based on that.

Along with the four images, there are four HTML templates.

Figure 11.5. Home.html (English)

<jwc id="border">

This tutorial demonstration how to dynamically change the locale
for the running application.

<p>
Select a new locale:

<jwc id="form">
	<jwc id="inputLocale"/>
	<jwc id="changeButton"/>
</jwc>

</jwc>

The alternate locale versions are named in the same pattern as the image asset files.

Figure 11.6. Home_de.html (German)

<jwc id="border">

Diese Referentendemonstration, wie man dynamisch
das locale f&#252;r die laufende Anwendung &#228;ndert.

<p>
W&#228;hlen Sie ein neues locale aus:

<jwc id="form">
	<jwc id="inputLocale"/>
	<jwc id="changeButton"/>
</jwc>

</jwc>

The ids of components are consistent regardless of the locale used; these are internal ids (the equivalent of variable names) and are not shown to the end user. In addition, there's only one specification file and the ids here must match the ids in the specification.

The only real different between the files is the static text which, here, is in German.

Again, when Tapestry is rendering the page, it first chooses the correct localized HTML template. When it is rendering the changeButton component, it finds the correct localized file. It all comes together to consistently display the localized images and text.

What if there isn't a localization of a template or file? Tapestry will use the more general file. For instance, if we somehow managed to convince the application that we spoke Spanish we would see mostly English text since we didn't provide Spanish localized templates or assets.

The Java code for the Home page is simple enough that we can largely skip it. The only interesting parts are providing a property selection model for the inputLocale component and responding when the form is submitted:

Figure 11.7. Home.java (excerpt)

    
  
  public void actionTriggered(IComponent component, IRequestCycle cycle)
    throws RequestCycleException
    {
        getEngine().setLocale(selectedLocale);

        cycle.setPage("Change");
    }


[7] All the translations were performed using Babelfish, and are probably quite laughable to someone who actually speaks the alternate languages.