本文尝试用一个简单的例子来演示在书写Java应用程序时候,怎样使之符合国际化标准,然后对其进行本地化有多么简单。
当一个软件产品需要在全球范围应用的时候,得考虑在不同的地域和语言环境下面的使用情况,最简单的要求就是UI上的信息上能用本地化语言来显示,当然一个优秀的全球化软件产品关于国际化和本地化的要求远远不止于此,本文只是涉及了国际化和本地化的关于界面显示语言的一小部分。Java语言内核基于Unicode2.1提供了对不同国家和不同语言文字的内部支持,由于先天的原因,Java对于国际化的支持远远要比C/C++来的优越。
在开始具体介绍之前,需要先介绍几个术语:
i18n: 就是internationalization, 国际化,由于首字母"i"和末尾字母"n"间有18个字符,所以简称i18n. internationalization指为了使应用程序能适应不同的语言和地区间的变化而不作系统性的变化所采取的设计措施。
l10n: 就是localization, 本地化,由于首字母"l"和末尾字母"n"间有10个字母,所以简称l10n. localization指为了使应用软件能够在某一特定语言环境或地区使用而加入本地非凡化部件和翻译后文本的过程。
locale: 简单来说是指语言和区域进行非凡组合的一个标志。
我们的例子,显示一个有一个按钮和一个菜单的Dialog窗,在不改动程序的前提下使应用程能够显示英文文字的或者中文文字的界面。 注:因为仅仅作为演示用,我们的菜单栏也作为一个部件加入对话框,好象是一个Button一样,而不是通常意义上的菜单条。
通常我们的程序是这样的:
/**
* File name: i18nDemo.java
* Author ID: Jack, at http://bbs.whnet.edu.cn, Java discuss board.
* Description: Shows a Dialog with a "OK" button and "File"/"Exit" menu.
*/
import javax.swing.*;
import java.awt.*;
import java.util.*;
public class i18nDemo {
public static void main(String args[]) throws Exception{
JDialog dialog=new JDialog();
JButton BTOK=new JButton();
JMenuBar menuBar=new JMenuBar();
JMenu menuFile=new JMenu();
JMenuItem menuExit=new JMenuItem();
btOK.setText("OK");
menuFile.setText("File");
menuExit.setText("Exit");
dialog.setTitle("i18n Demo");
menuBar.add(menuFile);
menuFile.add(menuExit);
dialog.getContentPane().setLayout(new FlowLayout());
dialog.getContentPane().add(btOK);
dialog.getContentPane().add(menuBar);
dialog.setSize(200,100);
dialog.setModal(true);
dialog.show();
System.exit(0);
}
}
我们通过修改程序来达到i18n的要求:将那些和界面显示有关系的资源单独提取出来到资源文件里面.Java里面的资源文件叫做ResourceBundle,它分成两种,一种是ListResourceBundle,另一种是PropertyResourceBundle,我们这里使用ListResourceBundle,关于PropertyREsourceBundle请参阅文后的推荐阅读。当一个程序需要一些Locale相关的资源,例如字符串资源的时候,它可以从resource bundle里面将需要的本地化资源装入。
需要注重的是:为了能够正确显示中文字符,程序里的部件需要选择指定字体,例如在显示中文的时候使用"MS Song",不然界面有中文字符的时候会出现没有意义的方框。
请看修改过的程序和资源文件。
/**
* File name: i18nDemo.java
* Author: Jack, at http://bbs.whnet.edu.cn, Java discuss board.
* Email: greatjava@sina.com
* Description: Shows a Dialog with a "OK" button and "File"/"Exit" menu.
* This program made some modifications to fit the requestion of i18n
*/
import javax.swing.*;
import java.awt.*;
import java.util.*;
public class i18nDemo {
public static void main(String args[]) throws Exception{
ResourceBundle res;
if (args.length<1) {
//use current locale at machine to get the resource bundle.
res = ResourceBundle.getBundle("Res");
}else {
res = ResourceBundle.getBundle("Res",new Locale(args[0], args[1]));
}
JDialog dialog=new JDialog();
JButton btOK=new JButton();
JMenuBar menuBar=new JMenuBar();
JMenu menuFile=new JMenu();
JMenuItem menuExit=new JMenuItem();
Font font = new Font(res.getString("FontName"),Font.PLAIN,12);
btOK.setText(res.getString("OKText"));
menuFile.setText(res.getString("FileMenuText"));
menuExit.setText(res.getString("FileExitMenuText"));
dialog.setTitle(res.getString("DialogTitle"));
btOK.setFont(font);
menuFile.setFont(font);
menuExit.setFont(font);
menuBar.add(menuFile);
menuFile.add(menuExit);
dialog.getContentPane().setLayout(new FlowLayout());
dialog.getContentPane().add(btOK);
dialog.getContentPane().add(menuBar);
dialog.setSize(200,100);
dialog.setModal(true);
dialog.show();
System.exit(0);
}
}
/**
* File name: Res_en_US.java
* Author: Jack, at http://bbs.whnet.edu.cn, Java discuss board.
* Email: greatjava@sina.com
* Description: Resource file for i18nDemo.java
*/
import java.util.*;
public class Res_en_US extends java.util.ListResourceBundle {
static final Object[][] contents = new String[][]{
{ "OKText", "OK" },
{ "FontName", "Dialoginput" },
{ "FileMenuText", "File"},
{ "FileExitMenuText", "Exit"},
{ "DialogTitle", "Demo Dialog" }};
public Object[][] getContents() {
return contents;
}
}
在运行前,我们再做一个包含中文资源的资源文件
/**
* File name: Res_zh_CN.java
* Author: Jack, at http://bbs.whnet.edu.cn, Java discuss board.
* Email: greatjava@sina.com
* Description: Resource file for i18nDemo.java
*/
import java.util.*;
public class Res_zh_CN extends java.util.ListResourceBundle {
static final Object[][] contents = new String[][]{
{ "OKText", "确定" },
{ "FontName", "MS Song" },
{ "FileMenuText", "文件"},
{ "FileExitMenuText", "退出"},
{ "DialogTitle", "演示对话框" }};
public Object[][] getContents() {
return contents;
}
}
先运行来看看结果:
//Run next command step by step
javac *.java
java i18nDemo
java i18nDemo zh CN
java i18nDemo en US
可以看到出现了中文界面和英文界面的对话框。
具体的看一下程序:
主程序i18nDemo.java,多了一个ResourceBundle对象,它包含了一个资源文件的信息。然后需要使用本地化资源的时候,都通过res.getString(KEY)来得到相应的Locale的值。通过命令行,我们传入关于语言和国家的代码,这样在生成ResourceBundle对象的时候,可以指向相应的资源文件。假如没有指定Locale,那么在生成ResourceBundle使用的Locale是当前机器上缺省的区域和语言。在我的机器上(English WindowsNT 4),打开Richwin中文平台的时候,缺省的locale是中国,关闭RichWin的时候,Locale是U.S..
资源文件Res_en_US.java里面包含了英文的界面资源,文件名里的"en"指英语语言,"US"指国家是美国。Res_zh_CN.java是中文的资源文件,”zh“说明语言是中文,"CN"说明国家是中国。关于语言和国家的完整对照表可以在参考资源里找到链接。
Res_xx_XX类是从ListResourceBundle继续而