js国际化

转载 2011年10月15日 11:00:09
   在Java项目中,尤其是WEB项目中,一般都是通过Struts框架的特性进行国际化的。
在采用Struts的项目架构中,借用Struts的的国际化标签等特性,可以非常方便的对jsp文件及action类文件进行国际化。但是,在一个面向大众用户的, 开放的WEB应用中,通常有非常多的js文件,如何对js文件进行国际化呢?
在互联网上,通过baidu,google,查找,对js国际化的方法一般是:
jsp页面中,通过判断客户端的Locale(request.getLocale()),加载不同语言的js文件,对图片的处理方法也是类似。不同语言 的js文件,内容上基本一致,只是把需要显示的文字翻译成不同语言的文字。缺点:不是真正的国际化,如果需要100个国家语言的用户访问,就得需要的 100个js文件。 

对于jsp文件,是通过struts国际化标签,在服务器端根据locale输出特定Locale的消息。因此,设想,js文件,能够也通过后台输出特定locale国际化的消息。
基本理论就是:
借用ajax,struts技术,js需要国际化的消息,通过ajax技术,通过后台输出,后台处理方式完全和jsp,action类中的处理方式一致. 

详细代码实现:
 
系统采用的框架:struts2.1.6 + spring+hibernate+dwr2.06.
其中dwr是个ajax框架,封装了ajax的调用。

1.js需要请求国际化的消息,必然要和服务器交互,也即通过js调用java类中的方法,这可以通过dwr实现。
java类:
JSActionSupport.java 
/*
* Copyright (c) 2002-2006 by OpenSymphony
* All rights reserved.
*/
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.Serializable;
import java.util.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.directwebremoting.WebContext;
import org.directwebremoting.WebContextFactory;

import javax.servlet.http.HttpServletRequest;


/**
* 这个类实际上就是struts2中的ActionSupport类的修改,主要修改了getLocale方法,目的是通过ajax调用,获取ajax请求中的locale。同时增加了2个方法 getMsg,getMsgs,用与暴露给js远程调用。
* JS ActionSupport for get the International message
* @see ActionSupport class
*/
 
