引言

    本期将介绍decj的国际化(I18N)支持,包括声明式多语言支持和声明式CSS文件动态按需加载。

声明式CSS文件按需加载

    使用decj框架,开发人员只需要在模块定义中声明模块所需的各个CSS文件,即可实现这些CSS在该模块被加载时而被动态加载,而无需事先在页面中添加link标签来引用各个CSS文件。

    模块定义的css属性用于声明模块所需的各个CSS文件。该属性值是一个字符串数组,其各个元素为所要加载的CSS文件的URL。如果只需要加载一个CSS文件,css属性的值也可以是一个字符串。如清单19所示:


清单 19. 使用decj的声明式CSS文件加载

css:["dialog.css","menu.css"]

    decj在实际加载模块定义的CSS文件时,可以根据当前的Locale加载相应的CSS文件。比如,清单19中指定了“dialog.css”,那么当decj根据其算法明确了当前的Locale是“zh_CN”时,名为“dialog-zh_CN.css”的文件会被加载。这样,可以实现在多语言情形下,不同语言的页面显示时可以使用不同的页面风格。


    decj也支持加载托管在其它域名上的CSS文件,即实现跨域的CSS文件加载,从而支持CDN(Content Delivery Network)。对于与页面文件处在同一个域名内的CSS文件,decj会采用AJAX的方式去加载。而对于与页面文件处在不同域名的CSS文件(外部CSS文件),decj会采用link元素的方式动态加载。

    但是,由于多数浏览器都不支持用于表示link元素已经加载完毕其内容的事件,如onload、onreadystatechange等,decj需要一些“提示”信息来帮助其确认某个外部CSS文件是否加载完毕。为此,每个外部CSS文件的尾部需要添加一个称为LoadClue的特殊CSS规则。LoadClue规则的选择器必须是一个ID选择器,并且不能与当前模块要动态载入的其它CSS文件中的选择器相同。因此,LoadClue规则的名称通常与其所在的CSS文件的短文件名(不包含表示Locale的字符串)加“-Clue“相同。LoadClue规则的声明部分需要包含“display:none”。比如,有个外部CSS文件的URL为“http://cdn.site.com/css/dialog-zh_CN.css”,那么该CSS文件的尾部需要添加一个选择器为“#dialog-Clue”的LoadClue规则,如清单20所示:


清单 20. 加载外部CSS文件所需的“提示”

#dialog-Clue{
display:none;
}

    如果LoadClue规则的选择器名称与其所在的CSS文件的短文件名不同,则在模块定义中声明CSS文件时,需要在相应的URL末尾附加选择器的名称。如清单21所示:

清单 21. 在外部CSS文件URL后添加“提示”
css:["http://cdn.site.com/css/ dialog-zh_CN.css#dialog-LoadClue"]

声明式多语言支持

    使用decj框架开发支持多语言的Web应用,开发人员无需编写繁琐的代码。只需要以下3个步骤即可实现。

    第一步,创建资源文件。decj框架中,资源文件其实也是一个Javascript模块。资源文件的文件名中需要包含相应的Locale。比如,一个适用于中国大陆中文简体(对应的Locale为zh_CN)的资源文件的文件名中应该包含“zh_CN”,如“userInfo-zh_CN.js”。清单22展示了示例资源文件userInfo-zh_CN.js的内容。保存资源文件的时候,注意将文件的文本编码设置为UTF-8,以避免页面上显示相关字符串时出现乱码的问题。  

  

清单 22. 使用decj定义资源文件---中文

define({
  "expertise-area":"专长领域",
  "firstname":"名",
  "lastname":"姓"
});

    再添加一个适用于英文的名为“userInfo-en_US.js”的资源文件,该文件内容如清单23所示:


清单 23. 使用decj定义资源文件---英文

define({
  "expertise-area":"Expertise Area",
  "firstname":"First name",
  "lastname":"Last name"
});

    第2步。在模块定义中声明模块需要引用的资源文件。模块定义的resources属性用于声明模块所需的各个资源文件。resources属性的值是一个数组。该数组的每个元素是模块所需的资源文件的URL。在声明资源文件的URL时,无需指定文件名中的Locale部分(如“-zh_CN”),因为decj会根据当前浏览器的语言设置自动加载相应Locale的资源文件。如清单24代码所示:


清单 24. 在模块定义中声明资源文件

define(['jquery','decj'],function(jQuery,decj){
  //…
  return {
      //…
     resources:['res/userInfo','res/anotherRes']
      //…
  };
});

    第3步。在模块页面中使用资源文件中定义的字符串。在页面中使用资源文件中定义的字符串只需要在相关HTML元素的class属性值中添加一个名为“res”或“res-replace”的类,并将该元素标签内容设置为资源key。如清单25中的HTML代码所示:


清单 25. 在模块页面中使用资源字符串

<label>
    <label class="res-replace">firstname</label>
    <input name="fn" type="text" value="firstname" title="firstname"/>
  </label><br/>
  <label>
    <label class="res-replace">lastname</label>
    <input name="lastname" type="text" value="lastname" title="lastname"/>
  </label><br/>

  <label>
    <label class="res-replace">expertise-area</label><br/>
    <select multiple="true" name="expertise">
      <option value="java">Java</option>
      <option value="cpp">C++</option>
      <option value="Javascript">Javascript</option>
      <option value="design-pattern">Design Pattern</option>
      <option value="oracedb">Oracle Database</option>
      <option value="css">CSS</option>
      <option value="html">html</option>
    </select>
  </label>

    当操作系统的语言设置为“中文(简体中文)”时,页面显示效果如图8所示:


图8. decj I18N示例效果——中文简体

    如果操作系统的语言设置为“英文(美国)”,则页面显示效果如图9所示:


图9. decj I18N示例效果——英语

    同时,decj也支持以API调用的方式去引用资源文件中定义的字符串。假设某个资源文件包含key为“welcome“的资源字符串,该资源串中花括号(”{}“)括起的字符串表示资源字符串中可以替代的部分。如清单26所示:


清单 26. 包含可替代部分的资源字符串

define({
  "welcome":"Welcome to {destination}!"
});

    decj为Javascript的String对象的原型(prototype)添加了一个名为val的方法。通过该方法,开发人员可以编写类似Linux命令的特定字符串,并调用其val方法来实现特定的功能。获取资源字符串时,这个特定字符串的格式是:“res 资源字符串的key“,如”res welcome”。示例代码如清单27所示:


清单 27. 以API调用的方式使用资源文件中定义的字符串

var str="res welcome".val({destination:"decj"});
alert(str);

    调用字符串的val方法时,若字符串的是以“res“开头的,则该方法接受一个普通Javascript对象型的参数。该参数的各个属性名表示相应资源字符串中可替代参数的名称,而属性值则用于替换资源字符串中相应的可替代参数。

总结

    本文介绍了Web前端开发中的常规问题的传统处理方式所存在的问题与弊端,并介绍了decj框架如何以声明式编程的方式去解决这些常规问题。

参考资源