使用java編寫(xiě)一個(gè)帶GUI程序或者其他需要給用戶(hù)傳遞文字信息的程序的時(shí)候,就很有可能需要用到國(guó)際化的知識(shí),來(lái)總結(jié)一下。
所謂的國(guó)際化,就是使編寫(xiě)的程序可以適應(yīng)不同的語(yǔ)言環(huán)境,比如,在中文環(huán)境下,可以與用戶(hù)使用中文交互,在英文環(huán)境下則切換為英文。而這個(gè)切換過(guò)程不需要修改代碼或者僅僅修改少量的代碼。java給我們提供了這樣的實(shí)現(xiàn)。
java文件國(guó)際化
我們通過(guò)將與界面顯示有關(guān)系的資源提取出來(lái)到資源文件中,然后讀取不同的資源文件來(lái)達(dá)到國(guó)際化的目的。在java中,這些是通過(guò)ResourceBundle這個(gè)類(lèi)來(lái)實(shí)現(xiàn)的。
ResourceBundle分為兩種,一種是ListResourceBundle,另一種是PropertyResourceBundle。下面介紹這兩種ResourceBundle的使用方法:
首先列出demo工程的代碼結(jié)構(gòu):
TestResourceBundle
|
|--src
|
|--kyu
|
|--bundle
| |
| |--ListResourceTranslator.java
| |
| |--PropertyResourceTranslator.java
| |
| |--ResourceTranslator.java
|
|--test
| |
| |--App.java
|
|--Errors_en_Us.java
|
|--Errors_zh_CN.java
|
|--Errors.java
|
|--Errors_en_Us.properties
|
|--Errors_zh_CN.properties
|
|--Errors.properties
PropertyResourceBundle
- 首先需要建立若干語(yǔ)言的properties文件: 自定義名語(yǔ)言代碼國(guó)別代碼.properties
比如:errors_en_US.properties, errors_zh_CN.properties
其中的語(yǔ)言代碼和國(guó)別代碼,分別是你要國(guó)際化的語(yǔ)言。需要幾種語(yǔ)言,就添加幾個(gè)properties文件。
通過(guò)打印java所支持的語(yǔ)言和國(guó)家查看:
private static void printLocal() {
Locale[] localeList = Locale.getAvailableLocales();
for (int i = 0; i < localeList.length; i++) {
System.out.println(localeList[i].getDisplayCountry() + ": " + localeList[i].getCountry());
System.out.println(localeList[i].getDisplayLanguage() + ": " + localeList[i].getLanguage());
}
}
- 建立默認(rèn)語(yǔ)言的properties文件:自定義名.properties
比如:errors.properties
當(dāng)所需語(yǔ)言的properties文件不存在的時(shí)候就會(huì)默認(rèn)讀取這個(gè)文件中的內(nèi)容
注意,資源文件都必須是ISO-8859-1編碼,對(duì)于中文等非西方語(yǔ)系,可通過(guò)JDK自帶的工具native2ascii進(jìn)行處理,在Eclipse中也可以安裝插件SimplePropertiesEditor來(lái)處理這類(lèi)文件。
- 使用
ResourceTranslator.java
package kyu.bundle;
import java.util.Locale;
import java.util.ResourceBundle;
public abstract class ResourceTranslator {
protected ResourceBundle bundle;
protected Locale lc;
protected static final String PROP_FILE = "kyu.errors";
public String translate(String id) {
return bundle.getString(id);
}
}
PropertyResourceTranslator.java
package kyu.bundle;
import java.util.Locale;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
public class PropertyResourceTranslator extends ResourceTranslator{
public PropertyResourceTranslator() {
lc = Locale.getDefault();
bundle = PropertyResourceBundle.getBundle(PROP_FILE, lc);
}
public PropertyResourceTranslator(String language, String country) {
lc = new Locale(language, country);
bundle = PropertyResourceBundle.getBundle(PROP_FILE, lc);
}
}
App.java
package kyu.test;
import kyu.bundle.ListResourceTranslator;
import kyu.bundle.PropertyResourceTranslator;
public class App {
public static void main(String[] args) {
testPropertyResource();
}
private static void testPropertyResource() {
PropertyResourceTranslator translatorDefault = new PropertyResourceTranslator();
PropertyResourceTranslator translatorZH = new PropertyResourceTranslator("zh", "CN");
PropertyResourceTranslator translatorEN = new PropertyResourceTranslator("en", "US");
String def = translatorDefault.translate("ERROR-001");
String zh = translatorZH.translate("ERROR-001");
String en = translatorEN.translate("ERROR-001");
System.out.println("test PropertyResourceBundle>>>>>>");
System.out.println("default: " + def);
System.out.println("zh: " + zh);
System.out.println("en: " + en);
}
}
.properties文件內(nèi)容:
Errors_en_Us.properties:
ERROR-001=error password
Errors.properties
ERROR-001=error password
Errors_zh_CN.properties
ERROR-001=密碼錯(cuò)誤
執(zhí)行App.java的測(cè)試結(jié)果:
test PropertyResourceBundle>>>>>>
default: 密碼錯(cuò)誤
zh: 密碼錯(cuò)誤
en: error password
可以看到,通過(guò)指定Local構(gòu)造函數(shù)的語(yǔ)言和國(guó)別代碼,就能自動(dòng)找到對(duì)應(yīng)的.properties,并匹配其中的內(nèi)容。
當(dāng)使用Locale.getDefault()時(shí),自動(dòng)檢測(cè)當(dāng)前的系統(tǒng)環(huán)境,從而選擇對(duì)應(yīng)的語(yǔ)言。
還有一點(diǎn)要注意的是:
PropertyResourceBundle.getBundle(PROP_FILE, lc);
其中PROP_FILE,為properties文件的路徑,此路徑為properties文件的完整路徑,即 所在完整包名.自定義名稱(chēng)
ListResourceBundle
ListResourceBundle的使用與PropertyResourceBundle的使用大同小異,不過(guò)是將properties文件換成了.java文件
ListResourceTranslator.java
package kyu.bundle;
import java.util.ListResourceBundle;
import java.util.Locale;
public class ListResourceTranslator extends ResourceTranslator{
public ListResourceTranslator() {
lc = Locale.getDefault();
bundle = ListResourceBundle.getBundle(PROP_FILE, lc);
}
public ListResourceTranslator(String language, String country) {
lc = new Locale(language, country);
bundle = ListResourceBundle.getBundle(PROP_FILE, lc);
}
}
ERRORS_en_US.java
package kyu;
import java.util.ListResourceBundle;
public class ERRORS_en_US extends ListResourceBundle{
static final Object[][] contents = new String[][] {
{ "ERROR-001", "error password" }
};
public Object[][] getContents() {
return contents;
}
}
ERRORS_zh_CN.java
package kyu;
import java.util.ListResourceBundle;
public class ERRORS_zh_CN extends ListResourceBundle {
static final Object[][] contents = new String[][] {
{ "ERROR-001", "密碼錯(cuò)誤" }
};
public Object[][] getContents() {
return contents;
}
}
繼承了ListResourceBundle的類(lèi)就相當(dāng)于前面的properties文件,需要提供一個(gè)getContents()方法,返回對(duì)應(yīng)的鍵值對(duì)。
同樣的,要注意ListResourceBundle子類(lèi)的命名規(guī)則,與properties文件相同,路徑也與properties文件相同。
通過(guò)App.java的測(cè)試(將對(duì)應(yīng)的bundle替換),可以得到相同的測(cè)試結(jié)果。
使用Eclipse對(duì)java文件進(jìn)行國(guó)際化
在需要國(guó)際化的類(lèi)文件上點(diǎn)擊右鍵->Source->Externalize Strings...
出現(xiàn)窗口,Eclipse會(huì)自動(dòng)檢測(cè)類(lèi)文件中的字符串,在窗口中可以選擇相應(yīng)的字符串,最后自動(dòng)生成類(lèi)似于上面的PropertyResourceTranslator.java和properties文件,完成國(guó)際化。
其原理與以上所講的相同,故不再詳細(xì)說(shuō)明。
Eclipse RCP國(guó)際化
最近在使用Eclipse RCP這項(xiàng)技術(shù)開(kāi)發(fā)程序,其中也有國(guó)際化相關(guān)的東西,總結(jié)下來(lái)。
Eclipse RCP and Plugin Internationalization - Tutorial
上面這篇文章詳細(xì)的說(shuō)明了Eclipse RCP工程中的國(guó)際化問(wèn)題,可以作為一個(gè)備忘錄。下面介紹一下eclipse rcp中比較常用到的國(guó)際化方式:
plugin.xml文件國(guó)際化
plugin.xml文件中保存了擴(kuò)展點(diǎn)等相關(guān)的信息,當(dāng)擴(kuò)展點(diǎn)與界面UI相關(guān)時(shí),就需要用到國(guó)際化
在工程的根目錄下面建立一個(gè)plugin.properties資源文件,此文件類(lèi)似于我們上面提到的errors.properties。當(dāng)然,也可以建立plugin_zh.properties等文件,這些文件名中的plugin是可以自由定義的。
-
在 MANIFEST.MF文件中增加代碼行:Bundle-Localization: plugin
注意,這個(gè)plugin與上面的properties文件名保持一致。
plugin.xml配置文件對(duì)資源文件進(jìn)行引用時(shí), 在引用的key前面加一個(gè)%,比如:
<view
id="org.jkiss.dbeaver.core.databaseNavigator"
category="org.jkiss.dbeaver.core.category"
class="org.jkiss.dbeaver.ui.navigator.database.DatabaseNavigatorView"
allowMultiple="false"
icon="icons/databases.png"
name="%view.database.navigator.title"/>
<view
類(lèi)文件國(guó)際化
與前面所介紹的java類(lèi)文件國(guó)際化相同,也可以通過(guò)選擇類(lèi)文件點(diǎn)擊右鍵->Source->Externalize Strings...
Eclipse IDE會(huì)自動(dòng)幫你完成國(guó)際化的一些工作,同樣也生成了相關(guān)的類(lèi)和properties文件,但不同的是,生成的類(lèi)文件內(nèi)容類(lèi)似于:
package test;
import org.eclipse.osgi.util.NLS;
public class Messages extends NLS {
private static final String BUNDLE_NAME
= "test.messages"; //$NON-NLS-1$
public static String View_0;
public static String View_1;
static {
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
}
private Messages() {
}
}
當(dāng)然,我們也可以手動(dòng)建立這些文件進(jìn)行國(guó)際化操作~不再詳細(xì)說(shuō)明,可以通過(guò)觀察IDE的行為進(jìn)行我們手動(dòng)的國(guó)際化操作