Java用户界面本地化实例讲解.docx
《Java用户界面本地化实例讲解.docx》由会员分享,可在线阅读,更多相关《Java用户界面本地化实例讲解.docx(14页珍藏版)》请在冰豆网上搜索。
Java用户界面本地化实例讲解
Java用户界面本地化实例讲解
2005-10-28文章出处:
赛迪网技术论坛
国际化是使程序具有足够的灵活性、能在世界上任何地区运行的过程。
国际化所要求的必然结果是地方化――使一个程序能够运行在特定地区的过程。
本文尝试用一个简单的例子来演示Java用户界面本地化。
Java语言内核基于Unicode3.0(Java1.4)提供了对不同国家和不同语言文字的内部支持,由于先天的原因,Java对于国际化的支持远远要比C/C++来的优越。
在我看来本地化必须满足以下的三个条件:
1、程序必须能读、写和操作本地化的文本。
2、程序在显示日期和时间、使数字格式化以及排序子串时,必须符合地方习惯。
(通过java.text包里面的类可以实现这些要求)
3、所有用户可见的文本都能在运行时获得,而不是直接写入程序中。
(通过java.util包里的ResourceBundle类和他的子类可以实现这些要求。
)
实现这三个方面可以真正实现程序的国际化。
首先让我们来了解一下地区。
地区代表一个地理上、政治上或文化上的区域。
在Java中,地区由java.util.Locale类表示。
地区常常以一种语言来定义,该语言则由其标准的小写双字母代码表示。
(例如:
en代表英国,fr代表法国,zh代表中国),但有时候语言是不能代表一个地区的,那就要在语言后面再加上一个国家或该国家的地域(例如:
en_US代表美国,zh_TW)。
Locale类保存着一个静态的默认地区,它可以用Locale.setDefault()和Locale.getDefault()来设置和查询。
一个程序可以生成和使用任意数目的非默认Locale对象。
让我们再来看一下Unicode字符编码。
Java使用Unicode的字符编码,其本身就是迈向国际化的一大步。
Unicode编码其每个字符都占两个字节。
用\u****的形式表示。
Unicode的字符可以等价于其他编码的字符(例如:
从\u0020到\u007E的字符等价于ASCII和ISO8859-1字符的0x20到0x7E)。
本文主要是对用户界面地方化,由于我使用的是资源束!
所以有必要对资源束作一下解释。
为定义一束地方化的资源,你需要生成一个ResourceBundle(资源束)的子类并且提供handleGetObject()和getKeys()方法的定义。
为了在程序中使用来自ResourceBundle的地方化资源,就需要先调用静态的getBundle()方法,用getBundle()获得一个ResourceBundle对象,然后再用getObject()方法去按照名字来查找资源。
当然也可以使用getString()简单的把getObject()的返回值分配给一个String对象。
GetBundle()方法采用basename_language_country_variait----没找到的话->basename_language_country----没找到的话->basename_language----没找到的话->basename(默认资源文件)的算法寻找合适的资源。
如果以上都没找到的话,则会抛出一个MissingResourceException异常。
现在我们来看一个简单的例子,如何使Java程序用户界面地方化的。
首先我们的程序需要查找特定Locale对象关联的资源包,所以应该定义一个Local对象,来获取本地默认的地区!
然后可以调用ResourceBundle的getBundle方法,并将locale对象作为参数传入。
清单一:
Localelocale=Locale.getDefault();//获取地区:
默认
//获取资源束。
如未发现则会抛出MissingResourceException异常
ResourceBundlebundle=ResourceBundle.getBundle("Properties.Dorian",locale);
清单一中的”Properties.Dorian”代表Properties包下以Dorian命名的默认资源文件。
这样就可以使用资源文件了!
让我们来看看资源文件是如何定义的。
清单二:
#Dorian.properties是默认的"Dorian"资源束文件。
#作为中国人,我用自己的地区作为默认
Title=\u4e2d\u56fd;
red.label=\u7ea2\u8272;
green.label=\u7eff\u8272;
blue.label=\u84dd\u8272;
清单三:
#文件Dorian_en_US.properties,是美国地区的资源束
#它覆盖了默认资源束
Title=America;
red.label=Red;
green.label=Green;
blue.label=Blue;
清单一和二定义了一个默认资源文件,和美国地区的资源文件。
其中等号左边的字符串表示主键,它们是唯一的。
为了获得主键对应的值,你可以调用ResourceBundle类的getString方法,并将主键作为参数。
此外,文件中以“#”号开头的行表示注释行。
需要注意的是清单二中的“\u4e2d\u56fd”,它是字符“中国”的Unicode字符码。
是使用Java自带的native2ascii工具转换的(native2asciiin.propertiesout.properties),这是为了不在程序界面中产生乱码。
清单四:
cmdRed.setText(bundle.getString("red.label"));
cmdBlue.setText(bundle.getString("blue.label"));
cmdGreen.setText(bundle.getString("green.label"));
清单二中的cmdRed、cmdBlue、cmdGreen为按钮。
bundle.getString("red.label")为得到资源文件中主键是red.label的值。
好了到此为止Java程序用户界面的本地化就是这么简单。
不过,要提醒你的是在为用户界面事件编写事件监听器代码时,要格外小心。
请看下面这段代码。
清单五:
publicclassMyAppletextendsJappletimplementsActionListener{
publicvoidinit(){
JButtoncancelButton=newJButton(“Cancel”);
CancelButton.addActionListener(this);
...
}
publicvoidactionPerformed(ActionEvente){
Strings=e.getActionCommand();
if(arg.equals(“Cancel”);
doCancel();
else……
}
}
如果你对清单五的代码不进行本地化,她就可能会运行的很好。
但当你的按钮被本地化为中文时,“Cancel”变为了“取消”。
这时就会出现你不愿意看到的问题。
下面有三个方法可以消除这个潜在的问题!
1>使用内部类而不使用独立的actionPerformed程序。
2>使用引号而不使用标签来标识组件。
3>使用name属性来标识组件
本例稍后的代码就是采用第一种方法来消除这个问题的。
清单六:
完整的代码
//:
MyNative.java
/**
Copyright(c)2003Dorian.Allrightsreserved
@(#)MyNative.java2003-12-21
@authorDorian
@version1.0.0
visithttp:
//www.D
*/
importjava.awt.*;
importjava.awt.event.*;
importjavax.swing.*;
importjava.util.*;
/**
这是一个将Java程序界面地方化的例子本例采用读取属性文件来达到目的
@seejava.util.Locale;
@seejava.util.ResourceBundle;
@seejava.util.MissingResourceException;
*/
publicclassMyNative{
publicstaticvoidmain(String[]args){
JFrameframe=newMyNativeFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setVisible(true);//Popthewindowup.
}
}
classMyNativeFrameextendsJFrame{
publicMyNativeFrame(){
Localelocale=Locale.getDefault();//获取地区:
默认
//获取资源束。
如未发现则会抛出MissingResourceException异常
//"Properties.Dorian"为在Properties下以Dorian为文件名的默认属性文件
ResourceBundlebundle=ResourceBundle.getBundle("Properties.Dorian",locale);
setTitle(bundle.getString("Title"));//通过getString()的返回值来设置Title
setSize(WIDTH,HEIGHT);//Setthewindowsize.
panel=newMyNativePanel();
ContainercontentPane=getContentPane();
contentPane.add(panel);
//通过获取资源束中*.label的值对三个按钮设置其Label
panel.setCmdRed(bundle.getString("red.label"));
panel.setCmdBlue(bundle.getString("blue.label"));
panel.setCmdGreen(bundle.getString("green.label"));
}
privateMyNativePanelpanel;
privatestaticfinalintWIDTH=400;
privatestaticfinalintHEIGHT=100;
}
classMyNativePanelextendsJPanel{
publicMyNativePanel(){
layout=newBorderLayout();
setLayout(layout);
txt=newJTextField(50);
add(txt,layout.CENTER);
cmdRed=newJButton();
cmdBlue=newJButton();
cmdGreen=newJButton();
panel.add(cmdRed);
panel.add(cmdBlue);
panel.add(cmdGreen);
add(panel,layout.SOUTH);
cmdRed.addActionListener(newActionListener(){
publicvoidactionPerformed(ActionEvente){
Strings=e.getActionCommand();
txt.setBackground(Color.red);
txt.setText(s);
}
});
cmdBlue.addActionListener(newActionListener(){
publicvoidactionPerformed(ActionEvente){
Strings=e.getActionCommand();
txt.setBackground(Color.blue);
txt.setText(s);
}
});
cmdGreen.addActionListener(newActionListener(){
publicvoidactionPerformed(ActionEvente){
Strings=e.getActionCommand();
txt.setBackground(Color.green);
txt.setText(s);
}
});
}
publicvoidsetCmdRed(Strings){
cmdRed.setText(s);
}
publicvoidsetCmdBlue(Strings){
cmdBlue.setText(s);
}
publicvoidsetCmdGreen(Strings){
cmdGreen.setText(s);
}
JPanelpanel=newJPanel();
BorderLayoutlayout;
privateJTextFieldtxt;
privateJButtoncmdRed,cmdBlue,cmdGreen;
}
//~
资源文件:
#Dorian.properties是默认的"Dorian"资源束文件。
#作为中国人,我用自己的地区作为默认
Title=\u4e2d\u56fd
red.label=\u7ea2\u8272
green.label=\u7eff\u8272
blue.label=\u84dd\u8272
#文件Dorian_en_US.properties,是美国地区的资源束
#它覆盖了默认资源束
Title=America
red.label=Red
green.label=Green
blue.label=Blue
#文件Dorian_zh_CN.properties,是中国大陆地区的资源束
#这个文件没有任何资源定义,从默认中国资源束继承