Get 10$ Digital Ocean SSD Hosting Credit for free.

GWT UiBinder I18n – Tutorial – The easy way!

The Problem with UiBinder i18n

gwt-logo

Anyone who tried to internationalize a GWT application that uses UiBinder at some point got to the official documentation page:
http://www.gwtproject.org/doc/latest/DevGuideUiBinderI18n.html

In very short the official way of doing UiBinder i18n according to the documentation looks like this:

  • Add three attributes to EVERY UiBinder ui.xml
  • Mark every text you want to translate with a ui:msg or ui:attributes tag
  • Run the compiler with the “-extras” flag to auto generate property files containing the key/message pairs used for translation
  • Copy those generated property files from the extras folder into your project
  • There is one property file per language per UiBinder xml file
  • Keys are incomprehensible MD5 hashes

It took me a while to understand what is going on here. Not a very convenient and straight forward way in my opinion!
Even the official documentation has a hard time to take itself seriously:

(…)run the gwt compiler with -extra /tmp/gwt-extras; you’ll find the file in /tmp/gwt-extras/com.example.app.App/com.example.app.client.HelloBinderImplGenMessages.properties. No kidding. Hopefully this will be cleaned up in a future release of the toolkit.

What UiBinder i18n should be like

For me the basic straight forward way of i18n should be:

  • Create key/value property files for every language
  • Access the messages in UiBinder via the key
  • The key is human readable
  • One property file per language per module

What if I told you, you can actually do this easily with GWT UiBinder?
whatif
The magic key word here is a bit hidden in the developer guide: ui:baseMessagesInterface See the documentation:

ui:baseMessagesInterface
Sets the base interface to use for generated messages. The value must be the fully-qualified class name of an interface that extends Messages. You can then put whatever annotations you want there, making it easy to have company or project-wide settings that can be changed in just one place. You can still use the other attributes to override defaults inherited from that interface if necessary.

Example

What follows is a short example how this style of i18n would look like

WelcomePanel.ui.xml

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
             xmlns:g='urn:import:com.google.gwt.user.client.ui'
             ui:baseMessagesInterface="com.sebastianmetzger.gwt.client.i18n.WelcomeMessages">

    <ui:style>
        .wrapper {
            padding: 64px;
        }
    </ui:style>

    <g:HTMLPanel styleName="{style.wrapper}">
        <h1><ui:msg key="heading">Not translated</ui:msg></h1>
        <p><ui:msg key="greeting">Not translated</ui:msg></p>
    </g:HTMLPanel>
</ui:UiBinder>

Notice the ui:baseMessagesInterface attribute in the ui:UiBinder tag, which points at com.sebastianmetzger.gwt.client.i18n.WelcomeMessages

WelcomeMessages.java

package com.sebastianmetzger.gwt.client.i18n;

import com.google.gwt.i18n.client.Messages;

public interface WelcomeMessages extends Messages {
    // Only add Messages here, you need to access outside of UiBinder
}

Note that it is not necessary to explicitly add the keys to the Java interface. They will be taken directly from the property files for UiBinder. You will need to put the messages into the interface, if you want to access the translations from anywhere else though.

WelcomeMessages_en.properties

heading = Welcome
greeting = Can I offer you a juicy hamburger?

WelcomeMessages_de.properties

heading = Willkommen
greeting = Möchten Sie eine leckere Schweinshaxe essen?

Note: The property files have to be in the same package as the corresponding Messages interface to be mapped automatically.

The Result

English version - Locale: en

English version – Locale: en

German version - locale: de

German version – locale: de

Dependent on the set locale the UiBinder template is now filled with the translated messages. Neat!

Get the Example from GitHub

I put the example project into a public github repo. Feel free to use it as a template!

Clone it

git clone https://github.com/Sturmination/gwt_uibinder_i18n

Build and run it (requires Maven)

gwt_uibinder_i18n/mvn clean jetty:run-exploded