Localization in GWT

In simple Java application you have a standard approach to read the localized string:

Locale currentLocale = new Locale("fr", "CA", "UNIX")
ResourceBundle labels = ResourceBundle.getBundle("ButtonLabel", currentLocale);

You can easily get the localized string

String buttonLabel = ButtonLabel.getString("buttons.OK");

The bad thing here is that you manipulate with string and such a string can probably do not exist in the properties file and you’ll be able to see it only after running application. You can’t detect this problem in the compile time.

The good thing here is that you can build this string dynamically. Lets say you have an enum with button type. You can easily get button label like:


String buttonLabel = ButtonLabel.getString("buttons." + button.getByttonType());

GWT localization stuff is a bit different. If you’re using Maven to build your project you have a bunch of properties files and the following code in your pom.xml:

<i18nMessagesBundles><i18nMessagesBundle>org.test.YourBundle</i18nMessagesBundle></i18nMessagesBundles>

GWT plugin creates an interface for you during compilation. This interface describes corresponding property names as methods:

public interface YourBundle extends com.google.gwt.i18n.client.Messages {
@DefaultMessage("Ok")
@Key("buttons.Ok")
String buttonsOk();
...

Now the labels are strong typed and the bad thing is eliminated. But what about a good thing? It has dissappeared too. GWT does not support reflection and the generated interface does not have method to get data by string key.

At first I tried to use gwt-dmesg to make the behaviour more dynamic, but I was unable to make it work. Finally I’ve discovered some native functionality provided by GWT. You can change i18nMessagesBundle with i18nConstantsWithLookupBundle and it will provide you the required flexibility:

<i18nConstantsWithLookupBundles><i18nConstantsWithLookupBundle>org.test.YourBundle</i18nConstantsWithLookupBundle></i18nConstantsWithLookupBundles>

The interface generated during compilation looks like:

public interface YourBundle extends com.google.gwt.i18n.client.ConstantsWithLookup {
@DefaultMessage("Ok")
@Key("buttons.Ok")
String buttonsOk();
...
}

Nothing special. But if we look at ConstantsWithLookup – we’ll see:

public interface ConstantsWithLookup extends Constants {
...
String getString(String methodName) throws MissingResourceException;
...
}

This method does exactly what you want. You can simply call the next code to get localized data:

String buttonLabel = GWT.create(YourBundle.class).getString("buttons." + button.getByttonType());

However it still has some limitations. You can’t use parametrized strings with this approach. It works nice in our case since we don’t have combination of dynamic retrieval and parameterized labels simultaneously.