当前的富客户端可以包含两部分:分别为JSP页面和通过富客户端js组件(如extjs)渲染的组件化窗口页。针对这两部分分别做如下处理:
对于JSP页面的部分采用JSTL标准库的fmt标签,如通过:
这样的形式进行展现,其中message对应的文本在服务端配置,并在web.xml中配置资源文件的位置,也可以采用spring标签,Structs标签等多种机制。不过为了以后的程序修改兼容性,建议采用JSTL进行JSP页面的国际化。
对于JavaScript,考虑到为提高效率,因为是静态资源,可以很方便的在一定周期内要在客户端浏览器进行缓存,不同的浏览器会有不同的缓存机理,在IE中,js文件通过定义一定的过期期限,C:"Documents and Settings"用户名"Local Settings"Temporary Internet Files下进行缓存,Firefox是C:"Documents and Settings"用户名"Local Settings"Application Data"Mozilla"Firefox"Profiles"XXXXXXX.default"Cache,为了缓存而不是每次下载为了实现富客户端而集成的很大的js,不能用动态的网页来生成(即把JavaScript包装为JSP页面,最简单的,把js扩展名改成jsp并利用jsp的机制做国际化)。因此,需要对JavaScript中国际化的内容通过变量单独加载,举例如下:
var Message = function(){
this.title =’中文标题’;
……
};
var msg = new Message();
/********************************
或:
var msg = {
title : ‘中文标题’;
};
*********************************/
new Ext.Window({
title :msg.title,
width : 265,
height : 140
});
其中msg对象的定义可以通过在另一个JavaScript文件中引用的本地化文件所定义,也可以通过AJAX返回JSON对象的形式来获取或者动态地进行服务端生成。
两种方法的优缺点定义如下:
方法
缺点
优点
前台主动定义
会产生大量零碎的文件(M个JavaScript文件需要对象N个语言的资源文件,总数M×N,如果把这些资源文件都放在一个JavaScript文件中定义,则对客户端来说,要下载过多不必要的资源)
资源定义非常灵活,可以保证只定义自己需要的资源,并且可以做到随时更改其内容
后台自动获取
加重了服务器的负担,需要用到AJAX或者类似dwr的服务端动态加载。具有一定的复杂性
可以和后台及JSP页面共享同一个资源定义文件,并动态生成资源定义文件,减少了开发人员的负担
综上,可以采取如下国际化方法:
针对JavaScript文件的国际化,分成两部分来进行:
对于通用的文本定义,如:”确定”,”返回”等等,放在前台的资源文件中,随JavaScript文件一同加载,对于特殊的文本定义通过后台自动获取的形式来展现,这样就可以结合两种方法的优点。
后台实现的如下:
按照命名规约定义页面的文本元素,然后动态的生成一个如下的json对象:
{
messageName : messageValue
……
}
然后前台页面JavaScript在加载时获取这个json对象,并应用到页面文本元素的定义中,如利用Extjs的使用方法:
var msg = Ext.util.json.decode(jsonString); 或者服务器动态生成时就表述为var msg={…};的形式,并在头文件指向动态的地址(类似dwr动态生成的机制),然后就可以通过msg.XXX来获得文本定义了。文中涉及的代码如下:
importjava.util.Enumeration;
importjava.util.HashMap;
importjava.util.Locale;
importjava.util.ResourceBundle;
importnet.sf.json.JSONObject;
/** *//** * 根据层次结构获取到特定前缀的所有的资源名称,并把它们放在一个JSON对象中返回,对于相同类型的资源请求进行缓存,
* 不再动态生成新的内容。这个对象要纳入到Spring的容器中进行管理,把bean的管理模式设置为单例模式就好,所以这里
* 没有提供对于类的单例封装
*
* *@author杨一
*/
publicclassHierarchicalMessage{
/** *//**资源对象的基础名称*/privateString bundleName;
/** *//**特定组件所使用的前缀*/privateString prefix;
/** *//**缓存对象用的哈希表*/privateHashMapcachingMap=newHashMap();
/** *//**设置或注入对象的基础名称*/
publicvoidsetBundleName(String bundleName){
this.bundleName=bundleName;
}
/** *//**设置或注入所使用的前缀*/
publicvoidsetPrefix(String prefix){
this.prefix=prefix;
}
/** *//**根据注入的结果返回语言包,(某些情况下,请求的资源是一定的)*/
publicJSONObject getMessagesWithPrefix(Locale localeName){
returngetMessagesWithPrefix(this.bundleName,this.prefix,localeName);
}
/** *//** * 根据层次结构获取到特定前缀的所有的资源名称,并把它们放在一个JSON对象中返回
**/
publicJSONObject getMessagesWithPrefix(String bundleName, String prefix, Locale localeName){
JSONObject toReturn;
//拼接的缓存字符串的格式为:i18n/messages$page.login$zh_CNString cachingString=newStringBuilder().append(bundleName).append("$").
append(prefix).append("$").append(localeName.toString()).toString();
toReturn=cachingMap.get(cachingString);
if(toReturn!=null){
returntoReturn;
}
toReturn=newJSONObject();
//此处无需缓存,因为Java核心库会做这件工作ResourceBundle rb=ResourceBundle.getBundle(bundleName,localeName);
Enumeratione=rb.getKeys();
String keyRef=null;
String componentPrefix=newStringBuilder().append(prefix).append(".").toString();
intshortNameStartIndex=prefix.length()+1;
while(e.hasMoreElements()){
keyRef=e.nextElement();
if(keyRef.startsWith(componentPrefix)){
toReturn.put(keyRef.substring(shortNameStartIndex), rb.getString(keyRef));
} }
cachingMap.put(cachingString, toReturn);
returntoReturn;
}}
importjava.io.IOException;
importjava.io.PrintWriter;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importorg.springframework.web.context.WebApplicationContext;
importorg.springframework.web.context.support.WebApplicationContextUtils;
importHierarchicalMessage;
publicclassI18nServletextendsHttpServlet{
/** *//** * 动态生成一个用于国际化的JavaScript脚本
*
*@paramrequest the request send by the client to the server
*@paramresponse the response send by the server to the client
*@throwsServletException if an error occurred
*@throwsIOException if an error occurred
*/publicvoiddoGet(HttpServletRequest request, HttpServletResponse response)
throwsServletException, IOException{
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
PrintWriter out=response.getWriter();
HierarchicalMessage hm=getHierarchicalMessage();
hm.setPrefix(newStringBuilder().append("page.").append(getBizId(request)).toString());
//此处从session中获取用户的登陆语言环境String json=hm.getMessagesWithPrefix(request.getLocale()).toString();
out.print(newStringBuilder().append("var msg=").append(json).append(";"));
out.close();
}
privateHierarchicalMessage getHierarchicalMessage(){
WebApplicationContext wc=WebApplicationContextUtils
.getWebApplicationContext(getServletContext());
HierarchicalMessage hm=(HierarchicalMessage)wc.getBean("msgBean");
returnhm;
}
privateString getBizId(HttpServletRequest request){
StringBuffer urlString=request.getRequestURL();
intstart=urlString.lastIndexOf("/")+1;
intend=urlString.lastIndexOf(".");
returnurlString.substring(start, end);
}
}
Spring配置:
i18n/messagessys
Web.xml配置:
I18nServletI18nServletI18nServlet/i18n/*
使用方法:
在html页面中先于功能js导入对应的语言js,名称相同,路径在/i18n/xxx.js
同时在根classpath下的i18n/messages资源下定义page.xxx.xxx
@2008 杨一. 版权所有. 保留所有权利
posted on 2008-12-23 12:07 杨一 阅读(2498) 评论(1) 编辑 收藏