论坛首页 Java企业应用论坛

Java内置的国际化

浏览 1810 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2014-01-03  
Java内置的国际化
Struts2的国际化也不是无本之木,它依赖于Java内置的国际化机制,只是在Java内置的国际化机制的基础上增加了跟Struts2其他组件的融合,使得其他组件也可以非常方便的使用国际化。
9.2.1 Java内置的国际化入门
1:准备国际化信息文件
Java内置的国际化,以java.util.ResourceBundle和java.util.Locale两个类为中心。其中, java.util.Locale负责选择合适的语言,而java.util.ResourceBundle负责根据注入的java.util.Locale对象来选择国际化信息的来源,返回国际化信息。
       如果我们的软件支持中文和英文两种语言,而以中文作为默认的语言。则会出现三种语言,默认的语言(中文)、中文和英文,当然,其实只有两种语言中文和英文。但是,以中文为默认的语言是非常必要的。有时候,软件需要应对的语言不一定只有中文和英文;如果法国的朋友想要使用软件呢?由于不存在法文的信息,这时候只能返回默认的语言,那就是中文了。
       在这种情况下准备国际化资源文件,一般准备三个文件,分别是默认语言、中文与英文的文件。
       每个文件都以properties为扩展名,内容以key-value对的形式存在,其中key是如何引用这条信息,而value就是这条信息真正要显示的内容了。
       综上所述,可以准备如下三个文件作为国际化信息的文件。
(1)默认语言文件:message.properties

java代码:
查看复制到剪贴板打印
labela = labela in zh_CN 
labelb = labelb in zh_CN 
注意:在这个文件中,本应该在“=”后面写上中文,但是,我们没有这样做,这是因为Java内置的国际化在处理中文的时候还需要一步特殊处理,这在后面有专门的章节处理,因此这里就没有使用中文了。
(2)中文语言文件:message_zh_CN.properties

java代码:
查看复制到剪贴板打印
#labela = labela in zh_CN 
#labelb = labelb in zh_CN 
注意:故意在两行之前都加了一个#,这在properties文件中代表注释的意思,也就是说这个message_zh_CN.properties实际上是空的。
(3)英文语言文件:message_en_US.properties

java代码:
查看复制到剪贴板打印
labela = labela in en_US 
labelb = labelb in en_US 
先不去考虑客户端怎么写,观察一下这三个文件的命名。它们拥有共通的前缀message,代表了它们是同一组国际化信息的不同语言;它们各自的后缀代表了自己的语言,其中没有后缀(message.properties)的文件,代表这是默认语言文件。
2:使用ResouceBundler和Locale选择多语言信息
       将上面的三个文件拷贝到工程的src目录下备用。然后就可以在Java程序中引用这些多语言信息了。
       在引用多语言信息的时候,要做三件事情:
引用哪种语言。
引用哪组多语言文件。
引用这种语言的这组文件里的哪条信息。
带着这三个问题,一起来看一下Java中的客户端:

java代码:
查看复制到剪贴板打印
package cn.javass.i18n; 
 
import java.util.Locale; 
import java.util.ResourceBundle; 
 
