当前位置 : 主页 > 网页制作 > Dojo >

Internationalization with the Dojo Toolkit

来源:互联网 收集:自由互联 发布时间:2021-06-15
In this tutorial, you'll learn how the Dojo Toolkit supports internationalization (i18n), including the useof dictionaries for string substitution, and how basic locale formatting for things such as Dateobjects, numbers and currencies are s

In this tutorial, you'll learn how the Dojo Toolkit supports internationalization (i18n), including the useof dictionaries for string substitution, and how basic locale formatting for things such as Dateobjects, numbers and currencies are supported.

  • Difficulty: Intermediate
  • Dojo Version: 1.6

Getting Started

Creating a web application for a specific target market is usually a daunting task, but libraries such as the Dojo Toolkitease that task by providing tools to quicklyassemble userinterfaces (i.e. Dijit), supporting code to easethe pain of cross-browsercompatibility, and various add-ons/plug-insfor specific functionality such as the DojoX Charting package.

No such toolkit would be complete without the ability to localize an application—in other words, the ability foran application to be presented using language based on the location of the application's user. The Dojo Toolkit provides thisability for application developers through the use of dojo.i18n.

A Short History

In software development, two terms are used when discussing the ability to display application elements based on a user's locale:internationalization (or i18n) and localization (or L10n). While many usethese terms interchangably, there is a subtle difference between the two:

  • An application is considered localized when language elements are hard-coded or built directly into the executable;
  • An application is considered internationalized when the preparation of language elements are built into the executable;in this case, it means that specific language elements are not substituted until run-time.

If you are wondering where "i18n" and "L10n" come from, it is an old computer science tradition that lists the numberof letters in the term that are abbreviated, and is wrapped with the first and last letters of the term. The capital "L" for localizationis normally used to distinguish the term from i18n. A good explanation of the concept and differences can befound at Wikipedia.

Because applications built using the Dojo Toolkit are dynamic in nature (i.e. compiled and executed at run-time), they are consideredto be internationalized and not localized.

Internationalization with the Dojo Toolkit takes two forms: the ability to define resource bundles that can be loadedbased on a user's locale, and special built-in i18n facilities based on the Unicode CLDRfor dates, numbers and currencies.

Locales with the Dojo Toolkit

In order for an application to know what resources it may need to use for i18n, a locale must first be defined.

What are locales?

Locales are a short string, based on a language code anda country code, separated by a dash. For example, the localefor a typical user in the United States is en-us.

Normally, the locale is determined for a browser during the browser's installation, and cannot be easily configured.

When loading a Dojo Toolkit-based application, the user's locale is detected automatically and can be found programmaticallythrough the dojo.locale property. This is the normal usage scenario; however, there may be times (particularlywhen testing your application with resource bundles) where you would like to specify a locale.

Specifying a locale

If you need to specify a locale, you may do so by setting a locale property on the Dojo configuration object, likeso:

//	before dojo.js is loaded
var dojoConfig = {
	locale: "pt-pt"
};

//	or in the script tag:
<script src="path/to/dojo.js" data-dojo-config="locale:'pt-pt'"></script>

