Monday, January 19, 2009

dojo internationalization: easy as 1 .. 2 .. 7

The internationalization APIs in dojo are pretty similar to the internationalization support in Java - at least I found more similarities between dojo i18n and Java than I did between dojo i18n and PHP's gettext. However, getting up and running with dojo i18n support can be a little tricky. Here's a few simple steps I followed to get started with dojo internationalization.

1. Include the list of locales you want to support in your build script. I use Perl to build my dojo application, so it ended up looking a like this:


system("sh build.sh profileFile=$trunk/build/dojo/profile.js releaseDir=../../../build/$revision/ action=release version=$revision localeList=en-us,ja-jp");


2. Set the locale in the djConfig at the top of your page:


var djConfig = {
parseOnLoad: true,
usePlainJson: true,
locale: determineUserLocale()};


The determineUserLocale method here simply returns a locale in the format "en-us", "ja-jp" based on the user's preferences.

3. Wherever your dojo.require's usually are, add the following


dojo.requireLocalization("my.class", "i18n");


This is responsible for downloading a resource bundle called i18n.js which is located under the my.class module.

4. Create an I18n base class (any widget I use which needs internationalization support needs to extend from this widget):


dojo.provide("my.class.I18n");

dojo.require("dijit._Widget");
dojo.requireLocalization("my.class", "i18n");

dojo.declare(
"my.class.I18n",
[dijit._Widget],
{
statics: { i18n: {}},

preamble: function() {
this.statics.i18n = dojo.i18n.getLocalization("my.class", "i18n");
},

translate: function(key, params) {
params = dojo.isArray(params) ? params : [params];
return !params ? this.statics.i18n[key] : dojo.string.substitute(this.statics.i18n[key], params);
}
}


5. Included my.class.I18n in any widget which required internationalization support:


dojo.provide("my.class.TopNav");

dojo.require("my.class.I18n");

dojo.declare(
"my.class.TopNav",
[my.class.I18n, dijit._Templated],
{
templatePath: dojo.moduleUrl("my.class", "templates/TopNav.html"),

postCreate: function() {
...
},

onClick: function() {
...
},

_postApiCall: function(res) {
this.successNode.innerHTML = this.translate("success", [res]);
}


6. Altered my TopNav.html file to be automatically populated by internationalized strings:


${statics.i18n.homeLink}


7. Included internationalized strings in a file called i18n.js under the my.class directory:


homeLink: "Home",
success: "Success ${0} !",


Allowing different languages in the same application should be easy from here on in. All you need to do is set up your directory structure as follows:


my
class
nls
en-us
i18n.js
ja-jp
i18n.js


One option you have for switching between languages is to refresh the full page with the new locale passed in as a query string variable:


loadNewLanguage: function(newLocale) {
var oldSearch = "";
if(window.location.search.length > 0) {
if(window.location.search.indexOf("?Locale=") != -1) {
var localeToRemove = window.location.search.substring(window.location.search.indexOf("?Locale="), (window.location.search.indexOf("?Locale=") + 14));
oldSearch = "&" + window.location.search.replace(localeToRemove, "");
} else {
oldSearch = "&" + window.location.search.substring(1, window.location.search.length);
}
}
window.location = ((window.location.href.substring(0, window.location.href.indexOf(window.location.search)) + "?Locale=" + newLocale + oldSearch + window.location.hash));
}


The determineUserLocale() function mentioned at the top of this article will need to be able to prioritize and Locale query string parameters.

While these steps should get you up and running with dojo's internationalization APIs, there's plenty of i18n and l10n resources available directly on the dojo website. I found these links useful:

3 comments:

  1. Very Nice article.
    Enlightened my day.

    ReplyDelete
  2. thanks for the article... got a question though, how would you change the localization on the fly? you know, classy change language buttons? thanks.
    -Mike

    ReplyDelete
  3. @vajnorcan ... added some more code to the post which deals with reloading new locales.

    ReplyDelete