本文主要是讲述 Dojo 所支持的三种不同的本地化处理方法。第一种是对时间、数字和货币本地化的直接支持;第二种是专注于本地化处理的 Dojo Widget;第三种是对页面显示内容的本地化处理。
在全球化趋势越来越明显的今天,一个优秀的软件往往面对的是全球的使用环境。为了使其能够在国际化的环境中得到更好的应用。Dojo 给出了一系列的针对软件本地化的解决方案。本文主要介绍 Dojo 对文字、时间、数字和货币的本地化处理方法。
对度量衡的本地化处理
世界各地在度量衡的表示方式上有着巨大的差异。这些差异主要表现在时间、数字、货币等的格式上。
时间格式的本地化
Dojo 给出了一个专门的模块来实现时间格式的本地化。这个模块位于 dojo_path/dojo/date 下。该模块主要是针对 Javascript 对象的日期部分和时间部分进行本地化。
清单 1. 时间本地化示例
<html> <head> <title>test</title> <script type="text/javascript" src="dojo_path/dojo/dojo.js" djConfig="isDebug:true,parSEOnLoad: true"></script> <script type="text/javascript"> dojo.require("dojo.date.locale"); function init() { var mydate =new Date(2007,5,26,10,1,13); var result=dojo.date.locale.format(mydate,{ formatLength :'long',locale: 'zh-cn' }); dojo.byId("content").innerHTML = result; } dojo.addOnLoad(init); </script> </head> <body> <div id="content"></div> </body> </html>
由于在清单 1 中将 locale 值设定为“zh-cn”,运行清单 1 中代码的页面便会使用简体中文的格式显示时间信息。locale 是根据计算机用户所使用的语言,所在国家或者地区,以及当地的文化传统所定义的一个软件运行时的语言环境。
dojo.require(“dojo.date.locale”) 表示引入时间显示格式本地化模块。var mydate =new Date(2007,13) 表示创建一个时间为 2007 年 5 月 26 日 10 点 1 分 13 秒的 Javascript 时间对象。这里给出的是一个固定不变的时间对象,同样也可以 new Date() 直接获得当前时间对象。var result=dojo.date.locale.format(mydate,{ formatLength :“long”,locale: “zh-cn”}) 表示将前面创建的 Javascript 时间对象依据 locale 值为“zh-cn”进行展现,同时显示格式为“long”型。此外除了“long”型的显示方式以外,还有“short”,“medium”和“full”三种显示方式,读者可以使用任意一种显示类型进行尝试,并运行查看其效果。
如果读者进行这样一种尝试,var result=dojo.date.locale.format(mydate,locale: “en-us”})(“en-us”表示当前软件运行环境为 locale 为美式英语环境)。这样修改后,页面运行的时候将会出现错误。其原因在于这种修改方法并没有将相应的美式英语运行环境文件与当前应用进行绑定(如果读者是英文操作系统不会出现这个错误)。因此当页面在加载的时候只会默认的将简体中文运行环境的文件加载。而当脚本尝试使用美式英语格式显示时间时,就会出现美式英语运行环境文件没有加载的错误。
对于这种错误的解决方法有两种。第一种方法是在页面完全加载以前,将页面的 locale 进行修改。这种方法将在后面的部分详细叙述。第二种方法是将当前需要使用的运行环境文件手动加载入页面中。
需要注意的是,对于时间的显示,各个国家的英文没有区分,因此需要引入的是 locale 为 en 的运行环境文件。
dojo.requireLocalization(“dojo.cldr”,“Gregorian”,“en”) 为引入英文格式显示时间的运行环境文件。在完成前面的引入英文格式显示时间的运行环境文件以后,再运行 var result=dojo.date.locale.format(mydate,locale: “en”}) 就不会出现错误了。
运行环境文件在 dojo_path/dojo/cldr/nls 目录下。读者在实际项目中,可以通过查看该目录下的文件选择合适的本地化环境文件,并将其引入系统中。
数字格式的本地化
数字格式的本地化需要引入的模块为 dojo.number。同时数字本地化需要调用的 API 函数为 dojo.number.format()。
清单 2. 数字本地化示例
SEOnLoad: true"></script> <script type="text/javascript"> dojo.require("dojo.number"); dojo.requireLocalization("dojo.cldr","number",'fr-fr'); function init() { var result=dojo.number.format( 999999.999,{ locale: 'fr-fr' }) ; dojo.byId("content").innerHTML = result; } dojo.addOnLoad(init); </script> </head> <body> <div id="content"></div> </body> </html>
运行清单 2,会发现页面中数字的显示非常奇怪。这是因为是以法语的方式对数字进行了显示。
dojo.requireLocalization("dojo.cldr",'fr-fr') 引入了法语运行环境文件。如果查看 dojo_path/dojo/cldr/nls 目录,会发现 fr 文件夹下有个 number.js 的文件。这就是上面引入的处理数字显示的法语运行环境文件。
如果希望对数字的显示进行一些更细致的处理,可以通过设置一些可选的属性来实现。pattern 可以设置数字的格式。places 可以设置小数点的位置。Round 可以设置取近似值的处理方法,值为 5 就取近似为 .5,值为 0 就取近似为整,值为 -1 就不取近似。
货币格式的本地化
对于商用国际化系统非常重要的一个问题是面对不同货币的显示格式。而且如何正确的显示各国不同的货币在实际使用环境中非常重要,容不得有一点的错误。
Dojo 提供了一套货币本地化显示的转化模块。需要注意的是对于需要显示的货币值必须为数值。
清单 3. 货币本地化示例
SEOnLoad: true"></script> <script type="text/javascript"> dojo.require("dojo.currency"); function init() { var result=dojo.currency.format( 999999.89,{currency: "EUR"}) ; dojo.byId("content").innerHTML = result; } dojo.addOnLoad(init); </script> </head> <body> <div id="content"></div> </body> </html>
清单 3 中显示币种为欧元。读者可能发现在清单 3 中没有引入任何与欧元显示相关的运行环境文件。这是因为币种的显示不受 locale 的影响,可以想象一个中国的国际金融家往往也会需要查看美元、欧元等币种的信息。
dojo.currency.format 有一些属性可以对货币的显示进行更细致的控制。symbol,可以重新设置货币符号;pattern,可以重新设置数字的格式;places,可以设置小数点的位置。除上述的以外,还有一些属性可以进行设置。读者可以将 dojo.currency.format 输入 Dojo API 在线文档中搜索,查看其所有的属性。
支持的本地化的 Dijit
除了使用上面的方法对日期、数字、货币进行本地化处理以外,一些 Dijit 能自动的根据 locale 进行本地化处理。
这些可以自动进行本地化处理的 Dijit 包括,ValidationTextBox,CurrencyTextBox,NumberTextBox,DateTextBox 和 TimeTextBox 等。
清单 4. Dijit 本地化示例
SEOnLoad: true"></script> <style type="text/css"> @import "dojo_path/dijit/themes/tundra/tundra.css"; @import "dojo_path/dojo/resources/dojo.css" </style> <script type="text/javascript"> dojo.require("dijit.form.TimeTextBox"); dojo.require("dojo.parser"); </script> </head> <body> <div dojoType="dijit.form.TimeTextBox"></div> </body> </html>
清单 4 中使用的是 TimeTextBox Dijit。这个 Dijit 实现的是选择时间填入输入框中的功能。
图 1. TimeTextBox 中时间的本地化
图 1 中显示的是 TimeTextBox 在简体中文环境中运行的实际效果。可以看见 Dijit 使用了汉字“上午”和“下午”来标注时间。如果将 TimeTextBox 在英文环境中运行,就不会看见汉字的“上午”和“下午”。
对于其它可以自动进行本地化处理的 Dijit,可以将其替换到实例 12-4 中查看其运行效果。
对页面显示内容的本地化处理
要使开发出来的系统支持国际化的工作环境,其要实现的一个重要目标就是要页面的文本内容能根据用户机器的 locale 值选取不同语言的文本进行显示。
要实现这个功能首先是必须将页面的文本内容抽离出来。将各个不同语言版本的文本内容文件分别放置。这些文件的内容是按照 Key 和 Value 以 JSON 的数据格式进行组织的。
在本节的后面部分将以一个具体的实例来讲述如何实现对页面文本显示内容的本地化处理。
在创建保存不同语言版本的文本内容文件之前,首先要建立一个文件夹,文件夹名字为 locale,在 locale 文件夹下建立一个子文件夹名为 nls,再在 nls 文件夹下建立两个子文件夹,分别名为 en 和 zh-cn(分别代表英文版的文本内容文件夹和中文版的文本内容文件夹)。
图 2. Dojo 目录结构
最后建立的文件夹目录结构如图 2 所示。需要注意的是在图 2 中也展示了 Dojo 包的文件目录结构以及其与“ll”文件夹的相对位置。在本节后面的清单代码中都会以图 2 所示的目录结构构造代码范例。
在 zh-cn 文件夹下建立一个文件,其文件名为 myfile.js。
清单 5. 中文的 myfile.js
( { "first": "欢迎!","myname": "善良的人。 现在时间是:${0}。","mynumber": "你是 ${0} 号。" } )
将清单 5 中的代码拷贝到 zh-cn 文件夹下的 myfile.js 文件中。
在 en 文件夹下建立一个文件,其文件名为 myfile.js。
清单 6. 英文的 myfile.js
( { "first": "Welcome!","myname": "Good Man. Now time is:${0}.","mynumber": "You are NO ${0}.",} )
将清单 6 中的代码拷贝到 en 文件夹下的 myfile.js 文件中。
从清单 5 和清单 6 可以看出被抽离出来的文本内容都是按照 Key 和 Value 一一对应的原则构建起来的。
清单 7. 测试代码
<html> <head> <Meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>test</title> <script type="text/javascript" src="../js/dojo1.0/dojo1.0/dojo/dojo.js" djConfig="isDebug:true,parSEOnLoad:true,locale:'zh-cn'"> </script> <script language="JavaScript" type="text/javascript"> dojo.require("dojo.date.locale"); dojo.require("dojo.number"); dojo.registerModulePath("my","../../../../ll"); dojo.requireLocalization("my.locale","myfile"); var resourceBundle; function init() { resourceBundle = dojo.i18n.getLocalization("my.locale","myfile"); dojo.byId('aaa').innerHTML = dojo.string.substitute(resourceBundle.first); dojo.byId('bbb').innerHTML = dojo.string.substitute(resourceBundle.myname,[dojo.date.locale.format( new Date(2007,12,17,32,12),{ formatLength:'long'})]); dojo.byId('ccc').innerHTML = dojo.string.substitute(resourceBundle.mynumber,[dojo.number.format(12345.67)]); } dojo.addOnLoad(init); </script> </head> <body class="tundra"> <p id="aaa"></p> <p id="bbb"></p> <p id="ccc"></p> </body> </html>
由于 djConfig 的 locale 属性值为 zh-cn,所以 test.html 运行显示的是中文信息。如果希望看见英文版本的信息,则只需将 djConfig 的 locale 属性值修改为 en(djConfig=“isDebug:true,locale:'en'”)。
dojo.registerModulePath(“my”,“../../../../ll”) 是将前面抽离出来的中英文文本文件注册为可用的模块(如果文本文件在 Dojo 包内,则不需要这步。另外一个较为常见的需要使用注册功能是当自己开发的 Widget 不在 Dojo 包内,而又要使用时,也需要先注册该 Widget 模块)。
dojo.requireLocalization(“my.locale”,“myfile”) 是加载相应的资源文件。
resourceBundle = dojo.i18n.getLocalization("my.locale","myfile") 将相应的资源文件转换为 JSON 对象,以方便后面提取对应的文本内容元素。
双向字符集的显示处理
目前大多数语言的书写习惯都是从左到右,但是有些国家的书写习惯是从右到左 ( 比如希伯来语、乌尔都语等 )。如果要将实现的系统在这些国家进行布置,必须考虑其的书写习惯问题。
Dojo 所提供的双向字符集的显示处理功能是基于 Dijit 的。也就是说 Dojo 的 Dijit 能非常方便的实现从右到左或从左到右的显示。
图 3. Dijit 的双向支持
如图 3 所示,上面一个 Dijit 的显示是从右到左,且其在页面中的位置也是先右后左,而下面一个 Dijit 的显示是从左到右,且其在页面中的位置也是先左后右。
由于大多数情况下,都应该是从左到右的书写习惯,因此 Dojo 默认的也是从左到右的书写系统。如果要特别实现从右到左书写习惯的系统,需要完成两步的操作。
第一步,引入从右到左书写习惯相应的 Dojo CSS 文件。例如 dijit_rtl.css 以及页面对应主题样式表的 rtl 样式文件(tundra_rtl.css)。
清单 8. 加载相应样式
@import "dojo_path/dijit/themes/tundra/tundra_rtl.css"; @import "dojo_path/dijit/themes/dijit_rtl.css";
第二步,声明要采用从右到左书写习惯的页面区块。所采用的方法是使用一个 div 标签将要声明的区块包裹起来,然后在该 div 标签中加上两个 Dojo 标签属性(dir=“rtl” class=“dijitRtl”)。
清单 9. 双向支持示例
<div dir="rtl" class="dijitRtl" style="width:40%"> <div id="righttoleft" dojoType="dijit.form.HorizontalSlider" value="5" minimum="-10" maximum="10" discreteValues="11" intermediateChanges="true" showButtons="true"> <div dojoType="dijit.form.HorizontalRuleLabels" container="topDecoration" style="height:1.2em;font-size:75%;color:gray;"></div> </div> </div> <div style="width:40%"> <div id="lefttoright" dojoType="dijit.form.HorizontalSlider" value="5" minimum="-10" maximum="10" discreteValues="11" intermediateChanges="true" showButtons="true"> <div dojoType="dijit.form.HorizontalRuleLabels" container="topDecoration" style="height:1.2em;font-size:75%;color:gray;"></div> </div> </div>
需要注意的是 Dojo1.0.0 并不是所有的 Dijit 都支持双向字符集的显示处理,而 Dojo1.1.0 则几乎所有的 Dijit 都支持双向字符集的显示处理。
参考资料
学习
- 访问Dojo 的官方站点,关于 Dojo 的最权威的站点。
- 掌握 Dojo 工具包:阅读本系列以前的文章。
- “教程:使用 Dojo 开发 HTML 小部件”(developerWorks,2006 年 12 月):您将学到使用 Dojo 开发 HTML 小部件的基础知识;包括如何引用一个图像、如何向 HTML 页面中添加事件处理程序以及如何处理复合小部件。
- “评论专栏 : Scott Johnson:沉迷于 Dojo”(developerWorks,2008 年 4 月):Dojo 内部人员讨论 Dojo Toolkit 如此广受欢迎而成为必备下载工具的原因、其现状和未来。
- “基于 Dojo 的本地化开发”(developerWorks,2008 年 1 月):本文介绍了基于 Dojo 的本地化的实现,通过实例讲解了如何利用 Dojo 提供的本地化支持模块来实现软件的本地化。
- “提高基于 Dojo 的 Web 2.0 应用程序的性能”(developerWorks,2008 年 2 月):本文通过演示一些实用的技巧来提高 Dojo 的性能,帮助开发人员找出 Web 2.0 应用程序的性能瓶颈。
- “使用 Dojo 开发支持 Accessibility 的 Web 应用”(developerWorks,2008 年 5 月):帮助开发人员了解 Accessibility 的基本内容,掌握 Dojo 开发可访问性 Web 应用的基本技能。
- “使用 Dojo 国际化 Web 应用程序”(developerWorks,2008 年 8 月):通过本文获得有关如何使用 Dojo 这个重要特性的简短的指导。
- “用 Firebug 动态调试和优化应用程序”(developerWorks,2008 年 5 月):了解如何使用 Firefox 浏览器的免费开源扩展 Firebug,它提供了很多有用的开发特性和工具。
- wikipedia上关于 XMLHttpRequest 对象的详细介绍。
- JSON 的官方网站,在这里可以找到最实用的关于 JSON 的第一手资料。
- wikipedia 上关于REST 架构风格的介绍。
- Ajax 资源中心:developerWorks 上所有有关 Ajax 的问题都可以在这里找到解答。
- developerWorks技术活动和网络广播:随时关注 developerWorks 技术活动和网络广播。
- developerWorks Web development 专区:通过专门关于 Web 技术的文章和教程,扩展您在网站开发方面的技能。
获得产品和技术
- 下载最新版 Dojo 工具包。
讨论
- 访问 Dojo 发起人Alex Russell 的博客:有很多有深度的文章。