天天看點

Web應用程式中Resource Bundle技術概述

背景概述

世界經濟日益全球化的同時,一個應用程式需要在全球範圍内使用勢在必然。傳統的程式設計方法将可翻譯資訊如菜單按鈕的标簽,提示資訊,幫助文檔等文字資訊寫死在程式代碼中,不能很好的适應全球化發展,程式的擴充性差,維護成本高。一個能支援全球化的應用程式,必須實作單一可執行的程式,動态地使用資源(Single

Source Single Executable),圖1 是兩種模型的對比圖。

圖 1. 傳統的程式模型和支援全球化程式模型

Web應用程式中Resource Bundle技術概述
Web應用程式中Resource Bundle技術概述

對于一個能支援全球化的應用程式來說:

一方面需要考慮的是使用者的語言環境(我們稱作 Language Locale):這裡主要就是指翻譯,在不同的國家用他們自己的語言正确運作軟體,讓客戶感覺這個産品是為他們而設計的;

另一方面就是使用者的文化環境(我們稱作 Culture Locale):主要處理的是多元文化的支援,包括貨币、月曆、時間、日期、排序、界面方向性(Bi-directional) 等符合各個國家自己習慣的顯示方式。

圖2 概述了如何使得一個應用程式(C/S 或者 B/S)支援全球化和本地化。

圖 2. 全球化應用程式

Web應用程式中Resource Bundle技術概述

本文結合項目實踐,總結了 web 應用程式中 Java,JSP,Dojo 和 HTML 四種不同語言是如何管理 Resource

Bundle

的,實作單一可執行程式動态讀取資源檔案,進而支援全球化和本地化。主要從三個方面來闡述:資源檔案存儲和命名規則;使用者語言區域資訊的讀取;如何取得對應語言的資源檔案中的鍵值。

Java 程式中的 Resource Bundle 管理

ResourceBundle 是一個機制,主要用來根據使用者的語言環境展示不同的界面文字給使用者,讓使用者感覺這個應用程式為我而定制。

然而 Java 中的 ResourceBundle 是一個類,包含在标準的 Java 發行版中。圖3總結了 Java 程式中 ResourceBundle 的管理機制。

圖 3. Java 程式 Resource Bundle 管理流程

Web應用程式中Resource Bundle技術概述
Web應用程式中Resource Bundle技術概述

Java 程式中資源檔案的存儲和命名

在一個多子產品的 Java 應用程式中,一般每個子產品都有自己獨立的資源檔案(也叫 Resource Bundles),Resource

Bundle 一般存儲在對應子產品的 src/resources/bundles/java/ 目錄下面。通常的命名規則是:子產品名_語言_國家

.properties({moduleName}_{language}_{country}.properties)。對應資源檔案中的每一個

key,一般都是小寫字母開頭,用下劃線表示這個 key 在程式中的層級結構,并且按照字母順序排序,便于管理和查找,如清單1所示的例子。

清單 1. Java properties 檔案示例

英文Properties 檔案: 

    helloKey=Hello! 

    goodMorningKey=Good Morning! 

    goodEveningKey=Good Evening! 

日語Properties 檔案: 

    helloKey=\u3053\u3093\u306b\u3061\u306f! 

    goodMorningKey=\u304a\u306f\u3088\u3046! 

    goodEveningKey=\u3053\u3093\u3070\u3093\u306f! 

Java 程式對資源檔案的復原機制:當對應翻譯的資源檔案不存在時,将使用"預設"的資源檔案(通常為英文),圖 4 是 Java 資源檔案的組織方式。

圖 4. Java 資源檔案組織方式

Web應用程式中Resource Bundle技術概述

Java 中使用者語言環境(Locale)和資源檔案的讀取

根據使用者使用的區域資訊來決定從哪個 Resource Bundle 裡面讀取對應的 key 值。Java 語言通過

java.util.Locale 類來表示區域,一個 Locale

執行個體就代表了一個特定的區域。在實際的項目中,通常将讀取資源檔案包裝成一個類,友善後續代碼的重用和管理,如清單 2 的示例所示。

