js文件国际化

   在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的使用)

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页