Internationalization

Internationalization

Easily support multiple locales with a single code base.

Contents

Overview

GWT includes a flexible set of tools to help you internationalize your applications and libraries. GWT internationalization support provides a variety of techniques to internationalize strings, typed values, and classes.

Getting Started

Since GWT supports a variety of ways of internationalizing your code, begin by researching which approach best matches your development requirements.

Are you writing code from scratch?
If so, you'll probably want to read up on GWT's static string internationalization techniques.

Do you want to internationalize mostly settings or end-user messages?
If you have mostly settings (the kind of thing for which you'd normally use simple properties files), consider Constants. If you have a lot a of end-user messages, then Messages is probably what you want.

Do you have existing localized properties files you'd like to reuse?
The i18nCreator tool can automatically generate interfaces that extend either Constants or Messages.

Are you adding GWT functionality to an existing web application that already has a localization process defined?
Dictionary will help you interoperate with existing pages without requiring you to use GWT's concept of locale.

Do you really just want a simple way to get properties files down to the client regardless of localization?
You can do that, too. Try using Constants without specifying a locale.

Internationalization Techniques

GWT offers multiple internationalization techniques to afford maximum flexibility to GWT developers and to make it possible to design for efficiency, maintainability, flexibility, and interoperability in whichever combinations are most useful.

Static string internationalization refers to a family of efficient and type-safe techniques that rely on strongly-typed Java interfaces, properties files, and code generation to provide locale-aware messages and configuration settings. These techniques depend on the interfaces Constants and Messages.

At the other end of the spectrum, dynamic string internationalization is a simplistic and flexible technique for looking up localized values defined in a module's host page without needing to recompile your application. This technique is supported by the class Dictionary.

Using an approach similar to static string internationalization, GWT also supports internationalizing sets of algorithms using locale-sensitive type substitution. This is an advanced technique that you probably will not need to use directly, although it is useful for implementing complex internationalized libraries. For details on this technique, see Localizable.

The I18N Module

The core types related to internationalization reside in the com.google.gwt.i18n package:
  • Constants
    Useful for localizing typed constant values
  • Messages
    Useful for localizing messages requiring arguments
  • ConstantsWithLookup
    Like Constants but with extra lookup flexibility for highly data-driven applications
  • Dictionary
    Useful when adding a GWT module to existing localized web pages
  • Localizable
    Useful for localizing algorithms encapsulated in a class

The GWT internationalization types are included in the module com.google.gwt.i18n.I18N. To use any of these types, your module must inherit from it:

 


Static String Internationalization

Static string localization relies on code generation from properties files. GWT supports static string localization through two tag interfaces (that is, interfaces having no methods that represent a functionality contract) and a code generation library to generate implementations of those interfaces.

For example, if you wanted to localize the constant strings "hello, world" and "goodbye, world" in your GWT application, you could define an interface that abstracts those strings by extending the built-in Constants interface:

public interface MyConstants extends Constants {

String helloWorld();
String goodbyeWorld();
}
Now create an associated default properties file called MyConstants.properties in the same package:
helloWorld = hello, world

goodbyeWorld = goodbye, world
You can also create a localized translation for each supported locale in separate properties file. In this case, we localize for Spanish:
helloWorld = hola, mundo

goodbyeWorld = adiĆ³s, mundo
To use the internationalized constants, you create an implementation of MyConstants using GWT.create(Class):
public void useMyConstants() {

MyConstants myConstants = (MyConstants) GWT.create(MyConstants.class);
Window.alert(myConstants.helloWorld());
}

The Benefits of Static String Internationalization

As you can see from the example above, static internationalization relies on a very tight binding between internationalized code and its localized resources. Using explicit method calls in this way has a number of advantages. The GWT compiler can optimize deeply, removing uncalled methods and inlining localized strings -- making generated code as efficient as if the strings had been hard-coded.

The value of compile-time checking becomes even more apparent when applied to messages that take multiple arguments. Creating a Java method for each message allows the compiler to check both the number and types of arguments supplied by the calling code against the message template defined in a properties file. For example, attempting to use this interface:

public interface ErrorMessages extends Messages {

String permissionDenied(int errorCode, String username);
}
with this properties file:
permissionDenied = Error {0}: User {1} does not have permission to access {2} 
results in a compile-time error because the message template in the properties file expects three arguments, while the permissionDenied method can only supply two.

Which Interface to Use?

Extend Constants to create a collection of constant values of a variety of types that can be accessed by calling methods (called constant accessors) on an interface. Constant accessors may return a variety of types, including strings, numbers, booleans, and even maps. A compile-time check is done to ensure that the value in a properties file matches the return type declared by its corresponding constant accessor. In other words, if a constant accessor is declared to return an int, its associated property is guaranteed to be a valid int value -- avoiding a potential source of runtime errors.

ConstantsWithLookup is identical to Constants except that the interface also includes a method to look up strings by property name, which facilitates dynamic binding to constants by name at runtime. ConstantsWithLookup can sometimes be useful in highly data-driven applications. One caveat: ConstantsWithLookup is less efficient than Constants because the compiler cannot discard unused constant methods, resulting in larger applications.

Extend Messages to create a collection of formatted messages that can accept parameters. You might think of the Messages interface as a statically verifiable equivalent of the traditional Java combination of Properties, ResourceBundle, and MessageFormat rolled into a single mechanism.

Properties Files

All of the types above use properties files based on the traditional Java properties file format, although GWT uses an enhanced properties file format that are encoded as UTF-8 and can therefore contain Unicode characters directly.

Dynamic String Internationalization

The Dictionary class lets your GWT application consume strings supplied by the host HTML page. This approach is convenient if your existing web server has a localization system that you do not wish to integrate with the static string methods. Instead, simply print your strings within the body of your HTML page as a JavaScript structure, and your GWT application can reference and display them to end users.

Since it binds directly to the key/value pairs in the host HTML, whatever they may be, the Dictionary class is not sensitive to the the GWT locale setting. Thus, the burden of generating localized strings is on your web server.

Dynamic string localization allows you to look up localized strings defined in a host HTML page at runtime using string-based keys.

This approach is typically slower and larger than the static string approach, but does not require application code to be recompiled when messages are altered or the set of locales changes.

Tip
The Dictionary class is completely dynamic, so it provides no static type checking, and invalid keys cannot be checked by the compiler. This is another reason we recommend using static string internationalization where possible.

Specifying a Locale

GWT represents locale as a client property whose value can be set either using a meta tag embedded in the host page or in the query string of the host page's URL. Rather than being supplied by GWT, the set of possible values for the locale client property is entirely a function of your module configuration.

If that sounded like gibberish (and it probably did), a quick digression into the purpose of client properties is in order...

Client Properties and the GWT Compilation Process

Client properties are key/value pairs that can be used to configure GWT modules. User agent, for example, is represented by a client property. Each client property can have any number of values, but all of the values must be enumerable when the GWT compiler runs.

GWT modules can define and extend the set of available client properties along with the potential values each property might assume when loaded in an end user's browser. At compile time, the GWT compiler determines all the possible permutations of a module's client properties, from which it produces multiple compilations. Each compilation is optimized for a different set of client properties and is recorded into a file ending with the suffix .cache.html.

In deployment, the end-user's browser only needs one particular compilation, which is determined by mapping the end user's client properties onto the available compiled permutations. Thus, only the exact code required by the end user is downloaded, no more. By making locale a client property, the standard startup process in gwt.js chooses the appropriate localized version of an application, providing ease of use (it's easier than it might sound!), optimized performance, and minimum script size.

The Default Locale

The com.google.gwt.i18n.I18N module defines only one locale by default, called default. This default locale is used when the locale client property goes unspecified in deployment. The default locale is used internally as a last-resort match between a Localizable interface and a localized resource or class.

Adding Locale Choices to a Module

In any real-world application, you will define at least one locale in addition to the default locale. "Adding a locale" means extending the set of values of the locale client property using the element in your module XML.

For example, the following module adds multiple locale values:
































Choosing a Locale at Runtime

The locale client property can be specified using either a meta tag or as part of the query string in the host page's URL. If both are specified, the query string takes precedence.

To specify the locale client property using a meta tag in the host page, embed a meta tag for gwt:property as follows:

For example, the following host HTML page sets the locale to "ja_JP":









To specify the locale client property using a query string, specify a value for the name locale. For example,

http://www.example.org/myapp.html?locale=fr_CA

Localized Properties Files

Both Constants and Messages use traditional Java properties files, with one notable difference: properties files used with GWT should be encoded as UTF-8 and may contain Unicode characters directly, avoiding the need for native2ascii. See the API documentation for the above interfaces for examples and formatting details.

Many thanks to the Tapestry project for solving the problem of reading UTF-8 properties files in Tapestry's LocalizedProperties class.

0 comments: