第一次寫部落格,先上我以前自己寫的一篇小文章。
JAVA
的國際化機制介紹
本文是翻譯SUN的官方網站的教程Internationalization
Tutorial
。
一 介紹
國際化(Internationalization)
是設計一個適用於多種語言和地區的應用程式的過程。適用於多種語言和地區的含義是當使用不同語言及處於不同的地區的使用者在使用這個應用程式時,應用程式必須使用他們能看懂的語言和符合他們文化習慣來顯示資訊。國際化有時候被簡稱為i18n,因為有18個字母在國際化的英文單詞的字母i和n之間。
一個國際化的程式通常具有以下特徵:
- 有一個附加的本地化資料(localized data)及擁有在全世界各個地區執行的能力。
- 文本的元素,比如狀態資訊或GUI截面的lables,不是直接寫(hardcoded)在程式中,而是被儲存在本地化的資料中,並且能被程式正確的動態使用。
- 支援新的語言時,不需要修改程式,不需要重新編譯。
- 文化差異的資料,比如日期和貨幣,必鬚根據擁護的語言和習慣顯示不同的格式。
- 可以被迅速的本地化。
本地化(Localization)
是指通過增加本地描述的構件(locale-specific components )和文字翻譯工作來使應用程式適應於不同的語言和地區的過程。本地化有時候被簡稱為l10n,應為有10個字母在本地化的英文單詞的字母l和n之間。通常本地化最耗時的工作應該是文字翻譯。本地化工作者們要根據地區的具體需求來為日期、數字和通貨等資料建立新的格式。其他類型的資料,象聲音,圖象等,也需要根據具體需要來決定是否本地化。
下面通過一個簡單的例子來說明如何給一個程式提供國際化的特性。這個例子在不同的語言環境下顯示不同的文本資訊。
一個簡單的例子
先看下面的一段代碼:
public class NotI18N {
static public void main(String[] args) {
System.out.println("Hello.");
System.out.println("How are you?");
System.out.println("Goodbye.");
}
}
如果你決定在上面的程式中給德國和法國的不同使用者顯示同樣的資訊。但是你的程式員卻不是個語言專家,他不懂德語和法語。所以你需要翻譯人員把它翻譯成德語和法語,但是你的翻譯人員不懂程式,所以你可以把這些資訊存到一個文本或其他格式的檔案中供翻譯人員使用。那麼,程式必須能顯示不同語言的資訊,並且你並不知道你希望為這個程式提供的下一個語言支援是什麼,或許是日語或許是別的什麼語言。
下面的代碼是一個國際化的代碼的例子:
import java.util.*;
public class I18NSample {
static
public void main(String[] args) {
String language;
String country;
if (args.length != 2) {
language = new String("en");
country = new String("US");
} else {
language = new String(args[0]);
country = new String(args[1]);
}
Locale currentLocale;
ResourceBundle messages;
currentLocale = new Locale(language, country);
messages = ResourceBundle.getBundle("MessagesBundle",
currentLocale);
System.out.println(messages.getString("greetings"));
System.out.println(messages.getString("inquiry"));
System.out.println(messages.getString("farewell"));
}
}
請注意:在上面的代碼中,資訊並沒有被hardcoded在代碼中!
如果想運行上面的代碼,請下載下面的檔案,存在你的workspace的相關package檔案存放的地方,這裡我把這幾個設定檔擱在名叫zhaoxf的workspace下,採用預設的包名,因此幾個properties檔案與Java
source codes和編譯後產生的Byte codes位於同一個目錄下,:
1、I18NSample.java
2、MessageBundle.properties
3、MessageBundle_de_DE.properties
4、MessageBundle_en_US.properties
5、MessageBundle_fr_FR.properties
下面看看這個程式的運行結果:
顯示法語資訊:
java I18NSample fr FR
Bonjour.
Comment allez-vous?
Au revoir.
顯示英語資訊:
java I18NSample en US
Hello.
How are you?
Goodbye.
從上面的代碼我們可以看出,在實現了國際化的代碼中,並沒有將需要顯示的資訊直接hardcode在代碼中,而是存在一個檔案中供程式使用。程式根據不同的語言和國家(Local)來取得檔案中不同資訊顯示。我們試著按一下的步驟一步一步分析這段代碼如何?了國際化:
1、建立properties檔案----本地化資料
properties檔案用來儲存程式和環境相關的資訊。必須以.properties的尾碼結尾,properties檔案是純文字格式的。在上面的例子中,一共有4個properties檔案。分別定義了不同語言和國家的打招呼、再見和問候時使用的語言。properties檔案使用名值對(key-value)的形式,如下所示:
greetings = Bonjour.
farewell = Au revoir.
inquiry = Comment allez-vous?
properties檔案的名字很重要,它的形式是basename_LL_CC.properties.LL表示語言代碼,CC表示國家代碼。語言代碼和國家代碼是Local類初始化的參數,basename是建立ResourceBundle對象的參數。
2、建立Local對象----不同語言和國家的標識
java.util.Local是JDK提供的標準API。這個類用來標識國家和語言。
我們可以建立一個local對象:
aLocale = new Locale("en","US");
這個對象標誌了一個地方,這個地方是美國,並且這裡的語言是英語。
這下面2個對象又表示什麼呢?
caLocale = new Locale("fr","CA");
frLocale = new Locale("fr","FR");
caLocale對象標誌的是加拿大並且那裡使用了法語,而frLocal標誌的是法國而那裡的語言是法語。
注意:Local對象只是一個標識類,建立了這個類的對象並不表示你的程式已經實現了國際化。這個類是給那些需要實現國際化的類使用的,它用來標識我們即將實現國際化的Local資訊。
3、建立ResourceBundle對象----本例中實現國際化的主要角色
java.util.ResourceBundle是JDK提供的標準API。它實際上是個抽象類別,同時它提供了建立它的子類的靜態Factory 方法。在例子程式中我們實際上使用的是ResourceBundle的子類PropertyResourceBundle的對象。通過它,我們可以根據Local對象來讀取不同的properties檔案,從而取得不同的資訊。除此之外,Java.util.ResourceBundle還提供另外一種資源類叫做
ListResourceBundle
,有關它的使用見
5
。
如果local = new
Locale("en","US");則讀取了MessagesBundle_en_US.properties檔案。
在例子中,用如下語句建立這個對象:
message = ResourceBundle.getBundle("MessagesBundle",
currentLocale);
4、用ResourceBundle讀取資訊----本地化實現了
讀取了propeties檔案後,我們就可以用ResourceBundle的執行個體通過getString(String
Key)方法來取得資訊了。如下的語句所示:
String msg1 =
messages.getString("greetings");
5、ListResourceBundle使用舉例
ListResourceBundel的使用與PropertyResourceBundle略有區別,ListResourceBundle將與國家地區有關的欄位資訊放在一個獨立的Java檔案裡面,同樣,這個Java檔案的命名也得遵循一定的規則,見下例:
Main函數內容不變,即:
包含簡體中文欄位資訊的Java檔案:MessageBundle_zh_CN.java
包含英文欄位資訊的Java檔案:MessageBundle_en_US.java
結論:
如上面的例子所示,實現國際化實際上並不困難。他需要你做一些計劃,並在程式中加入少量的額外編碼。