public class JSActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable 
{

protected static Log LOG = LogFactory.getLog(ActionSupport.class);

private final transient TextProvider textProvider = new TextProviderFactory().createInstance(getClass(), this);
private final ValidationAwareSupport validationAware = new ValidationAwareSupport();
   /**
* Get the International Message by the key
* @param key
* @return
*/
public String getMsg(String key)
{
return this.getText(key);

    /**
* Get the International Message by key collection
* @param key
* @return
*/
public List<String> getMsgs(List<String> key)
{
List<String> result=new ArrayList<String>();
for(String temp:key)
{
result.add(this.getMsg(temp));
}    
return result;
}
 

public void setActionErrors(Collection errorMessages) {
validationAware.setActionErrors(errorMessages);
}

public Collection getActionErrors() {
return validationAware.getActionErrors();
}

public void setActionMessages(Collection messages) {
validationAware.setActionMessages(messages);
}

public Collection getActionMessages() {
return validationAware.getActionMessages();
}

/**
* @deprecated Use {@link #getActionErrors()}.
*/
public Collection getErrorMessages() {
return getActionErrors();
}

/**
* @deprecated Use {@link #getFieldErrors()}.
*/
public Map getErrors() {
return getFieldErrors();
}

public void setFieldErrors(Map errorMap) {
validationAware.setFieldErrors(errorMap);
}

public Map getFieldErrors() {
return validationAware.getFieldErrors();
}

    /**
* 重写了这个方法,获取ajax请求中的locale,stuts2中的类会调用此方法。
* Get Locale from dwr request
*/
public Locale getLocale() {
//return ActionContext.getContext().getLocale();
WebContext webCxt=WebContextFactory.get();  
HttpServletRequest request = webCxt.getHttpServletRequest();
Locale result = request.getLocale();
return result;
}
 

public String getText(String aTextName) {
return textProvider.getText(aTextName);
}

public String getText(String aTextName, String defaultValue) {
return textProvider.getText(aTextName, defaultValue);
}

public String getText(String aTextName, String defaultValue, String obj) {
return textProvider.getText(aTextName, defaultValue, obj);
}

public String getText(String aTextName, List args) {
return textProvider.getText(aTextName, args);
}

public String getText(String key, String[] args) {
return textProvider.getText(key, args);
}

public String getText(String aTextName, String defaultValue, List args) {
return textProvider.getText(aTextName, defaultValue, args);
}

public String getText(String key, String defaultValue, String[] args) {
return textProvider.getText(key, defaultValue, args);
}

public String getText(String key, String defaultValue, List args, ValueStack stack) {
return textProvider.getText(key, defaultValue, args, stack);
}

public String getText(String key, String defaultValue, String[] args, ValueStack stack) {
return textProvider.getText(key, defaultValue, args, stack);
}

public ResourceBundle getTexts() {
return textProvider.getTexts();
}

public ResourceBundle getTexts(String aBundleName) {
return textProvider.getTexts(aBundleName);
}

public void addActionError(String anErrorMessage) {
validationAware.addActionError(anErrorMessage);
}

public void addActionMessage(String aMessage) {
validationAware.addActionMessage(aMessage);
}

public void addFieldError(String fieldName, String errorMessage) {
validationAware.addFieldError(fieldName, errorMessage);
}

public String input() throws Exception {
return INPUT;
}

public String doDefault() throws Exception {
return SUCCESS;
}

/**
* A default implementation that does nothing an returns "success".
* <p/>
* Subclasses should override this method to provide their business logic.
* <p/>
* See also {@link com.opensymphony.xwork2.Action#execute()}.
*
* @return returns {@link #SUCCESS}
* @throws Exception  can be thrown by subclasses.
*/
public String execute() throws Exception {
return SUCCESS;
}

public boolean hasActionErrors() {
return validationAware.hasActionErrors();
}

public boolean hasActionMessages() {
return validationAware.hasActionMessages();
}

public boolean hasErrors() {
return validationAware.hasErrors();
}

public boolean hasFieldErrors() {
return validationAware.hasFieldErrors();
}

/**
* Clears all errors and messages. Useful for Continuations and other situations
* where you might want to clear parts of the state on the same action.
*/
public void clearErrorsAndMessages() {
validationAware.clearErrorsAndMessages();
}

/**
* A default implementation that validates nothing.
* Subclasses should override this method to provide validations.
*/
public void validate() {
}

public Object clone() throws CloneNotSupportedException {
return super.clone();
}

/**
* <!-- START SNIPPET: pause-method -->
* Stops the action invocation immediately (by throwing a PauseException) and causes the action invocation to return
* the specified result, such as {@link #SUCCESS}, {@link #INPUT}, etc.
* <p/>
*
* The next time this action is invoked (and using the same continuation ID), the method will resume immediately
* after where this method was called, with the entire call stack in the execute method restored.
* <p/>
*
* Note: this method can <b>only</b> be called within the {@link #execute()} method.
* <!-- END SNIPPET: pause-method -->
*
* @param result the result to return - the same type of return value in the {@link #execute()} method.
*/
public void pause(String result) {
}

}

2.配置dwr(dwr.xml),达到暴露给js远程调用的目的。 
   getMsg(String key)可以实现获取单个key的国际化消息,但是一个js文件中,可能文件中的不同地方都需要国际化的消息,而如果通过getMsg(String key),则导致多次ajax请求,增大服务器压力,因此,可以通过集合方式(getMsgs(List<String> key),一个文件中,一次ajax请求,获取该文件中全部的国际化消息。
 
<dwr>
<allow>
<!--International support for js-->
<create creator="spring" javascript="jsActionSupport">
<param name="beanName" value="jsActionSupport"/> 
<include method="getMsg"/> 
<include method="getMsgs"/>   <!-- JSActionSupport类中,仅这2个方法暴露给远程调用-->
</create>
<convert converter="list" match="java.util.List"/>
</allow>
<signatures>  
<![CDATA[
import java.util.List;
import JSActionSupport;
JSActionSupport.getMsgs(List<String>key);
]]> 
</signatures>  
</dwr>
具体的dwr使用与配置,可以参考dwr文档。
然后可以通过http://localhost/webcontext/dwr/,进行测试dwr是否部署正确。

3.编辑资源文件,方法和struts国际化资源文件一样。为了逻辑清晰,可以把专属于js调用的国际化消息单独放在一个资源文件中 (JSActionSupport.properties,JSActionSupport_en.properties),这个资源文件和 JSActionSupport在同一类包中(package)。

4.客户端js文件编写与调用 
example.js文件内容

dwr.engine.setAsync(false);
var jsResult;
var jsPara;
jsPara=["key1",
"key2",
"key3"        
];
jsActionSupport.getMsgs(jsPara,function(data)   <!-- js远程调用Java方法 -->
{
jsResult=data;
}); 

function exampleTest()
{
alert(jsResult[0];
alert(jsResult[1];
}

总结:
国际化的本质都是通过判断客户端请求头携带的locale信息,根据locale输出国际化消息。

参考资料:

1.http://directwebremoting.org/dwr/index.html (可以下载dwr组件及文档,接受了dwr的使用)

2.http://blog.csdn.net/wen1019/article/details/4785190

网站多语言策略(即国际化策略)——Javascript实现

本文根据当下企业向国际化发展趋势,对企业网站的多语言(即国际化)的设计方案做详细讲解。...
  • yangyuyu77584
  • yangyuyu77584
  • 2014年10月04日 10:53
  • 2933

一个极端的前端国际化方法

最近一直在做整个页面的国际化,相信很多小伙伴们都做过,前端主要采用的是Angularjs,后端使用的是Spring来做国际化,那么他们的优点,缺点现在一起来总结一下。其实无论用哪种语言做国际化,感觉都...
  • liaodehong
  • liaodehong
  • 2016年08月29日 15:41
  • 5654

基于jQuery.i18n.properties 实现前端页面的资源国际化

jQuery.i18n.properties是一款轻量级的jQuery国际化插件,能实现Web前端的国际化。 国际化英文单词为:Internationalization,又称i18n,“i”为单词的第...
  • aixiaoyang168
  • aixiaoyang168
  • 2015年10月22日 17:58
  • 9613

js 国际化实现

  • 2015年05月28日 09:40
  • 1KB
  • 下载

Js国际化插件

  • 2013年06月06日 21:38
  • 2KB
  • 下载

国际化 js插件

  • 2017年10月25日 16:23
  • 15KB
  • 下载

js jquery 国际化 全兼容

  • 2012年02月29日 15:26
  • 26KB
  • 下载

tornado实现在JS文件的国际化和静态文件的引用

在一个tornado的项目中,需要在JS代码文件中也可以实现国际化和static_url()方法来引用静态文件。 而项目中使用了mako的模板引擎,正常情况下只是模板中可以实现国际化和使用static...
  • cloveses
  • cloveses
  • 2016年04月14日 20:51
  • 1131

angular.js 国际化模块 angular-translate 简单方便快捷翻译中英文等多语言环境

很多web服务面对的不仅仅是当地用户,多语言环境不仅能提升逼格,更重要是一种用户体验. angular.js 作为前后端拆分的解决方案之一,当然离不开前端框架处理国际化的问题,a...
  • daniel7443
  • daniel7443
  • 2016年04月15日 11:41
  • 4554

js简单实现国际化

最近碰到一个项目, 前台展示需要实现国际化(中英法俄西), 前台使用 freeMark 技术展示, 都是一些html , 因为是在网上找的开源项目, 只需要修改前台页面即可, 将前台 html 中的中...
  • u011526234
  • u011526234
  • 2015年10月22日 14:07
  • 444
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:js国际化
举报原因:
原因补充:

(最多只允许输入30个字)