Internationalization (i18n)

We’ve been asked a couple of time at JavaONE how to deal with internationalization in DukeScript. It’s fairly simple. ViewModels are initialized on the Java side and we can use the normal ResourceBundle approach, but what about the html?

There’s no need to deal with the loading itself, DukeScript can do that for you. Just add a call to the locale method of BrowserBuilder:

public static void main(String... args) throws Exception {
        BrowserBuilder.newBrowser().
                loadPage("pages/index.html").
                locale(Locale.getDefault()).
                loadClass(Main.class).
                invoke("onPageLoad", args).
                showAndWait();
        System.exit(0);
    }

This will load the required variant of the file. E.g. on my machine the default locale is German. So it will look for index_de.html. You just need to provide the localized file. Otherwise the BrowserBuilder will use index.html as a fallback.

Using templates

In files with more text, this is maybe a bit tedious, especially since you always also need to update all data-bind attributes in all the files, and there’s no way to check the consistency.

In order to help with that I wrote a little Maven plugin that you can use to generate the required resources from a template. It’s not very polished, so I didn’t bother to publish it to a central repository, but you still might find it useful.

To use it clone it from github and build it, then in your dependant project add this:

<plugin>
    <groupId>com.dukescript</groupId>
    <artifactId>simple-i18n-maven-plugin</artifactId>
    <version>1.0-SNAPSHOT</version>
    <configuration>
        <inputDir>${basedir}/src/main/resources/webapp/pages/</inputDir>
        <outputDir>${basedir}/src/main/webapp/pages/</outputDir>
    </configuration>
    <executions>
            <execution>
                <id>bla</id>
                <phase>generate-resources</phase>
                <goals>
                    <goal>i18n</goal>
                </goals>
            </execution>
        </executions>
</plugin>

I decided to use the “convention instead of configuration” (cioc) pattern. This is a super pattern of “convention over configuration” (coc). The difference is, that in coc you can still configure things, in cioc you can’t, which naturally leads to increased stability and backward compatibility.

To use it on our example project create “/src/main/resources/webapp/pages/” in your project, and add cut and paste the index.html from the original location to there and rename to index.ftl.html :

 index.ftl.html

Next open the file and replace the Strings you would like to localize with freemarker syntax. Fortunately the demo app only contains one single String:

<h1>${title}</h1>

Now create the ResourceBundle files, e.g.:

bundle.properties bundle_de.properties bundle_it.properties

…and add the matching key value pair to the files: # bundle.properties title = title # bundle_de.properties title = Der Titel # bundle_it.properties title = il titolo

During the build the plugin will generate the files index.html, index_de.html, and index_it.html.

The approach will treat any file in the inputDir with this pattern as a template:

<name>.ftl.<extension>

So you can also use it for your knockout templates.

Enjoy DukeScript!