You should always include the full locale (i.e. language + country) when specifying a locale, even though many resourcebundles are defined by language only (as you'll see later on).

Once a Dojo Toolkit-based application is loaded, it is not possible to change the locale.

Including extra locales

There may be times when you want to include more than one locale-specific resource—for instance, if you needto display date resources in more than one language. While this is not the normal use-case, the Dojo Toolkit allowsyou to include more locale-based resources through the use of the extraLocale property of the Dojoconfiguration object, like so:

//	before dojo.js is loaded
var dojoConfig = {
	locale: "pt-pt",
	extraLocale: ["zh-cn","zh-tw"]
};

//	or in the script tag:
<script src="path/to/dojo.js" data-dojo-config="locale:'pt-pt',extraLocale:['zh-cn','zh-tw']"></script>

These extra locales can be passed into methods such as dojo.date.format, or optionally used with specificDijits by setting the lang attribute/property when instantiating them.

Resource Bundles

A resource bundle is a file containing a JavaScript object literal (or dictionary) of terms used by yourapplication code for a specific locale. When a user's locale is detected (and dojo.i18n is required), you canuse the i18n facilities within the Dojo Toolkit to load the resource bundle for a specific locale. For example, here is theJapanese resource bundle for Dijit's ValidationTextBox widget:

define(
({
	invalidMessage: "入力した値は無効です。",
	missingMessage: "この値は必須です。",
	rangeMessage: "この値は範囲外です。"
})
);

If you're wondering what define is here, it is part of the transition the Dojo Toolkit is makingtowards using an Asynchronous Module Loader.Stay tuned for more details as the Dojo Toolkit progresses towards 2.0!

There are a few things to note here about the structure of this resource bundle:

  • The fields of the bundle correspond to fields that are referenced within dijit.form.ValidationTextBox(for instance, myValidationWidget.invalidMessage);
  • Not all fields need to be defined in a specific resource bundle;
  • Not all language/country combinations need to be defined.

Let's take a look at how to create a resource bundle, as part of a larger set of resource bundles.

Creating resource bundles

The first step in creating resource bundles is to create a subdirectory called nls where your code lives,like so:

Note that the directory must be named "nls", and must be a subdirectory of the code that will be using it.In our example above, we have i18n directories for both the root of Dijit (i.e. for any widget that lives directly underthe dijit namespace) and for dijit.form.

Inside the nls directory for your namespace, you'll add both individual files and directories based on eitherthe international language code, or the full locale (such as pt-pt):

The name of each resource bundle does not matter, though by convention it should be close to the purpose of it. For example,in our screen shot above, there are three main resource bundles in the root of /nls: ComboBox.js,Textarea.js and validate.js. The first two resource bundles are aimed at a specific widget, while the lastis intended for use by any validation widget.

The resource bundles in the root of the /nls folder are intended to be master bundles; what this meansis that any and all properties to be consumed must be defined within these files. The reason for this is because the"master" bundle is the fallback for when a particular property does not exist in a specific language-basedresource bundle. For example, if your master resource bundle defines a property called message but the localeresource fr does not define it, the value of message in the master resource bundle will be usedin its place—in other words, when a locale is detected and a resource bundle is loaded, the locale-specific bundle willbe mixed into the master bundle.

You do not have to create locale-specific bundles for all possible languages/locales; in the case that alocale is detected but no locale-specific resource exists, the master bundle will be used in full.

In your language or locale directory, create identically named resource bundles as the master bundles; in each locale-specificbundle, define whatever properties you will be using in your code.

Finally, in your master bundle (the main one in the root of the /nls folder, add properties matching each localeyou've defined and set the value of each to true. As an example, here is the master bundle for the validate.jsresource, followed by our localized Japanese version:

//	the master bundle, from dijit/form/nls/validate.js:
define({
	root: ({
		invalidMessage: "The value entered is not valid.",
		missingMessage: "This value is required.",
		rangeMessage: "This value is out of range."
	}),
	"zh": true,
	"zh-tw": true,
	"tr": true,
	"th": true,
	"sv": true,
	"sl": true,
	"sk": true,
	"ru": true,
	"ro": true,
	"pt": true,
	"pt-pt": true,
	"pl": true,
	"nl": true,
	"nb": true,
	"ko": true,
	"kk": true,
	"ja": true,
	"it": true,
	"hu": true,
	"he": true,
	"fr": true,
	"fi": true,
	"es": true,
	"el": true,
	"de": true,
	"da": true,
	"cs": true,
	"ca": true,
	"ar": true
});

//	our localized Japanese resource, from
//	dijit/form/nls/ja/validate.js:
define(
	({
		invalidMessage: "入力した値は無効です。",
		missingMessage: "この値は必須です。",
		rangeMessage: "この値は範囲外です。"
	})
);

Notice that in our "master" bundle, the properties to be consumed by your code is a full JavaScript objectliteral called root, while the localized Japanese version is a straight-up object literal.You must follow this form for i18n to work correctly.

Consuming resource bundles

To consume resource bundles in your application code, you'll rely on the dojo.i18n module alongwith two basic constructs: dojo.requireLocalization and dojo.i18n.getLocalization.These two methods work hand-in-hand; requireLocalization fetches and assembles the locale-specificbundle, and getLocalization returns the JavaScript object literal fully assembled.

Both requireLocalization and i18n.getLocalization have the same method signature:the main namespace under which the resource bundles live, and the name (without the .js extension)of the bundle to load. In addition, i18n.getLocalization can take one more argument: the localeof the resource bundle to load. Here's how the resources are loaded within dijit.form.ValidationTextBox:

//	at the top of ValidationTextBox.js:
dojo.require("dojo.i18n");
dojo.requireLocalization("dijit.form", "validate");

//	later on, in the declaration of the widget:
postMixInProperties: function(){
	this.inherited(arguments);
	this.messages = dojo.i18n.getLocalization("dijit.form", "validate", this.lang);
	if(this.invalidMessage == "$_unset_$"){
		this.invalidMessage = this.messages.invalidMessage;
	}
	if(this.missingMessage == "$_unset_$"){
		this.missingMessage = this.messages.missingMessage;
	}
}
//	Note that some lines in postMixInProperties have been removed for brevity.
View Demo

You'll see that i18n.getLocalization returns a JavaScript object, which we assign to the propertymessages; we then read that object to populate the properties of the widget that requirelocalization.

With the release of the Dojo Toolkit 1.6 and the gradual transition to AMD, requireLocalizationis no longer necessary; instead, the loading of the resource bundle is handled by an AMD plugindesigned specifically for loading i18n resources.

You'll also note that these localized properties are set in the postMixInProperties methodof dijit.form.ValidationTextBox; this is the proper place to set up your i18n within anycustom widget code. See Understanding _Widget for more information.

Creating builds with resource bundles

A typical step in deploying a Dojo Toolkit-based application is to createa build of your application; a build minifies your JavaScript, inlines HTML and CSS, and generally makes yourapplication run much more efficiently. The Dojo Build Tools alsoprovides ways of flattening your resource bundles through the command line parameter localeList.

Normally you won't need to include this command line parameter to create your build; by default, the following listof locales is included:

"en-gb,en-us,de-de,es-es,fr-fr,it-it,pt-br,ko-kr,zh-tw,zh-cn,ja-jp"

However, if your application needs more than these locales defined, you can write your own comma-delimited listas the value of the localeList parameter.

A common "gotcha" when creating internationally-aware applications is to forget to copy over any /nlsdirectories to your Dojo Toolkit release. If you create a build and run into errors loading the application thefirst time, it is likely that some /nls directories were not copied during the course of the build process;to fix simply copy the missing directories into your release, in the appropriate spots.

Dates, Numbers and Currencies in the Dojo Toolkit

Internationalization in a toolkit would not be complete without the ability to parse and format dates, numbers and currencyin locale-specific formats. The Dojo Toolkit provides this functionality with dojo.date.locale,dojo.number and dojo.currency.

You can learn more about working localization and dates specifically in the Dojo Date tutorial.

Locale-aware dates with the Dojo Toolkit

As with our resource bundles, dojo.date.locale provides locale-specific formatting and parsing of dates,like so:

//	with our config object:
var dojoConfig = {
	extraLocale: [ "zh-cn", "ja-jp" ]
};

//	after dojo.js has been loaded:
dojo.require("dojo.date.locale");

var d = new Date(2006,9,29,12,30);

// to format a date, simply pass the date to the format function
dojo.date.locale.format(d);
// => "10/29/06 12:30 PM"

// the second argument may contain a list of options in Object syntax,
// such as overriding the default locale
dojo.date.locale.format(d, {locale:'zh-cn'});
// => "06-10-29 下午12:30"

For more information about working with Date objects with the Dojo Toolkit, seethe Dojo Date tutorial.

Note that if you plan on formatting and parsing dates, numbers and currencies in a number of different locales, you mustset the extraLocale property on the Dojo configuration object before loading dojo.js.

Locale-aware number formatting

Like dojo.date.locale, dojo.number uses the Dojo CLDR (see below) to correctly format numbersbased on a locale. For example, an American user might expect to see the number "1000000" (one million) formatted likeso:

// => 1,000,000

...but German, French and Indian users would expect the following formats:

// => 1.000.000,00  German
// => 1 000 000,00  French
// => 10,00,000.00  Indian

Like with dojo.date.locale, you can pass an optional arguments object that specifies the locale toformat or parse a number with (otherwise it will use the current locale as detected by the browser):

dojo.require("dojo.number");

console.log(dojo.number.format(100000, { locale: "hi-in" }));
// => 10,00,000.00

console.log(dojo.number.parse("10,00,000.00", { locale: "hi-in" }));
// => 1000000

Locale-aware currencies

Finally, dojo.currency will display numbers formatted to the correct currency—or optionallybased on the three-letter ISO code for that currency—using the same basic function signature as dojo.number:

dojo.require("dojo.currency");

// in the United States
dojo.currency.format(1234.567, {currency: "USD"});
// => "$1,234.57"

//	basic Euro formatting
dojo.currency.format(1234.567, {currency: "EUR"});
// => "€1,234.57"

// a French-speaking Swiss user would see
dojo.currency.format(-1234.567, {currency: "EUR"});
// => "-1 234,57 €"

// while a German-speaking Swiss user would see
dojo.currency.format(-1234.567, {currency: "EUR"});
// => "-€ 1,234.57"

Note that dojo.currency combines locale information with currency information, so that the formattingfor a particular user is always correct. See the Dojo Toolkit API for more details.

Other internationalization resources

In addition to the basic i18n facilities, the Dojo Toolkit also implements a version of theUnicode CLDR and supports bi-directional text.

The Dojo CLDR

The dojo.cldr (or Common Locale Data Repository) contains tables withculturally sensitive information for hundreds of languages and country variants for locale-specific information,such as days of week, currency symbols and formats, and more. In addition to being used by date, number andcurrency-specific functions in the Dojo Toolkit (see the above section), it also contains some methods that allowyou to find locale-based things. For example, if you want to find out how to format a currency (by learning howmany places and rounding should be), you'd pass an ISO code to dojo.cldr.monetary.getData, like so:

dojo.require("dojo.cldr.monetary");

//	get the formatting data for a euro
console.dir(dojo.cldr.monetary.getData("EUR"));

//	should display the following:
{
	places: 2,
	round: 0
}

For more information on using the dojo.cldr directly, check outThe Dojo Reference Guide.

Bi-directional Language Support

Some languages (particularly Middle Eastern in origin, such as Hebrew and Arabic) read right-to-left as opposed tothe usual left-to-right. The Dojo Toolkit supports bi-directional text, but there are some caveats:

  • The DIR attribute on either the html or body element must be set to rtl;
  • Dojo functions, including those in Dijit, only support one text direction at a time;
  • Special considerations (such as CSS specific to right-to-left text) must be taken into account.

Full information on how bi-directional text is supported throughout the Dojo Toolkitcan be found in the Dojo Toolkit Reference Guide,but the definition of resource bundles for right-to-left text remains the same as with any other locale.

Conclusion

The Dojo Toolkit provides full-features internationalization tools to aid you in creating localized applications.User interface elements benefit from the Dojo Toolkit's i18n resource bundle system, and also gives youbuilt-in formatting and parsing capabilities for dates, numbers and currencies. In addition, the Dojo Build systemis capable of "compiling" resource bundles et al to help make your application download and run more efficiently.

We hope that the information contained in this article aids you in creating full-featured applications that canbe used by users all around the world!

网友评论