Welcome, guest ( Login )

WikiHome » HowToLocalizeWidgets

HowToLocalizeWidgets

Version 22, changed by peller 12/11/2006.   Show version history

OBSOLETE?  no.  needs to be moved to the book.


This document will show how to make a widget show strings in the user's native language.  As a prerequisite, the reader should be familiar with the InternationalizationOverview.  There are many aspects to internationalization, but perhaps the most obvious is to make sure that strings visible to the user are factored out from the code and made available as translations in the user's native language.  Dojo has a framework to provide such translations and load them on demand, and it works nicely with widget templates which allow you to substitute variables directly into the widget markup. As an example, we will use the validationtextbox widget, which was localized by changeset [5201]

Background

src/widget/templates/ValidationTextbox.html

The validationtextbox has three spans which contain strings.  (These strings were already parameterized, but let's pretend they were hard-coded as English strings)


    <span dojoAttachPoint='invalidSpan' class='$ {this.invalidClass}'>* The value entered is not valid.</span>

    <span dojoAttachPoint='missingSpan' class='$ {this.missingClass}'>* This value is required.</span>

    <span dojoAttachPoint='rangeSpan' class='$ {this.rangeClass}'>* This value is out of range.</span>

Providing translated resources

We want to pull these strings out and put them in a bundle so that we can provide translations.  So, we create a directory called "nls" under src/widget.  The nls directory has special meaning and is assumed to have a directory structure under it representing all the supported locales.  At the root of the directory is one or more fallback translation files.  We'll set that up as English.  It is essential to put something in the root so that you will provide support for all users.  In our example, this means that anyone who has a locale which we don't directly support will see English.  There's no need to put a copy of this file under nls/en by convention, as that would be redundant.  We'll call our bundle "validate" since it is used by the widget code by the same name.  Bundles are JSON property lists.  Javascript-style comments are allowed, and they may be necessary to provide hints or instructions to translation houses.

src/widget/nls/validate.js

1
({
2
                invalidMessage: "* The value entered is not valid.",
3
                missingMessage: "* This value is required.",
4
                rangeMessage: "* This value is out of range."
5
})

You'll want to provide translations for other languages, but in the least-specific manner possible.  For example, to translate Japanese, you'd probably want to put the strings under "ja" for Japanese, rather than "ja-jp" for Japanese spoken in Japan. Even though pretty much all web usage is probably the latter, it's just better form to leave things as generic as possible.  Country specific overrides are called variants and may be provided as sparse lists, so if there was a term that was used only by English speakers in Australia, you could provide that one property separately under en-au.

So, now we can provide a translation for the xx locale:

src/widget/nls/xx/validate.js will contain all of the strings which change, in this case all strings need to be translated.

1
({
2
                invalidMessage: "* xxxxxxx.",
3
                missingMessage: "* xxxxxxxx.",
4
                rangeMessage: "* xxxxxxxx."
5
})

If any upper-ASCII or double-byte characters are included, you must make sure to use UTF-8 encoding when you edit your file.  This is something you need to determine for your own editor; unfortunately, it seems there is no way to mark the encoding in SVN.  While UTF-8 is handled properly by most major browsers, there is a known bug in KHTML (Safari and Konqueror).  See ticket #1010 for a workaround.

Next, you might have a variant xx-yy on xx where only one of those strings changes.  src/widget/nls/xx-yy/validate.js:

1
({
2
                invalidMessage: "* yyyyyyyyyyy.",




3
})

Make sure to use lowercase for all your locale directories with dashes as separators, not underscores.  When xx-yy is loaded, it will pick up "missingMessage" and "rangeMessage" translations from the xx locale.  [Someone please help me here with some actual translated text!]

Using the translated resources in code

src/widget/validate.js

Now, we need to actually load this bundle into the widget object.  First, we need to declare the bundle at the top of the file:
dojo.requireLocalization("dojo.widget", "validate");

This says to look under the dojo.widget package at runtime for the translation in the user's locale and make sure it's loaded; the one we want is called validate.  Then we need to get and hold a reference to the generated object. This can be done in the postMixInProperties method with a single line:
    this.messages = dojo.i18n.getLocalization("dojo.widget", "validate", this.lang);

It looks a lot like the line you used above.  This merely grabs the appropriate Javascript hash object already in memory.  "this.lang" is the lang attribute on htmlwidget?.  If it is defined in the markup as an override, its value will be used as the locale instead of the user's default locale.  To use the getLocalization method, you need to put in the appropriate require at the top of the file:
dojo.require("dojo.i18n.common");

We're almost done.  Now, go back to the template

src/widget/tempaltes/ValidationTextbox.html

Let's replace those hard-coded English strings with indirect references to this.messages.  The strings are just properties on the object contained by this.messages.

5
        <span dojoAttachPoint='invalidSpan' class='$ {this.invalidClass}'>$ {this.messages.invalidMessage}</span>
6
        <span dojoAttachPoint='missingSpan' class='$ {this.missingClass}'>$ {this.messages.missingMessage}</span>
7
        <span dojoAttachPoint='rangeSpan' class='$ {this.rangeClass}'>$ {this.messages.rangeMessage}</span>

NOTE: Jot won't allow the $ {} syntax -- the space between the $ and the { should not be there!

Testing

You're ready to test.  Getting your browser to run in a locale other than your own is not easy, as most browsers don't let you change the language setting on the navigator object; it's usually fixed depending on what version of the browser you install.  Fortunately, you can insert a Dojo override into your test page to use a locale other than your own at runtime for testing:
djConfig = {locale: 'xx'}
If you wish to test multiple locales on the same page, use djConfig.extraLocale, which may take either a single locale or an array containing a list of locales.

Builds, performance, and deployment

Note that loading this widget now results in several hits over the network -- in addition to the hits for the widget class itself, all referenced Javascript, and the template, you now need to search for the nls file which may require several hits on its search path.  Just as the build compresses and folds all the Javascript into a single file, it will now do the same for your resources.  All the locales are flattened so that searching for variants is no longer necessary, and all used bundles are flattened into a single file per locale.  These files will be put under the "nls" directory next to dojo.js in the release/dojo directory.  Be sure to deploy this directory and its contents along with your Dojo build.

Attachments (0)

  File By Size Attached Ver.