清單 2. Java 中 ResourceBundleService 使用

public class LocalizedPropertyResources extends MessageResources {  

private static final String MODULE_NAME = "resourceBundle.module.name";  

public String getProperty(String key, Object... parameters) {  

Locale locale = getUserLocale();  

String value = getProperty(key, locale, parameters);  

Return value;  

}  

public String getProperty(String key, Locale locale, Object... parameters) {  

ResourceBundle resourceBundle = ResourceBundle.getBundle(MODULE_NAME, locale);  

String value resourceBundle.getString(key, parameters);  

return value;  

JSP 中的 Resource Bundle 管理

資源檔案管理:JSP 是基于 Java 技術,是以 Java 中的 ResourceBundle 機制也可以應用于 JSP,同樣以

.properties 形式存儲資源檔案,資源檔案的命名規則、資源檔案的存儲結構,key 的命名規則等都可以遵循 Java 程式中的

Resource Bundle 管理機制。

使用者語言環境的設定:HTTP 協定通過 Accept-Language 請求頭将本地化資訊從浏覽器傳遞至伺服器, JSTL fmt

庫中的定制标記又會利用這些方法來自動地确定使用者的語言環境,進而相應地調整它們的輸出。同時使用者也可以通過 來設定使用者語言環境。

對于 JSP 中資源檔案的讀取有以下三種情況:

1、使用 fmt 消息标簽:JSP 标準标簽庫(JSP Standard Tag Library,JSTL)中的

fmt标簽支援通過資源檔案(ResourceBundle)對文本内容進行本地化,該功能可以對一個特定的語言請求作出相應的響應,它使用了 J2SE

的 ResourceBundle 來保持各種翻譯過的語言編碼。另外用來設定地區,比如,這等于設定了語言和國家代碼。預設 JPS 将讀取

Accept-Language 資訊。還可以指定 ResourceBundle,比如: 。一旦設定了 locale(地區)或

ResourceBundle,就可以使用 來把原文進行相應的轉化,同時還可以使用<

fmt:requestEncoding/>來設定請求的字元編碼。如清單3 示例所示:

清單 3. JSTL fmt 标簽示例

//myTest.jsp 

<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> 

<html> 

  <head> 

    <title>JSTL fmt: Localized tag testing</title> 

  </head> 

 <body> 

  <fmt:requestEncoding value="UTF-8" /> 

  <fmt:setLocale value="zh_TW"/> 

  <fmt:setTimeZone value= "GMT+8" scope="request"/> 

  <fmt:bundle basename="src.resources.bundles.java.menu "> 

      <fmt:message key="OK"/><br/> 

      <fmt:message key="CANCEL"/><br/> 

  </fmt:bundle> 

//也可以通過下面的方式擷取資源檔案 

  <fmt:setBundle basename="src.resources.bundles.java.menu"    var="resources"/> 

    … 

    <fmt:message key="OK"/><br/> 

    <fmt:message key="CANCEL"/><br/> 

     … 

  </body> 

</html> 

2、被 Spring 管理的 JSP,通常 JSP 中有這樣的 taglig"",這種情況下可以使用 Spring message 标簽。

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>  

<spring:message code="common_button_ok"/> 

3、對于由 Struts 操作類提供的JSP,可以使用 Struts bean 消息标簽:

<%@ taglib uri="/tags/struts-bean" prefix="bean" %>  

<bean:message key=" common_button_ok "/> 

Dojo 中的 Resource Bundle 管理

Dojo 是一個 JavaScript 庫,提供了一個有用的工具來建立豐富的 Web 用戶端界面。同時 Dojo 也提供了 API

支援全球化功能,如翻譯資源包,函數的格式化和解析日期、數字和貨币,Dojo 對全球化的支援主要基于 CLDR (Common Locale

Data Repository) 和 ICU 的使用。 這一小節總結了 Dojo

中資源檔案的管理,使用者區域資訊(locale)和資源檔案的讀取,如圖5所示。

圖 5. Dojo 中資源檔案管理

Web應用程式中Resource Bundle技術概述
Web應用程式中Resource Bundle技術概述

Dojo 中資源檔案的存儲和命名

UTF-8 是 Dojo 程式編碼的先決條件,Dojo 腳本一般将使用 HTML,JSP,Servlet,js等編寫,是以這些檔案必須以

UTF-8 編碼。Dojo 用 JSON 格式來組織資源檔案,首先在 /nls

目錄下有一個主資源檔案(一般是英文),主資源檔案中定義了支援的區域,區域的值設定為 true 或者 false,如清單4所示。

清單 4. Dojo 主資源檔案的定義

define({ 

      root: { 

        OK: "Ok", 

        CANCEL: "Cancel", 

        OK_CANCEL: "${OK}, ${CANCEL}" 

      }, 

      "ko": true, 

      "ja": true, 

      "ru": false, 

      "zh-cn": true 

    }); 

翻譯的資源檔案應放在/ nls / 目錄中,目錄的命名需要符合下面的規範:

目錄的名稱必須要全部小寫

用橫線(而不是下劃線)分割語言和國家,比如 zh-cn,zh-tw 等,如清單5所示。

清單 5. 翻譯資源檔案的目錄結構

/src/web/js/nls/menu.js       ... 主資源檔案,用于預設的消息顯示 

    /src/web/js/nls/ko/menu.js    ... 韓語的翻譯檔案 

                    /ja/menu.js    ... 日語的翻譯檔案 

                    /ru/menu.js    ...俄語的翻譯檔案 

                     /zh-cn/menu.js  ...簡中的翻譯檔案 

                    ... 

Dojo 資源檔案的復原機制為:在 / nls 目錄的根目錄下如果檢測到區域設定,但 nls 目錄中不存在特定于區域設定的資源,則将使用主包;當主資源檔案中某個語言設定為 false 時,即使該語言的資源檔案存在,也将使用主包。

Dojo 中使用者語言環境(Locale)和資源檔案的讀取

Dojo 和 Java 以相同的方式支援使用者區域資訊,但 Dojo 和 Java 實作之間存在微小差異。

"Dojo 和 Java 對區域設定命名約定有一些差別,Dojo 使用" - "(連字元)作為連接配接語言代碼,國家代碼和變體的分隔符,而 Java 使用"_"(下劃線)。例如,Java 中的 "zh_CN" 與 Dojo 中的 "zh-cn" 相似。

像 Java 中的預設使用者語言區域一樣,Dojo 有一個全局變量 dojo.locale 用來存儲預設 locale

值,但是我們不能直接修改 dojo.locale,可以通過 dojoConfig.locale 來對 dojo.locale 做初始化工作。

如果 dojoConfig.locale 未定義,Dojo 使用浏覽器的顯示語言作為使用者區域設定。另外

dojoConfig.locale 的設定需要在加載 dojo.js 之前,這樣設定的 dojoConfig.locale 才會起效果。如清單

6 是一個示例将使用者的 locale 資訊儲存在 sessionScope,然後傳遞給 dojoConfig。

清單 6. 将使用者 locale 儲存在 sessionScope 傳遞給 dojoConfig

var dojoConfig = { 

            async: 'sync', 

            baseUrl: '', 

            locale: '${sessionScope.userLanguageLocale}', 

             bindEncoding: "utf-8", 

                … 

        }; 

userLanguageLocale:是應用程式中使用者所設定的 locale,每個應用程式可能不太一樣。

Dojo 中有兩種方式讀取資源檔案:

方式 1:又叫 AMD 方式,通過 dojo/i18n! 這個插件加載資源檔案,首先檢測 dojoConifg.locale

是否設定,如果設定了就讀取 dojoConfig.locale,否則就會使用浏覽器的顯示語言讀取對應的翻譯資源檔案。清單 7 是

dojo/i18n! 的使用示例。

清單 7. Dojo/i18n!使用示例

...  

<script src="dojo-release-1.9.1/dojo/dojo.js" data-dojo-config="async: true, parseOnLoad: true></script>  

<script>  

require(["dojo/string", "dojo/i18n!js/nls/menu"],  

function(string, resources){  

var strOk = resources.OK;  

alert(strOk);  

});  

</script>  

... 

方式 2: 使用 dojo.requireLocalization 加載資源檔案,dojo.i18n.getLocalization

讀取資源檔案,這個是舊的資源加載方式,新的 Dojo 版本都将采用 AMD 的方式,不過這種方式使用者可以指定 locale 資訊,預設

locale 的時候,采用和 AMD 同樣的 locale 解析方式。清單8 是一個示例。

清單 8. Dojo. requireLocalization 使用示例

dojo.require("dojo.i18n");  

dojo.requireLocalization("js", "menu");  

var resources = dojo.i18n.getLocalization("js", "menu", locale);  

//或者省去 locale 參數,var resources = dojo.i18n.getLocalization("js", "menu")  

alert(resources.OK);  

HTML 中的 Resource Bundle 管理

HTML 中的寫死(Hard Code)通常分為兩種情況:一種情況是 HTML 頁面不涉及任何程式設計邏輯,這時候可以翻譯整個 HTML

檔案(這種方式在開發過程中不需要特殊處理),或者将 HTML 變更為 JSP,這樣就可以利用 JSP 中 fmt 标簽将 Hard Code

提取出來,如清單 9 示例所示。

清單 9. HTML 更改為 JSP

//Index.html  

<html>  

<head>  

<script language="JavaScript">  

window.location = "/login.do";  

<title> Welcome Page </title>  

</head>  

<body>  

…  

</body>  

</html>  

//将 Index.html 更改為 Index.jsp,這樣就可以利用 JSP 中 fmt 标簽  

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>  

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>  

<title> <fmt:message key="common_welcome" /></ title>  

//test.properties 

 Common_welcome=Welcome Page  

… 

//将 Index.html 更改為 Index.jsp,這樣就可以利用 JSP 中 fmt 标簽

另外一種情況是 HTML 作為 Dojo widget 模闆檔案,這種情況下可以使用 dojo API 的 i18n

庫來處理寫死消息,其處理方式和 Dojo 很類似,模闆 HTML 檔案中使用的 Key 需要在 Widget 的 js

檔案中定義和擷取。下面将通過示例介紹 HTML 作為 Dojo 模闆檔案時,如何抽取當中的 hard code 資訊。通常分三個步驟完成模闆

HTML 檔案中的字元串抽取。

第一步: 将 HTML 中的字元串放到一個資源檔案如 message.js 中,資源檔案的組織方式和 Dojo 是一樣的;

第二步: 在 Dojo widget 的 js 檔案中使用 Dojo Resource Bundle 擷取資源檔案,定義變量擷取對應的Key值;

第三步: 在HTML模闆檔案中使用 Dojo .js 檔案中定義的變量。如清單 10 所示。

清單 10. HTML 作為 Dojo Widget 模闆

Test.html  

<div dojoAttachPoint="testNode" style="display:inline">  

<table style="position: relative; margin: 20px 0 0 120px; padding: 0;">  

<tr>  

<td style="text-align: right;">Username:</td> //原來的 hard code  

<td style="text-align: right;">${usernameLabel}</td> //Resource out 之後的變量引用  

….  

</tr>  

</div>  

Test.js  

dojo.requireLocalization("js", "message");  

dojo.declare("Test") {  

templatePath: dojo.moduleUrl("common", " /html/Test.html"),  

usernameLabel: "",  

postMixInProperties: function(){  

this.inherited(arguments);  

var resources = dojo.i18n.getLocalization("js", "message");  

this.usernameLabel = resources.labels.username; //擷取資源檔案  

清單 11. HTML 中特殊寫死處理

// Hard Code  

<select id="Product">  

<option>Is Not</option>  

<option>Is</option>  

</select>  

//處理後的 HTML  

<option value="Is Not"> ${ Label.IS_NOT}</option> 

<option value="Is">${Label.IS}</option>  

總結

本文總結了如何存儲 web 應用程式中使用不同架構時的資源檔案及其命名規則,如何取得資源檔案中的鍵值。希望這篇文章能為正在開發國際化 Web 應用程式的讀者提供一定的參考價值。

本文作者:佚名

來源:51CTO