i18n
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.
Note: To run through the steps to internationalize a sample GWT app, see the tutorial Internationalizing a GWT Application.
- Locales in GWT
- Static String Internationalization
- Dynamic String Internationalization
- Java Annotations
- Localized Properties Files
Quick Start with Internationalization
GWT supports a variety of ways of internationalizing your code. Start by researching which approach best matches your development requirements.
- Are you using UiBinder?
If so, you will probably want to read up on UiBinder's I18n support.
-
Are you writing code from scratch?
If so, you will probably want to read up on GWT's static string internationalization techniques.
-
Do you want to store non-String localized values ?
Use the Constants or ConstantsWithLookup interfaces, which allow types such as primitives, String arrays, and String maps.
-
Do you need to substitute parameters into the translated messages?
Use Messages.
-
Do you have existing localized properties files you'd like to reuse?
The i18nCreator tool can automatically generate interfaces that extend either Constants, ConstantsWithLookup 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 and just not having any locale-specific property files.
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
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, ConstantsWithLookup, and Messages.
-
Dynamic string internationalization
A simple 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.
-
Extending or implementing Localizable
Provides a method for 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 the Localizable class documentation.
The I18N Module
Core types related to internationalization:
-
LocaleInfo
Provides information about the current locale. -
Constants
Useful for localizing typed constant values -
Messages
Useful for localizing messages requiring arguments -
ConstantsWithLookup
LikeConstants
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 or when the classes above don't provide sufficient control -
DateTimeFormat
Formatting dates as strings. See the section on date and number formatting. -
NumberFormat
Formatting numbers as strings. See the section on date and number formatting.
Locales in GWT
GWT is different than most toolkits by performing most locale-related work at compile time rather than runtime. This allows GWT to do compile-time error checking, such as when a parameter is left out or the translated value is not of the correct type, and for optimizations to take into account known facts about the locale. This also allows an end user to download only the translations that are relevant for them.
For details on configuring locales in your GWT application, see the detailed locale documentation.
Static String Internationalization
Static string internationalization is the most efficient way to localize your application for different locales in terms of runtime performance. This approach is called "static" because it refers to creating tags that are matched up with human readable strings at compile time. At compile time, mappings between tags and strings are created for all languages defined in the module. The module startup sequence maps the appropriate implementation based on the locale setting using deferred binding.
Static string localization relies on code generation from standard Java properties files or annotations in the Java source. GWT supports static string localization through three tag interfaces (that is, interfaces having no methods that represent a functionality contract) and a code generation library to generate implementations of those interfaces.
Extending the Constants Interface
The Constants
interface
allows you to localize constant values in a type-safe manner, all resolved
at compile time. At some cost of runtime overhead, you can also allow runtime
lookup by key names with the ConstantsWithLookup
interface.
Using the Messages Interface
The Messages
interface
allows you to substitute parameters into messages and to even re-order those
parameters for different locales as needed. The format of the messages in the
properties files follows the specification in Java MessageFormat.
The interface you create will contain a Java
method with parameters matching those specified in the format string.
In addition, the Messages
interface supports Plural Forms to allow your application
to accurately reflect text changes based on the count of something.
Which Interface to Use?
Here are some guidelines to help choose the right interface for your application's needs:
-
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 anint
, its associated property is guaranteed to be a validint
value — avoiding a potential source of runtime errors. -
The
ConstantsWithLookup
interface is identical toConstants
except that the interface also includes a method to look up values 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 thanConstants
because the compiler cannot discard unused constant methods, resulting in larger applications and the lookup cannot be resolved at compile-time. -
Extend
Messages
to create a collection of formatted messages that can accept parameters. You might think of theMessages
interface as a statically verifiable equivalent of the traditional Java combination ofProperties
,ResourceBundle
, andMessageFormat
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 allows for UTF-8 and therefore allows properties files to contain Unicode characters directly.
Dynamic String Internationalization
For existing applications that may not support the GWT locale
client property, GWT offers dynamic string internationalization to easily
integrate GWT 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 internationalization 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 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.
Java Annotations
The recommended approach for specifying the default values for
Constants
or Messages
interfaces is using Java annotations.
The advantage of this approach is that you can keep the values with the
source, so when refactoring the interface or creating new methods in your IDE
it is easier to keep things up to date. Also, if you are using a
custom key generator or generating output files for translation, you
need to use annotations.
The annotations that apply everywhere are discussed here — for annotations
that are only used on Constants
and Messages
are
discussed there.
Class Annotations
The following annotations apply to classes or interfaces:
-
@DefaultLocale(String localeName)
Specifies that text contained in this file is of the specified locale. If not specified, the default isen
. -
@GeneratedFrom(String fileName)
Indicates that this file was generated from the supplied file. Note that it is not required that this file name be resolvable at compile time, as this file may have been generated on a different machine, etc. If the generator does check the source file, such as for staleness, it must not give any warning if the file is not present or if the name is not resolvable. -
@GenerateKeys(String generatorFQCN)
Requests that the keys for each method be generated with the specified generator (see below). If this annotation is not supplied, keys will be the name of the method, and if specified without a parameter it will default to the MD5 implementation.
The specified generator class must implement the
KeyGenerator
interface. By specifying a fully-qualified class name,
this will be extensible to other formats not in the GWT namespace. The
user just has to make sure the specified class is on the class path at
compilation time.
This allows integration with non-standard or internal tools that may use their own
hash functions to coalesce duplicate translation strings between multiple
applications or otherwise needed for compatibility with external tools.
A string containing the fully-qualified class name is used instead of a class literal because the key generation algorithm is likely to pull in code that is not translatable, so cannot be seen directly in client code.
If this annotation is not supplied, the key will be the simple name of the method.
@Generate(String[] formatFQCN, String filename, String[] locales)
Requests that a message catalog file is generated during the compilation process. If the filename is not supplied, a default name based on the interface name is used. The output file is created under the -out directory. The format names are the fully-qualified class names which implement theMessageCatalogFormat
interface. For example, this could generate an XLIFF or properties file based on the information contained in this file. SpecificMessageCatalogFormat
implementations may define additional annotations for additional parameters needed for thatMessageCatalogFormat
.
If any locales are specified, only the listed
locales are generated. If exactly one locale is listed, the filename supplied
(or generated) will be used exactly; otherwise locale
will
be added before the file extension.
A string containing the fully-qualified class name is used instead of a class literal because the message catalog implementation is likely to pull in code that is not translatable, so cannot be seen directly in client code.
Method Annotations
The following annotations apply to methods:
@Key(String key)
Specifies the key to use in the external format for this particular method. If not supplied, it will be generated based on the@GenerateKeys
annotation, discussed above.@Description(String desc)
A description of the text. Note that this is not included in a hash of the text and depending on the file format may not be included in a way visible to a translator.@Meaning(String meaning)
Supplies a meaning associated with this text. This information is provided to the translator to distinguish between different possible translations — for example, orange might have meaning supplied as "the fruit" or "the color". Note that two messages with identical text but different meanings should have different keys, as they may be translated differently.
Localized Properties Files
Static string internationalization uses traditional Java .properties
files to manage
translating tags into localized values. These files may be placed into the same package as your main module class. They must be placed in the same package as their corresponding
Constants
/Messages
subinterface definition file.
Tip: Use the i18nCreator script to get started.
$ i18nCreator -eclipse Foo com.example.foo.client.FooConstants
Created file src/com/example/foo/client/FooConstants.properties
Created file FooConstants-i18n.launch
Created file FooConstants-i18n
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.
In order to use internationalized characters, make sure that your host HTML page is served as UTF-8, the easiest way is to include a meta tag in the page's head:
<meta charset="utf-8" />
You must also ensure that all relevant source and .properties
files are set to be in the UTF-8 charset in your IDE.