隨筆-34  評論-1965  文章-0  trackbacks-0

          國際化是商業系統中不可或缺的一部分,所以無論您學習的是什么Web框架,它都是必須掌握的技能。

          其實,Struts 1.x在此部分已經做得相當不錯了。它極大地簡化了我們程序員在做國際化時所需的工作,例如,如果您要輸出一條國際化的信息,只需在代碼包中加入FILE-NAME_xx_XX.properties(其中FILE-NAME為默認資源文件的文件名),然后在struts-config.xml中指明其路徑,再在頁面用<bean:message>標志輸出即可。

          不過,所謂“沒有最好,只有更好”。Struts 2.0并沒有在這部分止步,而是在原有的簡單易用的基礎上,將其做得更靈活、更強大。

          國際化Hello World

          下面讓我們看一個例子——HelloWorld。這個例子演示如何根據用戶瀏覽器的設置輸出相應的HelloWorld。

          1. 在Eclipse創建工程配置開發和運行環境(如果對這個步驟有問題,可以參考我早前的文章《為Struts 2.0做好準備》)。
          2. 在src文件夾中加入struts.properties文件,內容如下:
            struts.custom.i18n.resources=globalMessages
            Struts 2.0有兩個配置文件,struts.xml和struts.properties都是放在WEB-INF/classes/下。
            • struts.xml用于應用程序相關的配置
            • struts.properties用于Struts 2.0的運行時(Runtime)的配置
          3. 在src文件夾中加入globalMessages_en_US.properties文件,內容如下:
            HelloWorld=Hello World!
          4. 在src文件夾中加入globalMessages_zh_CN.properties文件,內容如下:
            HelloWorld=你好,世界!
            在此想和大家分享一個不錯的編寫properties文件的Eclipse插件(plugin),有了它我們在編輯一些簡體中文、繁體中文等Unicode文本時,就不必再使用native2ascii編碼了。您可以通過Eclipse中的軟件升級(Software Update)安裝此插件,步驟如下:
            1、展開Eclipse的Help菜單,將鼠標移到Software Update子項,在出現的子菜單中點擊Find and Install;
            2、在Install/Update對話框中選擇Search for new features to install,點擊Next;
            3、在Install對話框中點擊New Remote Site;
            4、在New Update Site對話框的Name填入“PropEdit”或其它任意非空字符串,在URL中填入http://propedit.sourceforge.jp/eclipse/updates/;
            5、在Site to include to search列表中,除上一步加入的site外的其它選項去掉,點擊Finsih;
            6、在彈出的Updates對話框中的Select the features to install列表中將所有結尾為“3.1.x”的選項去掉(適用于Eclipse 3.2版本的朋友);
            7、點擊Finish關閉對話框;
            8、在下載后,同意安裝,再按提示重啟Eclipse,在工具條看到形似vi的按鈕表示安裝成功,插件可用。此時,Eclpise中所有properties文件的文件名前有綠色的P的圖標作為標識。
          5. 在WebContent文件夾下加入HelloWorl.jsp文件,內容如下:
            <%@ page ?contentType="text/html; charset=UTF-8"%>
            <%@taglib prefix="s" uri="/struts-tags"%>
            <html>
            <head>
            ? ?
            <title>Hello World</title>
            </head>
            <body>
            ? ?
            <h2><s:text name="HelloWorld"/></h2>
            ? ?
            <h2><s:property value="%{getText('HelloWorld')}"/></h2>
            </body>
            </html>
          6. 發布運行應用程序,在瀏覽器地址欄中輸入http://localhost:8080/Struts2_i18n/HelloWorld.jsp ,出現圖1所示頁面。
            圖1 中文輸出
            圖1 中文輸出
          7. 將瀏覽器的默認語言改為“英語(美國)”,刷新頁面,出現圖2所示頁面。
            圖2 英文輸出
            圖2 英文輸出
          上面的例子的做法,與Struts 1.x的做法相似,似乎并不能體現Struts 2.0的優勢。不過,我在上面的例子用了兩種方法來顯示國際化字符串,其輸出是相同的。其實,這就是Struts 2.0的一個優勢,因為它默認支持EL,所示我們可以用getText方法來簡潔地取得國際化字符串。另外更普遍的情況——在使用UI表單標志時,getText可以用來設置label屬性,例如:
          <s:textfield name="name" label="%{getText('UserName')}"/>

          資源文件查找順序

          之所以說Struts 2.0的國際化更靈活是因為它可以能根據不同需要配置和獲取資源(properties)文件。在Struts 2.0中有下面幾種方法:

          1. 使用全局的資源文件,方法如上例所示。這適用于遍布于整個應用程序的國際化字符串,它們在不同的包(package)中被引用,如一些比較共用的出錯提示;
          2. 使用包范圍內的資源文件。做法是在包的根目錄下新建名的package.properties和package_xx_XX.properties文件。這就適用于在包中不同類訪問的資源;
          3. 使用Action范圍的資源文件。做法為Action的包下新建文件名(除文件擴展名外)與Action類名同樣的資源文件。它只能在該Action中訪問。如此一來,我們就可以在不同的Action里使用相同的properties名表示不同的值。例如,在ActonOne中title為“動作一”,而同樣用title在ActionTwo表示“動作二”,節省一些命名工夫;
          4. 使用<s:i18n>標志訪問特定路徑的properties文件。使用方法請參考我早前的文章《常用的Struts 2.0的標志(Tag)介紹》。在您使用這一方法時,請注意<s:i18n>標志的范圍。在<s:i18n name="xxxxx">到</s:i18n>之間,所有的國際化字符串都會在名為xxxxx資源文件查找,如果找不到,Struts 2.0就會輸出默認值(國際化字符串的名字)。

          上面我列舉了四種配置和訪問資源的方法,它們的范圍分別是從大到小,而Struts 2.0在查找國際化字符串所遵循的是特定的順序,如圖3所示:

          圖3 資源文件查找順序圖
          圖3 資源文件查找順序圖

          假設我們在某個ChildAction中調用了getText("user.title"),Struts 2.0的將會執行以下的操作:

          1. 查找ChildAction_xx_XX.properties文件或ChildAction.properties;
          2. 查找ChildAction實現的接口,查找與接口同名的資源文件MyInterface.properties;
          3. 查找ChildAction的父類ParentAction的properties文件,文件名為ParentAction.properties;
          4. 判斷當前ChildAction是否實現接口ModelDriven。如果是,調用getModel()獲得對象,查找與其同名的資源文件;
          5. 查找當前包下的package.properties文件;
          6. 查找當前包的父包,直到最頂層包;
          7. 在值棧(Value Stack)中,查找名為user的屬性,轉到user類型同名的資源文件,查找鍵為title的資源;
          8. 查找在struts.properties配置的默認的資源文件,參考例1;
          9. 輸出user.title。

          參數化國際化字符串

          許多情況下,我們都需要在動行時(runtime)為國際化字符插入一些參數,例如在輸入驗證提示信息的時候。在Struts 2.0中,我們通過以下兩種方法做到這點:

          1. 在資源文件的國際化字符串中使用OGNL,格式為${表達式},例如:
            validation.require=${getText(fileName)} is required
          2. 使用java.text.MessageFormat中的字符串格式,格式為{ 參數序號(從0開始), 格式類形(number | date | time | choice), 格式樣式},例如:
            validation.between=Date must between {0, date, short} and {1, date, short}
          在顯示這些國際化字符時,同樣有兩種方法設置參數的值:
          1. 使用標志的value0、value1...valueN的屬性,如:
            <s:text name="validation.required" value0="User Name"/>
          2. 使用param子元素,這些param將按先后順序,代入到國際化字符串的參數中,例如:
            <s:text name="validation.required">
            ? ?
            <s:param value="User Name"/>
            </s:text>

          讓用戶方便地選擇語言

          開發國際化的應用程序時,有一個功能是必不可少的——讓用戶快捷地選擇或切換語言。在Struts 2.0中,通過ActionContext.getContext().setLocale(Locale arg)可以設置用戶的默認語言。不過,由于這是一個比較普遍的應用場景(Scenario),所以Struts 2.0為您提供了一個名i18n的攔截器(Interceptor),并在默認情況下將其注冊到攔截器鏈(Interceptor chain)中。它的原理為在執行Action方法前,i18n攔截器查找請求中的一個名為"request_locale"的參數。如果其存在,攔截器就將其作為參數實例化Locale對象,并將其設為用戶默認的區域(Locale),最后,將此Locale對象保存在session的名為“WW_TRANS_I18N_LOCALE”的屬性中。

          下面,我將提供一完整示例演示它的使用方法。

          package tutorial;

          import java.util.Hashtable;
          import java.util.Locale;
          import java.util.Map;

          publicclass Locales {
          ? ?
          public Map<String, Locale> getLocales() {
          ? ? ? ?Map
          <String, Locale> locales =new Hashtable<String, Locale>(2);
          ? ? ? ?locales.put(
          "American English", Locale.US);
          ? ? ? ?locales.put(
          "Simplified Chinese", Locale.CHINA);
          ? ? ? ?
          return locales;
          ? ?}

          }
          tutorial/Locales.java

          <%@taglib prefix="s" uri="/struts-tags"%>
          <script type="text/javascript">
          <!--
          ? ?
          function langSelecter_onChanged() {
          ? ? ? ? document.langForm.submit();
          ? ? }
          //-->
          </script>
          <s:set name="SESSION_LOCALE" value="#session['WW_TRANS_I18N_LOCALE']"/>
          <s:bean id="locales" name="tutorial.Locales"/>
          <form action="<s:url includeParams="get" encode="true"/>" name="langForm"?
          ? ? style="background-color: powderblue; padding-top: 4px; padding-bottom: 4px;">
          ? ? Language:
          <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>
          LangSelector.jsp

          上述代碼的原理為,LangSelector.jsp先實例化一個Locales對象,并把對象的Map類型的屬性locales賦予下拉列表(select) 。如此一來,下拉列表就獲得可用語言的列表。大家看到LangSelector有<s:form>標志和一段Javascript腳本,它們的作用就是在用戶在下拉列表中選擇了后,提交包含“reqeust_locale”變量的表單到Action。在打開頁面時,為了下拉列表的選中的當前區域,我們需要到session取得當前區域(鍵為“WW_TRANS_I18N_LOCALE”的屬性),而該屬性在沒有設置語言前是為空的,所以通過值棧中locale屬性來取得當前區域(用戶瀏覽器所設置的語言)。

          你可以把LangSelector.jsp作為一個控件使用,方法是在JSP頁面中把它包含進來,代碼如下所示:
          <s:include value="/LangSelector.jsp"/>

          在例1中的HellloWorld.jsp中<body>后加入上述代碼,并在struts.xml中新建Action,代碼如下:
          <action name="HelloWorld">
          ? ?
          <result>/HelloWorld.jsp</result>
          </action>

          或者,如果你多個JSP需要實現上述功能,你可以使用下面的通用配置,而不是為每一個JSP頁面都新建一個Action。
          <action name="*">
          ? ?
          <result>/{1}.jsp</result>
          </action>

          分布運行程序,在瀏覽器的地址欄中輸入http://localhost:8080/Struts2_i18n/HelloWorld.action,出現圖4所示頁面:
          圖3 HelloWorld.action
          圖3 HelloWorld.action

          在下拉列表中,選擇“American English”,出現圖5所示頁面:
          圖3 HelloWorld.action
          圖4 HelloWorld.action
          可能大家會問為什么一定要通過Action來訪問頁面呢?
          你可以試一下不用Action而直接用JSP的地址來訪問頁面,結果會是無論你在下拉列表中選擇什么,語言都不會改變。這表示不能正常運行的。其原因為如果直接使用JSP訪問頁面,Struts 2.0在web.xml的配置的過濾器(Filter)就不會工作,所以攔截器鏈也不會工作。
          posted on 2006-11-01 19:06 Max 閱讀(73188) 評論(123)  編輯  收藏 所屬分類: Struts 2.0系列
          評論共2頁: 上一頁 1 2 

          評論:
          # re: 在Struts 2.0中國際化(i18n)您的應用程序 2006-11-02 08:27 | 壞男孩
          踩個腳印  回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序 2006-11-02 11:22 | Java菜鳥[匿名]
          十分感謝你的關于Struts 2的一系列文章,最近我正在學習Struts 2,由于時間緊,資料少,所以很感謝你的文章!
          請問你的文章來源是哪里,能不能共享一下,因為我的項目趕時間,另外請問你關于Struts2與Webwork2有什么區別和進步,有沒有這方面的文章,多謝指教!  回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序 2006-11-02 11:57 | 張先生
          謝謝樓上指點!能否介紹Struts2的標簽校驗?謝謝!  回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序 2006-11-02 14:22 | Max
          @張先生
          我的下一篇文章將會介紹一下Struts 2.0中的Converter,再一篇會介紹校驗部分。
          感謝大家的支持,我會再加把勁加快文章的更新速度。  回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序 2006-11-02 14:23 | Max
          @Java菜鳥[匿名]
          我已經給您回了郵件。  回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序 2006-11-02 14:43 | Java菜鳥[匿名]
          多謝指點,謝謝!@Max
            回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序 2006-11-03 21:23 | 一滴水
          謝謝了,收藏  回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序 2006-11-04 10:05 | Frank[匿名]
          我通過Software Update安裝插件propedit,Eclipse提示網絡連接有問題,Eclipse的網絡連接在哪里配置?盼高手指教.  回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序 2006-11-06 16:48 | Max
          @Frank[匿名]
          你好,可能是由于您的網絡不穩定或防火墻的問題。
          解決方法:
          1、檢查網絡是否連通;
          2、暫時關閉防火墻。  回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序 2006-11-07 15:03 | Frank[匿名]
          謝謝Max的回復.我試過關閉防火墻了,而且網絡連接沒有問題,但問題依舊.錯誤提示如下:
          在搜索期間遇到了網絡連接問題。
          無法訪問“http://propedit.sourceforge.jp/eclipse/updates/”。
          無法訪問站點:“http://propedit.sourceforge.jp/eclipse/updates/” [java.io.IOException]
          無法訪問站點:“http://propedit.sourceforge.jp/eclipse/updates/” [java.io.IOException]
            回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序 2006-11-08 09:42 | Max
          @Frank[匿名]
          請問您用的是什么網絡?教育網或ADSL?  回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序 2006-11-09 08:42 | Frank[匿名]
          通過代理服務器,電信的出口  回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序 2006-11-10 11:33 | Frank[匿名]
          網速太慢,MAX可否發我一個WEB TOOLS插件?謝謝先。
          mailto: yfrank2003@163.com  回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序 2006-11-16 11:26 | Frank[匿名]
          propedit插件可以更新,是MyEclipse須設代理。:)  回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序 2006-11-16 23:04 | Max
          @Frank[匿名]
          Good for you  回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序 2006-11-28 17:04 | tongor
          頂你個肺^^

          向你學習!!!  回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序 2006-12-09 16:47 | konhon 優華
          建議簡單解釋下原理.
          如: <s:url includeParams="get" encode="true"/>
          request_locale參數是怎麼樣加進來的.  回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序 2007-03-11 13:41 | praguesky
          謝謝MAX的文章...我現在也慢慢開始從struts1 向2轉型了.你的文章比較基礎.不過讓我轉型的步伐大大加快..真的很感謝  回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序[未登錄] 2007-03-15 11:29 | hunter
          學習中﹗﹗  回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序 2007-03-16 15:19 | film
          頂你個肺  回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序 2007-03-16 15:28 | yangdamao
          非常感謝提供寶貴資源并耐心回覆!  回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序[未登錄] 2007-03-16 18:37 | bird
          我頂你個肺﹗﹗﹗例子咋不能運行﹗﹗
          將瀏覽器的默認語言改為“英語(美國)”這句話啥意思﹗﹗
          怎么改﹗怎么沒有配置struts.xml
          速度﹗﹗急﹗﹗﹗  回復  更多評論
            
          # re: 在Struts 2.0中國際化(i18n)您的應用程序 2007-03-21 15:07 | Rookie
          @bird
          Search the fuck web
            回復  更多評論
            
          評論共2頁: 上一頁 1 2 
          主站蜘蛛池模板: 邹城市| 临城县| 达尔| 共和县| 板桥市| 宁津县| 天峨县| 托里县| 西乌珠穆沁旗| 留坝县| 观塘区| 韶山市| 丽水市| 莆田市| 曲周县| 城口县| 邢台市| 来凤县| 涟水县| 望都县| 西昌市| 武清区| 霍城县| 正蓝旗| 通江县| 亚东县| 集贤县| 喜德县| 晋宁县| 台南县| 句容市| 萍乡市| 都江堰市| 高平市| 台南县| 且末县| 蒲城县| 泸水县| 周口市| 宣城市| 阿巴嘎旗|