當前的富客戶端可以包含兩部分:分別為JSP
頁面和通過富客戶端js組件(如extjs)
渲染的組件化窗口頁。針對這兩部分分別做如下處理:
對于JSP頁面的部分采用JSTL標準庫的fmt標簽,如通過:
<fmt:message key="page.login.title"/>這樣的形式進行展現(xiàn),其中message對應(yīng)的文本在服務(wù)端配置,并在web.xml中配置資源文件的位置,也可以采用spring標簽,Structs標簽等多種機制。不過為了以后的程序修改兼容性,建議采用JSTL進行JSP頁面的國際化。
對于JavaScript,考慮到為提高效率,因為是靜態(tài)資源,可以很方便的在一定周期內(nèi)要在客戶端瀏覽器進行緩存,不同的瀏覽器會有不同的緩存機理,在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,為了緩存而不是每次下載為了實現(xiàn)富客戶端而集成的很大的js,不能用動態(tài)的網(wǎng)頁來生成(即把JavaScript包裝為JSP頁面,最簡單的,把js擴展名改成jsp并利用jsp的機制做國際化)。因此,需要對JavaScript中國際化的內(nèi)容通過變量單獨加載,舉例如下:
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對象的形式來獲取或者動態(tài)地進行服務(wù)端生成。
兩種方法的優(yōu)缺點定義如下:
方法
|
缺點
|
優(yōu)點
|
前臺主動定義
|
會產(chǎn)生大量零碎的文件(M個JavaScript文件需要對象N個語言的資源文件,總數(shù)M×N,如果把這些資源文件都放在一個JavaScript文件中定義,則對客戶端來說,要下載過多不必要的資源)
|
資源定義非常靈活,可以保證只定義自己需要的資源,并且可以做到隨時更改其內(nèi)容
|
后臺自動獲取
|
加重了服務(wù)器的負擔,需要用到AJAX或者類似dwr的服務(wù)端動態(tài)加載。具有一定的復(fù)雜性
|
可以和后臺及JSP頁面共享同一個資源定義文件,并動態(tài)生成資源定義文件,減少了開發(fā)人員的負擔
|
綜上,可以采取如下國際化方法:
針對JavaScript文件的國際化,分成兩部分來進行:
對于通用的文本定義,如:”確定”,”返回”等等,放在前臺的資源文件中,隨JavaScript文件一同加載,對于特殊的文本定義通過后臺自動獲取的形式來展現(xiàn),這樣就可以結(jié)合兩種方法的優(yōu)點。
后臺實現(xiàn)的如下:
按照命名規(guī)約定義頁面的文本元素,然后動態(tài)的生成一個如下的json對象:
{
messageName : messageValue
……
}
然后前臺頁面JavaScript在加載時獲取這個json對象,并應(yīng)用到頁面文本元素的定義中,如利用Extjs的使用方法:
var msg = Ext.util.json.decode(jsonString); 或者服務(wù)器動態(tài)生成時就表述為var msg={…};的形式,并在頭文件指向動態(tài)的地址(類似dwr動態(tài)生成的機制),然后就可以通過msg.XXX來獲得文本定義了。文中涉及的代碼如下:
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.ResourceBundle;

import net.sf.json.JSONObject;


/** *//**
* 根據(jù)層次結(jié)構(gòu)獲取到特定前綴的所有的資源名稱,并把它們放在一個JSON對象中返回,對于相同類型的資源請求進行緩存,
* 不再動態(tài)生成新的內(nèi)容。這個對象要納入到Spring的容器中進行管理,把bean的管理模式設(shè)置為單例模式就好,所以這里
* 沒有提供對于類的單例封裝
*
* * @author 楊一
*/


public class HierarchicalMessage
{

/** *//**資源對象的基礎(chǔ)名稱*/
private String bundleName;

/** *//**特定組件所使用的前綴*/
private String prefix;

/** *//**緩存對象用的哈希表*/
private HashMap<String, JSONObject> cachingMap = new HashMap<String, JSONObject>();

/** *//**設(shè)置或注入對象的基礎(chǔ)名稱*/

public void setBundleName(String bundleName)
{
this.bundleName = bundleName;
}


/** *//**設(shè)置或注入所使用的前綴*/

public void setPrefix(String prefix)
{
this.prefix = prefix;
}


/** *//**根據(jù)注入的結(jié)果返回語言包,(某些情況下,請求的資源是一定的)*/

public JSONObject getMessagesWithPrefix(Locale localeName)
{
return getMessagesWithPrefix(this.bundleName,this.prefix,localeName);
}

/** *//**
* 根據(jù)層次結(jié)構(gòu)獲取到特定前綴的所有的資源名稱,并把它們放在一個JSON對象中返回
* */

public JSONObject getMessagesWithPrefix(String bundleName, String prefix, Locale localeName)
{
JSONObject toReturn;
//拼接的緩存字符串的格式為:i18n/messages$page.login$zh_CN
String cachingString = new StringBuilder().append(bundleName).append("$").
append(prefix).append("$").append(localeName.toString()).toString();
toReturn = cachingMap.get(cachingString);

if(toReturn != null)
{
return toReturn;
}
toReturn = new JSONObject();
//此處無需緩存,因為Java核心庫會做這件工作
ResourceBundle rb = ResourceBundle.getBundle(bundleName, localeName);
Enumeration<String> e = rb.getKeys();
String keyRef = null;
String componentPrefix = new StringBuilder().append(prefix).append(".").toString();
int shortNameStartIndex = 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);
return toReturn;
}
}
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import HierarchicalMessage;


public class I18nServlet extends HttpServlet
{

/** *//**
* 動態(tài)生成一個用于國際化的JavaScript腳本
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException
{
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
HierarchicalMessage hm = getHierarchicalMessage();
hm.setPrefix(new StringBuilder().append("page.").append(getBizId(request)).toString());
//此處從session中獲取用戶的登陸語言環(huán)境
String json = hm.getMessagesWithPrefix(request.getLocale()).toString();
out.print(new StringBuilder().append("var msg=").append(json).append(";"));
out.close();
}


private HierarchicalMessage getHierarchicalMessage()
{
WebApplicationContext wc = WebApplicationContextUtils
.getWebApplicationContext(getServletContext());
HierarchicalMessage hm = (HierarchicalMessage)wc.getBean("msgBean");
return hm;
}


private String getBizId(HttpServletRequest request)
{
StringBuffer urlString = request.getRequestURL();
int start = urlString.lastIndexOf("/") + 1;
int end = urlString.lastIndexOf(".");
return urlString.substring(start, end);
}

}

Spring配置:
<bean id="msgBean" class="HierarchicalMessage" scope="singleton">
<property name="bundleName">
<value>i18n/messages</value>
</property>
<property name="prefix">
<value>sys</value>
</property>
</bean>

Web.xml配置:
<servlet>
<servlet-name>I18nServlet</servlet-name>
<servlet-class>I18nServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>I18nServlet</servlet-name>
<url-pattern>/i18n/*</url-pattern>
</servlet-mapping>

使用方法:
在html頁面中先于功能js導(dǎo)入對應(yīng)的語言js,名稱相同,路徑在/i18n/xxx.js
同時在根classpath下的i18n/messages資源下定義page.xxx.xxx
@2008 楊一. 版權(quán)所有. 保留所有權(quán)利