Internationalization with the Dojo Toolkit

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: "入力した値は無効です。",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,000.00

console.log(dojo.number.parse("10,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!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


我有一个网格,可以根据更大的树结构编辑小块数据.为了更容易知道用户保存了什么,我希望当用户第一次看到网格时,网格处于不可编辑状态.当用户准备好后,他们可以单击编辑按钮,这将使网格的某些部分可编辑.然后,有一个保存或取消按钮可以保存更改或还原.在大多数情况下它是有效的.但
我即将开始开发一款教育性的视频游戏.我已经决定以一种我可以轻松打包为Web,Mobiles和可能的Standalone版本的方式来实现这一目标.我不想使用Flash.因此,我确信(无论如何我会听取建议)使用JavaScript和SVG.我正在对这个问题进行大量研究,但我很难把各个部分放在一起.我知道Raphae
我正在使用带有Grails2.3.9的Dojo1.9.DojoNumberTextBox小部件–我在表单中使用–将固定格式(JavaScript基本格式)的实数值(例如:12.56)设置为HTML表单输入字段(但根据浏览器区域设置显示/编辑它们,所以用户总是看到格式正确的数字).另一方面,Grails期望输入字段根据浏览器
1.引言鉴于个人需求的转变,本系列将记录自学arcgisapiforjavaScript的学习历程,本篇将从最开始的arcgisapiforjavaScript部署开始,个人声明:博文不在传道受业解惑,旨在方便日后复习查阅。由于是自学,文章中可能会出现一些纰漏,请留言指出,不必留有情面哦!2.下载ArcGISforDe
我正在阅读使用dojo’sdeclare进行类创建的语法.描述令人困惑:Thedeclarefunctionisdefinedinthedojo/_base/declaremodule.declareacceptsthreearguments:className,superClass,andproperties.ClassNameTheclassNameargumentrepresentsthenameofthec
我的团队由更多的java人员和JavaScript经验丰富组成.我知道这个问题曾多次被问到,但为了弄清楚我的事实,我需要澄清一些事情,因为我在客户端技术方面的经验非常有限.我们决定使用GWT而不是纯JavaScript框架构建我们的解决方案(假设有更多的Java经验).这些是支持我的决定的事实.>
路由dojo/framework/srcouting/README.mdcommitb682b06ace25eea86d190e56dd81042565b35ed1Dojo应用程序的路由路由FeaturesRoute配置路径参数RouterHistoryManagersHashHistoryStateHistoryMemoryHistoryOutletEventRouterContextInjectionOutl
请原谅我的无知,因为我对jquery并不熟悉.是否有dojo.connect()的等价物?我找到了这个解决方案:http:/hink-robot.com/2009/06/hitch-object-oriented-event-handlers-with-jquery/但是没有断开功能!你知道jquery的其他解决方案吗?有jquery.connect但这个插件在我的测试中不起作用.
与java类一样,在dojo里也可以定义constructor 构造函数,在创建一个实例时可以对需要的属性进行初始化。//定义一个类mqsy_yjvar mqsy_yj=declare(null,{     //thedefaultusername    username: "yanjun",          //theconstructor   
我一直在寻找一些最佳实践,并想知道Dojo是否具有框架特定的最佳实践,还是最好只使用通用的Javascript标准?特别是我主要是寻找一些功能和类评论的指导方针?解决方法:对于初学者来说,这是项目的风格指南:DojoStyleGuide
我有’05/17/2010’的价值我想通过使用dojo.date.locale将其作为“2010年5月17日”.我尝试过使用dojo.date.locale.parse,如下所示:x='05/17/2010'varx=dojo.date.locale.parse(x,{datePattern:"MM/dd/yyyy",selector:"date"});alert(x)这并没有给我所需的日期
我正在尝试创建一个包含函数的dojo类,这些函数又调用此类中的其他函数,如下所示:dojo.provide("my.drawing");dojo.declare("my.drawing",null,{constructor:function(/*Object*/args){dojo.safeMixin(this,args);this.container=args[0];
我知道你可以使用jQuery.noConflict为jQuery做这件事.有没有办法与Dojo做类似的事情?解决方法:我相信你可以.有关在页面上运行多个版本的Dojo,请参阅thispage.它很繁琐,但似乎是你正在寻找的东西.一般来说,Dojo和jQuery都非常小心,不会破坏彼此或其他任何人的变量名.
我有一个EnhancedGrid,用户经常使用复杂的过滤器.有没有办法允许用户保存或标记过滤器,以便将来可以轻松地重新应用它?我知道我可以通过编程方式设置过滤器,但我无法预测用户想要的过滤器.谢谢!编辑:自己做了一些进展…使用grid.getFilter()返回过滤器的JSON表示,然后使用json.strin
我有这个代码:dojo.declare("City",null,{constructor:function(cityid,cityinfo){}});dojo.declare("TPolyline",GPolyline,{constructor:function(points,color){},initialize:function(map){});应该是什
我遇到的问题是我的所有javascript错误似乎来自dojo.xd.js或子模块.我正在使用chrome调试器和许多dijit功能,如dijit.declaration和dojo.parser.这有点烦人,因为它很难找到简单的错误或滑倒.我希望我可以添加一个选项,允许我的调试器在我的非dojo代码中显示选项会发生的位置.我是
我正在使用DojoToolkit数字/解析函数来处理格式化和使用ICU模式语法解析字符串.有没有人知道有可能采取任意ICU模式字符串并以某种方式使用Dojo(或其他)库将其分解为它的部分(例如,对于数字模式,它可以被分解为小数位数,数千个分组等…).我希望这样做,而不需要让我的代码密切了
我有两个看似相关的问题,访问在不同的地方定义的javascript函数.我遇到的第一个问题是调用我在firgbug或safari控制台中定义的函数.我定义了一个名为getRed的函数,如下所示:functiongetRed(row,col){//dosomethingstuffandreturntheredvalueasa
我想添加一个在Ajax调用中指定的外部样式表.我已经找到了一种方法来使用jQuery(参见下面的示例),但是我需要使该方法适应dojoJavaScript框架.JQuery示例$('head').append('<linkrel="stylesheet"type="text/css"href="lightbox_stylesheet.css">');谢谢.解决方法:一旦你
我正在尝试使用dojo.connect将onMouseDown事件连接到图像,如:dojo.connect(dojo.byId("workpic"),"onMouseDown",workpicDown);functionworkpicDown(){alert("mousedown");}类似的代码几行后,我将onMouse*事件连接到dojo.body确实完全正常工作.但是当我点击图像时