一、引言
首先要回答的一个问题就是,我们是否有必要实现这样一个功能。
现在大多数网站(如论坛、博客等)的多语言往往是在服务器端实现的,主要用于整站的本地化。此外,像新华网这一类的新闻类网站实际上每种语言都有一个独立的站点,有不同的团队来维护——当然这不在本文的讨论范围之内。用服务器脚本替换的方式处理多语言信息对于用户来说是非常被动的,对我们代码编写者来说则是一件浪费时间的事情。而且每次修改或添加词条都要维护一个庞大的脚本文件(一般都使用数组……)。
我希望得到这样的一个东西:服务器端的系统不处理语言;客户可以在已经下载好的页面上选择自己擅长或喜好的语言(现在会两种语言的人不在少数……),这些信息异步发送到服务器。注意:这里也不消耗脚本资源,只需要request一个或几个xml文件就能搞定。这样的好处是:可以通过各种现成的XML编辑器修改整理词条,可以同样简单地添加语言;节约服务器资源(运行脚本总比下载文件更耗费资源),有时候甚至可以节省SQL查询的时间(如果有人会在数据库中记录用户喜欢的语言……不过我目前还没听说……);变以前“推”的方式为现在“拉”的方式;更新界面语言不必刷新……
二、设计与实施
为了节省开发时间,我选用prototype 1.5.1作为基础类库(顺便提一句,prototype库简直太好用了,只是1.5.1版有90多KB……这应该就是Fat Client的典型代表吧)。
包含词条的语言文件采用XML,目录结构如下:
lang / config.xml
zh-cn.xml
en-ww.xml
/ subpage / config.xml
zh-cn.xml
en-ww.xml
说明:一个目录就是一个多语言配置单元,lang/config.xml指定了可用的语言,结构如下:
<?xml version=”1.0″ encoding=”utf-8″?>
<lang-config version=”1.0″>
<entry value=”zh-cn” name=”中文(简体)” />
<entry value=”en-ww” name=”English” />
</lang-config>
这里可以根据需要添加语言,entry的value属性所指定的语言必须有同名的xml在与该文件相同的目录下。
zh-cn.xml和en-ww.xml就是存储词条的文件了,其结构如下:
<?xml version=”1.0″ encoding=”utf-8″?>
<lang-pack lang=”en-ww” name=”English” version=”1.0″>
<title>PHIL idea. Online</title>
<entry id=”STR_SOMETHING“>Something …</entry>
</lang-pack>
在本例中每个配置单元代表一个页面,所以title字段表示页面的标题。此处可以根据需要添加内容。后面的每一个词条占用一个entry标签,id属性指定了词条的在该配置单元中的唯一标识符。zh-cn.xml的结构与此相同,在此不做赘述。
为了避免在不同的文件里引用相同的内容,可以在subpage/lang-code.xml的根标签中添加include属性,写上所引用文件的相对路径:
<lang-pack lang=”en-ww” name=”English” include=”../en-ww”>
<title>PHIL idea. Online — Brief Introduction</title>
<entry id=”STR_TEST”>TEST</entry>
</lang-pack>
接下来,在页面中需要应用词条的地方放置这样的东西:
<span class=”lang-spot:STR_SOMETHING“></span>
为什么用class属性?原因是prototype有非常简便的操作class的函数……真是太方便了!如果你有兴趣可以参见文档。当然,在这个lang-spot:STR_SOMETHING的后面还可以追加其它的class,并不会影响CSS效果的展现。
最后的工作就是写javascript脚本了:
您可以在此下载用于测试的脚本:multi_lang_demo.js
测试:
在HTML页面中,引用这个文件。
在页面的最后添加一个脚本块儿:
Event.observe( window, "load", function(){
Lang.initialize( "lang/", function(){
// 列表可用语言列表到divLangList中
//(假设你的页面中存在这个东西)
Lang.LanguagesSupported.keys.each(
function(oKey){
$("divLangList").innerHTML +=
"<a href='javascript:void(0);' "+
"onclick=/"Lang.Apply(document, '" +
Lang.LanguagesSupported[oKey].Code + "');/">" +
Lang.LanguagesSupported[oKey].Name + "</a><br />";
});
// 在页面中应用代码为zh-cn的语言,即简体中文
// 未设置应用完成的事件处理器
Lang.Apply( document, "zh-cn", null );
});
});
现在可以试一下了。页面上的那个标记好的标签会被自动替换成相应的词条。你可以添加
四、后记
这段代码只是一个DEMO,你可以在此基础上进行自己的修改,比如添加使用Cookie记住用户上次使用的语言等等。此外,对于语言包的引用有一个循环引用的问题,在这个DEMO中没有解决,有兴趣的朋友可以试一下。
欢迎交流!也希望各位把您修改的作品发来看看!