public class Test { 
    public static void main(String[] args) {         
        //选择中文 
        Locale locale1 = Locale.SIMPLIFIED_CHINESE; 
        //选择message这组文件 
        ResourceBundle bundle1 = ResourceBundle.getBundle("message",locale1); 
        //选择其中的labela这一项 
        System.out.println("bundle1=="+bundle1.getString("labela")); 
         
        Locale locale2 = Locale.US; 
        ResourceBundle bundle2 = ResourceBundle.getBundle("message",locale2); 
        System.out.println("bundle2=="+bundle2.getString("labela")); 
         
        Locale locale3 = Locale.FRANCE; 
        ResourceBundle bundle3 = ResourceBundle.getBundle("message",locale3); 
        System.out.println("bundle3=="+bundle3.getString("labela")); 
    } 

Locale类里预置了许多语种,上面代码中引用的Locale.SIMPLIFIED_CHINESE对应zh_CN,Locale.US对应en_US,Locale.FRANCE对应fr_FR;也就确定了前面所说的文件名后缀。
       ResouceBundle.getBundle方法传入的第一个参数就是要引用哪组文件,也就确定了前面所说的文件名前缀。
       由前缀和后缀共同作用取得的ResourceBundle对象就代表了一个文件中的所有多语言信息,它的getString方法传入的参数就是前面所说的key,而且返回值就是实际需要的value。
       运行测试一下,结果如下:

java代码:
查看复制到剪贴板打印
bundle1==labela in zh_CN 
bundle2==labela in en_US 
bundle3==labela in zh_CN 
9.2.2对中文的支持
在上一节中并没有在message.properties中写中文。现在,试着写一下中文,把“labela in zh_CN”改成“labela in 中文”,发现eclipse根本保存不了,eclipse会报错,这是因为properties文件只支持ascii码,而中文使用了Unicode,这该怎么办呢?
       方法特别简单,找个工具把中文转换成ascii码就可以了,比如native2ascii的工具,它可以在jdk安装路径下的bin目录中找到。
       使用native2ascii的基本步骤如下:
1、要先把message.proerties改个名字,比如为src_message.properties,因为message.properties这个文件要用来存储操作后的内容。
2、用文本编辑器来编辑src_message.properties,加入中文。
java代码:
查看复制到剪贴板打印
labela = labela in 中文 
labelb = labelb in 中文 
3、在cmd窗口中找到工程的src文件夹,运行如下命令。

java代码:
查看复制到剪贴板打印
native2ascii src_message.properties message.properties 
然后在eclipse中刷新一下工程,会发现多出了message.properties,里面的内容为

java代码:
查看复制到剪贴板打印
labela = labela in \u4e2d\u6587 
labelb = labelb in \u4e2d\u6587 
这就是转换后的中文。
再次运行上一节的java客户端,我们可以发现,中文已经能正确显示了。

java代码:
查看复制到剪贴板打印
bundle1==labela in 中文 
bundle2==labela in en_US 
bundle3==labela in 中文 
提示:为了保证知识的紧凑,这里只是用了最原始的方法调用了native2ascii,在真正的项目中会有更好的方法去调用,比如写ant脚本、使用eclipse插件等等。
9.2.3向国际化信息传入参数
在实际项目中,只是在国际化信息文件中写死一个字符串还并不能满足要求。比如,用户可能会对已经确定的订单进行修改操作,但是这时候商品已经出库,所以订单就不允许修改了。
这种情况下,通常需要提示用户:“您的订单已处理,商品已出库,不允许修改”。可是,一个用户有可能有多张订单,这样一句简单的提示会让用户迷惑,到底哪张订单不允许修改啊?
如果写出更友好的提示,比如:“您的订单(201009290001)已处理,商品已出库,不允许修改”,这就明确了很多。
       该怎么实现这种功能呢?
这时候,光用前面学的国际化知识就不够了。前面在国际化文件中写的文本都是死的,但是,订单号显然不能在文本中写死,因为任何一张订单都有可能不允许修改。对于这种情况,可以把订单编号作为参数传入国际化信息内。
       要向国际化信息传入参数,需要考虑两方面事情:
在编写国际化信息时,如何给参数留出位置?
在客户端访问国际化信息时,如何把参数传入预定的位置?
在国际化信息中,是使用索引的方式来进行占位。可以将默认语言的国际化信息修改一下,为了简单,避免去转换中文,就用英文来示例了,示例如下:

java代码:
查看复制到剪贴板打印
labela = your order({0}) is confirmed,can not be modified 
在客户端中,需要使用MessageFormat类将参数合成进读出的国际化信息中,示例如下:

java代码:
查看复制到剪贴板打印
public class Test { 
    public static void main(String[] args) {         
        //选择中文 
        Locale locale1 = Locale.SIMPLIFIED_CHINESE; 
        //选择message这组文件 
        ResourceBundle bundle1 = ResourceBundle.getBundle("message",locale1); 
        //选择其中的labela这一项 
        String message = bundle1.getString("labela"); 
        //将参数合成进读出的国际化信息 
        String info = MessageFormat.format(message, "201009290001"); 
        System.out.println(info); 
    } 

运行的结果为:

java代码:
查看复制到剪贴板打印
your order(201009290001) is confirmed,can not be modified 
有朋友可能会说,那怎么传入多个参数呢?比如把国际化的信息修改成如下示例:

java代码:
查看复制到剪贴板打印
labela ={0},your order({1}) is confirmed,can not be modified 
那么在程序里面,只要把传入的参数改成数组就可以了,示例如下:

java代码:
查看复制到剪贴板打印
public class Test { 
    public static void main(String[] args) {         
        //选择中文 
        Locale locale1 = Locale.SIMPLIFIED_CHINESE; 
        //选择message这组文件 
        ResourceBundle bundle1 = ResourceBundle.getBundle("message",locale1); 
        //选择其中的labela这一项 
        String message = bundle1.getString("labela"); 
        //将参数合成进读出的国际化信息 
        String[] params = new String[2]; 
        params[0] = "Petter"; 
        params[1] = "201009290001"; 
        String info = MessageFormat.format(message, params); 
        System.out.println(info); 
    } 

运行的结果如下:

java代码:
查看复制到剪贴板打印
Petter,your order(201009290001) is confirmed,can not be modified 
9.2.4小结
本节中介绍的都是Java内置的国际化信息的使用,而Struts2的国际化,是在Java内置的国际化支持的基础上对其包装使用,因此,以上的特性在Struts2中都得到了体现,也就是说在这节中学到的知识,到Struts2中仍然有用。
私塾在线原创
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics