java富客户端_富客户端技术中的JavaScript脚本国际化

当前的富客户端可以包含两部分:分别为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来获得文本定义了。文中涉及的代码如下:

4f1150b881333f12a311ae9ef34da474.pngimportjava.util.Enumeration;

4f1150b881333f12a311ae9ef34da474.pngimportjava.util.HashMap;

4f1150b881333f12a311ae9ef34da474.pngimportjava.util.Locale;

4f1150b881333f12a311ae9ef34da474.pngimportjava.util.ResourceBundle;

4f1150b881333f12a311ae9ef34da474.png

4f1150b881333f12a311ae9ef34da474.pngimportnet.sf.json.JSONObject;

4f1150b881333f12a311ae9ef34da474.png

1fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gif/** *//**d18c02628675d0a2c816449d98bda930.png * 根据层次结构获取到特定前缀的所有的资源名称,并把它们放在一个JSON对象中返回,对于相同类型的资源请求进行缓存,

d18c02628675d0a2c816449d98bda930.png * 不再动态生成新的内容。这个对象要纳入到Spring的容器中进行管理,把bean的管理模式设置为单例模式就好,所以这里

d18c02628675d0a2c816449d98bda930.png * 没有提供对于类的单例封装

d18c02628675d0a2c816449d98bda930.png * 

d18c02628675d0a2c816449d98bda930.png *  *@author杨一

8f1ba5b45633e9678d1db480c16cae3f.png*/4f1150b881333f12a311ae9ef34da474.png

1fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gifpublicclassHierarchicalMessage9b8a8a44dd1c74ae49c20a7cd451974e.png{

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif/** *//**资源对象的基础名称*/d18c02628675d0a2c816449d98bda930.pngprivateString bundleName;

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif/** *//**特定组件所使用的前缀*/d18c02628675d0a2c816449d98bda930.pngprivateString prefix;

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif/** *//**缓存对象用的哈希表*/d18c02628675d0a2c816449d98bda930.pngprivateHashMapcachingMap=newHashMap();

d18c02628675d0a2c816449d98bda930.png    

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif/** *//**设置或注入对象的基础名称*/97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifpublicvoidsetBundleName(String bundleName)9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.pngthis.bundleName=bundleName;

ecedf933ec37d714bd4c2545da43add2.png    }d18c02628675d0a2c816449d98bda930.png

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif/** *//**设置或注入所使用的前缀*/97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifpublicvoidsetPrefix(String prefix)9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.pngthis.prefix=prefix;

ecedf933ec37d714bd4c2545da43add2.png    }d18c02628675d0a2c816449d98bda930.png

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif/** *//**根据注入的结果返回语言包,(某些情况下,请求的资源是一定的)*/97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifpublicJSONObject getMessagesWithPrefix(Locale localeName)9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.pngreturngetMessagesWithPrefix(this.bundleName,this.prefix,localeName);

ecedf933ec37d714bd4c2545da43add2.png    }d18c02628675d0a2c816449d98bda930.png    

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif/** *//**d18c02628675d0a2c816449d98bda930.png     * 根据层次结构获取到特定前缀的所有的资源名称,并把它们放在一个JSON对象中返回

ecedf933ec37d714bd4c2545da43add2.png     **/97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifpublicJSONObject getMessagesWithPrefix(String bundleName, String prefix, Locale localeName)9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png        JSONObject toReturn;

d18c02628675d0a2c816449d98bda930.png//拼接的缓存字符串的格式为:i18n/messages$page.login$zh_CNd18c02628675d0a2c816449d98bda930.pngString cachingString=newStringBuilder().append(bundleName).append("$").

d18c02628675d0a2c816449d98bda930.png                                append(prefix).append("$").append(localeName.toString()).toString();

d18c02628675d0a2c816449d98bda930.png        toReturn=cachingMap.get(cachingString);

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(toReturn!=null)9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.pngreturntoReturn;

ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png        

