WW_TRANS_I18N_LOCALE」與「WW_TRANS_I18N_LOCALE」屬性

Struts2 i18n國際化(容許用戶自行選擇語言)轉
最近在學習struts2,學習資料是李剛著的《struts2權威指南》,這本書寫得很是好,很是有學習價值。我在學習過程當中,本身跟着作了些例子。下面就是關於在struts2中容許用戶自行選擇程序語言的原理和示例:

在不少成熟的商業軟件中,可讓用戶自由切換語言,當用戶進入系統時候,能夠出現一個下拉列表框,讓用戶選擇語言,一旦用戶選擇了本身須要使用的語言環境,整個系統的語言環境將一直是這種語言環境。
Struts2也能夠容許用戶自行選擇程序語言。並且,由於Struts2的支持,在程序中自行選擇語言環境將變得更加簡單。

一. Struts2國際化的運行機制
在Struts 2中,咱們能夠經過ActionContext.getContext().setLocale(Locale arg)能夠設置用戶的默認語言。不過,這種方式徹底是一種手動方式,並且須要編程實現。
爲了簡化設置用戶默認語言環境,Struts 2提供了一個名i18n的攔截器(Interceptor),而且將其住註冊在默認的攔截器棧中(defaultStack)。下面是Struts2的默認攔截器棧的配置片斷,代碼中粗體字表示的就是i18n的攔截器 
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servlet-config"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="debugging"/>
<interceptor-ref name="profiling"/>
<interceptor-ref name="scoped-model-driven"/>
<interceptor-ref name="model-driven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="static-params"/>
<interceptor-ref name="params">
  <param name="excludeParams">dojo\..*</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
     <param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
     <param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
</interceptor-stack>
i18n攔截器在執行Action方法前,自動查找請求中的一個名爲request_locale的參數。若是該參數存在,攔截器就將其做爲參數,並轉換成Locale對象,並將其設爲用戶默認的Locale(表明語言/國家環境)。
除此以外,i18n攔截器還會將上面生成的Locale對象保存在用戶Session的名爲「WW_TRANS_I18N_LOCALE」的屬性中。一旦用戶Session中存在一個名爲「WW_TRANS_I18N_LOCALE」的屬性,則該屬性指定的Locale將會做爲瀏覽者的默認Locale。

二. 建立下拉列表框
基於前面的介紹,爲了實現讓用戶自行選擇程序語言的功能,只需提供一個下拉列表框,讓下拉列表框中列出本應用所支持的各類語言,而且,當用戶選擇下拉列表框中某一項時,系統將該下拉項的值做爲request_locale參數提交給Struts2系統,
爲此,咱們將系統所支持的語言放入一個Map中,經過在JSP頁面中迭代該Map對象,經過這種方式,就能夠在頁面上列出系統所支持的所有語言,並讓用戶自由選擇。
下面定義了JavaBean,這個JavaBean裏保存了當前應用所支持的所有語言,該JavaBean的代碼以下:
//該JavaBean存放了系統所支持的所有語言。
public class Locales extends ActionSupport
{
//由於本實例也須要實現國際化,因此使用current做爲用戶當前的Locale
private Locale current;
//取得用戶當前Locale的setter方法
public void setCurrent(Locale cur)
{
  this.current = cur;
}
//取得本系統所支持的所有語言
     public Map<String, Locale> getLocales()
{
  //將當前系統支持的所有語言保持在Map對象中
         Map<String, Locale> locales = new Hashtable<String, Locale>();
  ResourceBundle bundle = ResourceBundle.getBundle("messageResource" , current);
  //添加當前系統支持的語言,key是系統支持語言的顯示名字,value是系統支持語言的Locale實例
         locales.put(bundle.getString("usen"), Locale.US);
         locales.put(bundle.getString("zhcn"), Locale.CHINA);
         return locales;
    }
}
在上面JavaBean中,咱們使用了一個Map對象來保存全部用戶支持的語言,該Map對象的key是所支持語言的顯示名字,而該Map對象的value是所支持語言的Locale實例。應用支持語言的顯示名字,也是經過國際化消息來生成的。
一旦定義了該JavaBean以後,就能夠在JSP頁面中建立該JavaBean的實例,併爲其傳入一個current參數,決定該JavaBean中的Locale參數,就能夠根據該Locale參數來決定怎樣顯示系統所支持語言顯示名稱。
爲了在JSP頁面中使用該JavaBean實例,使用下面標籤來建立該JavaBean實例。
<!-- 使用lee.Locales建立locales實例 -->
<s:bean id="locales" name="lee.Locales">
<!-- 爲locales實例這種current參數值 -->
<s:param name="current" 
  value="#SESSION_LOCALE == null locale : #SESSION_LOCALE"/>
