If you take a look at the unit test for i18n at http://download.dojotoolkit.org/current-stable/dojo-release-1.2.2/dojo/tests/i18n.js you see that it uses three major tricks;
1. Load the i18n strings bundle of your choice using dojo.requireLocalization("tests","salutations",locale);
2. Get a specific bundle using var salutaions = dojo.i18n.getLocalization("tests", "salutations", "en");
3. Get the specific string for a given key using salutations['hello'];
Let's check the arguments for number (1) and (2; Only the first two are needed, which describe the dojo package to look for bundles in and the name of the bundle. If you want to specify another locale than the one the browser declares, it can be added as third argument, "sv" for Swedish, when the browser would say "en-us", et.c.
All well and good, but where do we put our different version of strings? As it turns out, in the dojo/test directory a directory named 'nls' can be found. In the root of that is a file called 'salutations.js'. This is the default key-value translation that i18n falls back on if the locale cannot be found.
Then comes a host of subdirectories ; zh, nl, il, dk, de, et.c et.c., one for each locale (that you want or can define). In each of these is a separate 'salutations.js' containing locale-specific resources.
The file format look like this;
{
it: "Italian",
ja: "Japanese",
ko: "Korean",
......
hello: "Hello",
dojo: "Dojo",
hello_dojo: "${hello}, ${dojo}!",
file_not_found:"The file you requested, ${0}, is not found."
}
for the default file, and like this in the 'it' subdirectory;
{
it: "italiano",
hello: "Ciao"
}
And that's it.
I began creating a small naive custom widget, which subtituted the content of the element where it is declared with the localized string found for the content used as key. It's not very fast, but simple to understand and use.
dojo.provide("layout.translate");
dojo.require("dijit._Templated");
dojo.require("dijit._Widget");
dojo.require("dojo.i18n");
dojo.declare("layout.translate", [ dijit._Widget ],
{
widgetsInTemplate : false,
string : "",
postCreate: function()
{
if (!this.string)
{
this.string = this.domNode.innerHTML;
}
console.log("postCreate for layout.translate called. locale == '"+dojo.locale+"'");
dojo.requireLocalization("layout", "salutations");
var res = dojo.i18n.getLocalization("layout", "salutations");
console.log("Translation key was '"+this.string+"'");
var str = res[this.string];
this.domNode.innerHTML = str;
}
});
Note that I just copied the whole nls directory from dojo/test for my own uses, and edited the files, leaving the original filename intact, just in case :) A better way of utilizing i18n would be to have a base class for all custom widgets, which read in a i18n bundle, and injects all keys into each class, so that every subclass has a lot of this._i18n_command_delete (If we have a naming convention that let all i18n keys begin with '_i18n_' for example).
Then we could have all custom widget templates just sprinkle their markup with a lot of ${_i18n_command_delete} and so on, which would pull in the current value of that 'this' property of the widget when it is rendered in the page.
Hmm....
Come to think of it, it seems to be possible for this to be put inside dijit._Widget, or possibly _Templated, which would make it spread to all custom widgets automatically. The only thing needed would be to prepend '_i18n_' to all key names, so that 'command_delete' inside a bundle file would become this_i18n_command_delete in the widget.
One would also need to have a convention that this only worked if the developer put a 'nls' directory under the package directory where widgets of a certain package are declared, following the order declared earlier.
Actually, this would be a pretty neat idea. Just my fault for using a blog post instead of TRAC to add feature requests! Oh, you mean I could do it myself? OK, I'll add it to the queue :)
Cheers,
PS
PS