d18c02628675d0a2c816449d98bda930.png        toReturn=newJSONObject();

d18c02628675d0a2c816449d98bda930.png        

d18c02628675d0a2c816449d98bda930.png//此处无需缓存,因为Java核心库会做这件工作d18c02628675d0a2c816449d98bda930.pngResourceBundle rb=ResourceBundle.getBundle(bundleName,localeName);

d18c02628675d0a2c816449d98bda930.png        

d18c02628675d0a2c816449d98bda930.png        Enumeratione=rb.getKeys();

d18c02628675d0a2c816449d98bda930.png        String keyRef=null;

d18c02628675d0a2c816449d98bda930.png        String componentPrefix=newStringBuilder().append(prefix).append(".").toString();

d18c02628675d0a2c816449d98bda930.pngintshortNameStartIndex=prefix.length()+1;

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifwhile(e.hasMoreElements())9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png            keyRef=e.nextElement();

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifif(keyRef.startsWith(componentPrefix))9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png                toReturn.put(keyRef.substring(shortNameStartIndex), rb.getString(keyRef));

ecedf933ec37d714bd4c2545da43add2.png            }ecedf933ec37d714bd4c2545da43add2.png        }d18c02628675d0a2c816449d98bda930.png        

d18c02628675d0a2c816449d98bda930.png        cachingMap.put(cachingString, toReturn);

d18c02628675d0a2c816449d98bda930.png        

d18c02628675d0a2c816449d98bda930.pngreturntoReturn;

ecedf933ec37d714bd4c2545da43add2.png}8f1ba5b45633e9678d1db480c16cae3f.png}

4f1150b881333f12a311ae9ef34da474.pngimportjava.io.IOException;

4f1150b881333f12a311ae9ef34da474.pngimportjava.io.PrintWriter;

4f1150b881333f12a311ae9ef34da474.png

4f1150b881333f12a311ae9ef34da474.pngimportjavax.servlet.ServletException;

4f1150b881333f12a311ae9ef34da474.pngimportjavax.servlet.http.HttpServlet;

4f1150b881333f12a311ae9ef34da474.pngimportjavax.servlet.http.HttpServletRequest;

4f1150b881333f12a311ae9ef34da474.pngimportjavax.servlet.http.HttpServletResponse;

4f1150b881333f12a311ae9ef34da474.png

4f1150b881333f12a311ae9ef34da474.pngimportorg.springframework.web.context.WebApplicationContext;

4f1150b881333f12a311ae9ef34da474.pngimportorg.springframework.web.context.support.WebApplicationContextUtils;

4f1150b881333f12a311ae9ef34da474.png

4f1150b881333f12a311ae9ef34da474.pngimportHierarchicalMessage;

4f1150b881333f12a311ae9ef34da474.png

1fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gifpublicclassI18nServletextendsHttpServlet9b8a8a44dd1c74ae49c20a7cd451974e.png{

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gif/** *//**d18c02628675d0a2c816449d98bda930.png     * 动态生成一个用于国际化的JavaScript脚本

d18c02628675d0a2c816449d98bda930.png     * 

d18c02628675d0a2c816449d98bda930.png     *@paramrequest the request send by the client to the server

d18c02628675d0a2c816449d98bda930.png     *@paramresponse the response send by the server to the client

d18c02628675d0a2c816449d98bda930.png     *@throwsServletException if an error occurred

d18c02628675d0a2c816449d98bda930.png     *@throwsIOException if an error occurred

ecedf933ec37d714bd4c2545da43add2.png*/d18c02628675d0a2c816449d98bda930.pngpublicvoiddoGet(HttpServletRequest request, HttpServletResponse response)

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifthrowsServletException, IOException9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png        

d18c02628675d0a2c816449d98bda930.png        response.setContentType("application/json");

d18c02628675d0a2c816449d98bda930.png        response.setCharacterEncoding("UTF-8");

d18c02628675d0a2c816449d98bda930.png        

d18c02628675d0a2c816449d98bda930.png        PrintWriter out=response.getWriter();

d18c02628675d0a2c816449d98bda930.png        

d18c02628675d0a2c816449d98bda930.png        HierarchicalMessage hm=getHierarchicalMessage();

d18c02628675d0a2c816449d98bda930.png        hm.setPrefix(newStringBuilder().append("page.").append(getBizId(request)).toString());

d18c02628675d0a2c816449d98bda930.png//此处从session中获取用户的登陆语言环境d18c02628675d0a2c816449d98bda930.pngString json=hm.getMessagesWithPrefix(request.getLocale()).toString();

d18c02628675d0a2c816449d98bda930.png        

d18c02628675d0a2c816449d98bda930.png        out.print(newStringBuilder().append("var msg=").append(json).append(";"));

d18c02628675d0a2c816449d98bda930.png        out.close();

ecedf933ec37d714bd4c2545da43add2.png    }d18c02628675d0a2c816449d98bda930.png

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifprivateHierarchicalMessage getHierarchicalMessage()9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png        WebApplicationContext wc=WebApplicationContextUtils

d18c02628675d0a2c816449d98bda930.png                                     .getWebApplicationContext(getServletContext());

d18c02628675d0a2c816449d98bda930.png        HierarchicalMessage hm=(HierarchicalMessage)wc.getBean("msgBean");

d18c02628675d0a2c816449d98bda930.pngreturnhm;

ecedf933ec37d714bd4c2545da43add2.png    }d18c02628675d0a2c816449d98bda930.png

97e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifprivateString getBizId(HttpServletRequest request)9b8a8a44dd1c74ae49c20a7cd451974e.png{

d18c02628675d0a2c816449d98bda930.png        StringBuffer urlString=request.getRequestURL();

d18c02628675d0a2c816449d98bda930.pngintstart=urlString.lastIndexOf("/")+1;

d18c02628675d0a2c816449d98bda930.pngintend=urlString.lastIndexOf(".");

d18c02628675d0a2c816449d98bda930.pngreturnurlString.substring(start, end);

ecedf933ec37d714bd4c2545da43add2.png    }d18c02628675d0a2c816449d98bda930.png

8f1ba5b45633e9678d1db480c16cae3f.png}4f1150b881333f12a311ae9ef34da474.png

4f1150b881333f12a311ae9ef34da474.pngSpring配置:

4f1150b881333f12a311ae9ef34da474.png4f1150b881333f12a311ae9ef34da474.png4f1150b881333f12a311ae9ef34da474.pngi18n/messages4f1150b881333f12a311ae9ef34da474.png4f1150b881333f12a311ae9ef34da474.png4f1150b881333f12a311ae9ef34da474.pngsys4f1150b881333f12a311ae9ef34da474.png4f1150b881333f12a311ae9ef34da474.png4f1150b881333f12a311ae9ef34da474.png

4f1150b881333f12a311ae9ef34da474.pngWeb.xml配置:

4f1150b881333f12a311ae9ef34da474.png4f1150b881333f12a311ae9ef34da474.pngI18nServlet4f1150b881333f12a311ae9ef34da474.pngI18nServlet4f1150b881333f12a311ae9ef34da474.png4f1150b881333f12a311ae9ef34da474.png4f1150b881333f12a311ae9ef34da474.pngI18nServlet4f1150b881333f12a311ae9ef34da474.png/i18n/*4f1150b881333f12a311ae9ef34da474.png4f1150b881333f12a311ae9ef34da474.png

使用方法:

在html页面中先于功能js导入对应的语言js,名称相同,路径在/i18n/xxx.js

同时在根classpath下的i18n/messages资源下定义page.xxx.xxx

@2008 杨一. 版权所有. 保留所有权利

posted on 2008-12-23 12:07 杨一 阅读(2498) 评论(1)  编辑  收藏

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值