</s:bean>
上面標籤建立了lee.Locales類的locales實例,併爲該實例傳入了current參數值,設置該參數值時使用了三目運算符,先判斷SESSION_LOCALE是否爲空,若是該SESSION_LOCALE爲空,則返回ValueStack中locale屬性值(即用戶瀏覽器設置的Locale);若是SESSION_LOCALE不爲空,則返回該SESSION_LOCALE的值(即用戶選擇的Locale)。
爲了讓該頁面中包含SESSION_LOCALE,使用Struts2的<s:set .../>標籤將用戶Session中的「WW_TRANS_I18N_LOCALE」屬性值設置成SESSION_LOCALE。
下面是完成該設置的標籤:
<!-- 將用戶Session中的「WW_TRANS_I18N_LOCALE」屬性值設置成SESSION_LOCALE。 -->
<s:set name="SESSION_LOCALE" value="#session['WW_TRANS_I18N_LOCALE']"/>
下面是該selectlanguage.jsp頁面的代碼:
<%@taglib prefix="s" uri="/struts-tags"%>
<script type="text/javascript">
function langSelecter_onChanged()
{
document.getElementById("langForm").submit();
}
</script>
<!-- 將用戶Session中的「WW_TRANS_I18N_LOCALE」屬性值設置成SESSION_LOCALE。 -->
<s:set name="SESSION_LOCALE" value="#session['WW_TRANS_I18N_LOCALE']"/>
<!-- 使用lee.Locales建立locales實例 -->
<s:bean id="locales" name="lee.Locales">
<!-- 爲locales實例這種current參數值 -->
<s:param name="current" 
  value="#SESSION_LOCALE == null locale : #SESSION_LOCALE"/>
</s:bean>
<!-- 讓用戶選擇語言的表單 -->
<form action="<s:url/$amp;>quot;$ id="langForm" 
     >
<!-- 輸出國際化提示 -->
     <s:text name="languag"/>
<!-- 使用s:select標籤迭代locales實例的locales Map屬性 -->
<s:select label="Language" list="#locales.locales" listKey="value" listValue="key"
        value="#SESSION_LOCALE == null locale : #SESSION_LOCALE"
        name="request_locale" id="langSelecter" 
        onchange="langSelecter_onChanged()" theme="simple"/>
</form>
注意:上面頁面中大量使用了Struts2的標籤,關於Struts2標籤的詳細用法,請參考本書第十章的講解。
上面頁面的原理是:使用<s:set .../>標籤實例化一個Locales對象,並使用<s:select ..../>標前來顯示該Locales對象的locales(Map類型)屬性, <s:select ..../>可使用一個下拉列表框來顯示Map類型的集合,本應用將該Map的key輸出成下拉列表項的顯示名稱,將該Map的value輸出成下拉列表項的值。
除此以外,頁面上面還有一段簡單的Javascript腳本,它會在用戶在選擇下拉列表中某一項後,提交包含「reqeust_locale」變量的表單到Action。
上面頁面和JavaBean一共使用了三個國際化key,因此須要在資源文件定義這三個key對應的國際化消息。由於本系統僅支持簡體中文和美式英語兩種環境(如須要增長其餘語言也很是簡單, 只須要增長更過的資源文件,並簡單修改Locales類便可),因此須要分別在中文資源文件中增長以下三項:
languag=選擇語言
usen=美式英語
zhcn=簡體中文
在英文資源文件中增長以下三項:
languag=Select Lanuage
usen=American English
zhcn=Simplified Chinese

三. 選擇程序語言
本應用爲了更好的安全性,將全部的JSP頁面都放在WEB-INF/jsp路徑下,從而避免了直接訪問JSP頁面,爲了讓全部的JSP頁面都能獲得Struts2的處理,在struts.xml文件中增長以下配置片斷:
<!-- 使用通配符號定義Action的name -->
<action name="*">
<!-- 將請求轉發該WEB-INF/jsp路徑下同名的JSP頁面 -->
<result>/WEB-INF/jsp/{1}.jsp</result>
</action>
若是在瀏覽器中請求selectlanguage.action,將看到選擇程序語言的頁面。
若是用戶經過上面的下拉列表框選擇了「美式英語」項後,將看到用戶選擇美式英語的頁面。
一旦定義了上面的頁面後,咱們就能夠在JSP頁面中經過<s:include .../>標籤來包含該頁面,包含該頁面後,就能夠自行選擇程序語言了。
例如在登錄頁面中經過以下標籤來包含上面選擇程序語言的頁面:
<!-- 包含讓用戶自行選擇程序語言的頁面 -->
<s:include value="selectlanguage.jsp"/>
在任何頁面中增長了上面代碼後,該頁面就能容許用戶自行選擇語言。一般,咱們只須要在應用的第一個頁面讓用戶選擇程序語言,後續頁面直接使用該語言便可。
若是瀏覽者在瀏覽器的地址欄訪問input.action,Struts2自動進入WEB-INF/jsp/input.jsp頁面,將看到容許用戶選擇程序語言的頁面。
若是用戶但願使用美式英語的語言,則在容許用戶選擇程序語言的頁面的下拉列表框中選中「美式英語」項,將看到使用美式英語界面的頁面。
若是用戶登錄成功,將看到美式英語環境下登錄成功的頁面。該頁面自動使用了美式英語的環境,這都是由於用戶選擇了美式英語的語言後,系統將用戶選擇設置成了Session的WW_TRANS_I18N_LOCALE屬性值,該Session屬性值直接決定Struts2系統的語言環境。





---------!!!!!特別提醒:Locales 必須繼承extends ActionSupport,這個是我折騰了一天的經驗教訓,網上有的就沒繼承的例子,不繼承的話,致使<s:bean id="locales" name="lee.Locales">
<!-- 爲locales實例這種current參數值 -->
<s:param name="current" 
  value="#SESSION_LOCALE == null locale : #SESSION_LOCALE"/>
</s:bean>
這裏傳值locale進去是空的,後邊就會出問題。javascript

相關文章
相關標籤/搜索