《研磨struts2》第九章 国际化 之 9.2 Java内置的国际化

9.2  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代码:
  1. labela = labela in zh_CN  
  2. labelb = labelb in zh_CN  

注意:在这个文件中,本应该在“=”后面写上中文,但是,我们没有这样做,这是因为Java内置的国际化在处理中文的时候还需要一步特殊处理,这在后面有专门的章节处理,因此这里就没有使用中文了。

扫描二维码关注公众号,回复: 709454 查看本文章

(2)中文语言文件:message_zh_CN.properties

 

java代码:
  1. #labela = labela in zh_CN  
  2. #labelb = labelb in zh_CN  

注意:故意在两行之前都加了一个#,这在properties文件中代表注释的意思,也就是说这个message_zh_CN.properties实际上是空的。

(3)英文语言文件:message_en_US.properties

 

java代码:
  1. labela = labela in en_US  
  2. labelb = labelb in en_US  

先不去考虑客户端怎么写,观察一下这三个文件的命名。它们拥有共通的前缀message,代表了它们是同一组国际化信息的不同语言;它们各自的后缀代表了自己的语言,其中没有后缀(message.properties)的文件,代表这是默认语言文件。

2:使用ResouceBundler和Locale选择多语言信息

       将上面的三个文件拷贝到工程的src目录下备用。然后就可以在Java程序中引用这些多语言信息了。

       在引用多语言信息的时候,要做三件事情:

  • 引用哪种语言。
  • 引用哪组多语言文件。
  • 引用这种语言的这组文件里的哪条信息。

带着这三个问题,一起来看一下Java中的客户端:

 

java代码:
  1. package cn.javass.i18n;  
  2.   
  3. import java.util.Locale;  
  4. import java.util.ResourceBundle;  
  5.   
  6. public class Test {  
  7.     public static void main(String[] args) {          
  8.         //选择中文  
  9.         Locale locale1 = Locale.SIMPLIFIED_CHINESE;  
  10.         //选择message这组文件  
  11.         ResourceBundle bundle1 = ResourceBundle.getBundle("message",locale1);  
  12.         //选择其中的labela这一项  
  13.         System.out.println("bundle1=="+bundle1.getString("labela"));  
  14.           
  15.         Locale locale2 = Locale.US;  
  16.         ResourceBundle bundle2 = ResourceBundle.getBundle("message",locale2);  
  17.         System.out.println("bundle2=="+bundle2.getString("labela"));  
  18.           
  19.         Locale locale3 = Locale.FRANCE;  
  20.         ResourceBundle bundle3 = ResourceBundle.getBundle("message",locale3);  
  21.         System.out.println("bundle3=="+bundle3.getString("labela"));  
  22.     }  
  23. }  

Locale类里预置了许多语种,上面代码中引用的Locale.SIMPLIFIED_CHINESE对应zh_CN,Locale.US对应en_US,Locale.FRANCE对应fr_FR;也就确定了前面所说的文件名后缀。

       ResouceBundle.getBundle方法传入的第一个参数就是要引用哪组文件,也就确定了前面所说的文件名前缀。

       由前缀和后缀共同作用取得的ResourceBundle对象就代表了一个文件中的所有多语言信息,它的getString方法传入的参数就是前面所说的key,而且返回值就是实际需要的value。

       运行测试一下,结果如下:

 

java代码:
  1. bundle1==labela in zh_CN  
  2. bundle2==labela in en_US  
  3. 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代码:
  1. labela = labela in 中文  
  2. labelb = labelb in 中文  

3、在cmd窗口中找到工程的src文件夹,运行如下命令。

 

java代码:
  1. native2ascii src_message.properties message.properties  

然后在eclipse中刷新一下工程,会发现多出了message.properties,里面的内容为

 

java代码:
  1. labela = labela in \u4e2d\u6587  
  2. labelb = labelb in \u4e2d\u6587  

这就是转换后的中文。

再次运行上一节的java客户端,我们可以发现,中文已经能正确显示了。

 

java代码:
  1. bundle1==labela in 中文  
  2. bundle2==labela in en_US  
  3. bundle3==labela in 中文  

提示:为了保证知识的紧凑,这里只是用了最原始的方法调用了native2ascii,在真正的项目中会有更好的方法去调用,比如写ant脚本、使用eclipse插件等等。

9.2.3向国际化信息传入参数

在实际项目中,只是在国际化信息文件中写死一个字符串还并不能满足要求。比如,用户可能会对已经确定的订单进行修改操作,但是这时候商品已经出库,所以订单就不允许修改了。

这种情况下,通常需要提示用户:“您的订单已处理,商品已出库,不允许修改”。可是,一个用户有可能有多张订单,这样一句简单的提示会让用户迷惑,到底哪张订单不允许修改啊?

如果写出更友好的提示,比如:“您的订单(201009290001)已处理,商品已出库,不允许修改”,这就明确了很多。

       该怎么实现这种功能呢?

这时候,光用前面学的国际化知识就不够了。前面在国际化文件中写的文本都是死的,但是,订单号显然不能在文本中写死,因为任何一张订单都有可能不允许修改。对于这种情况,可以把订单编号作为参数传入国际化信息内。

       要向国际化信息传入参数,需要考虑两方面事情:

  • 在编写国际化信息时,如何给参数留出位置?
  • 在客户端访问国际化信息时,如何把参数传入预定的位置?

在国际化信息中,是使用索引的方式来进行占位。可以将默认语言的国际化信息修改一下,为了简单,避免去转换中文,就用英文来示例了,示例如下:

 

java代码:
  1. labela = your order({0}) is confirmed,can not be modified  

在客户端中,需要使用MessageFormat类将参数合成进读出的国际化信息中,示例如下:

 

java代码:
  1. public class Test {  
  2.     public static void main(String[] args) {          
  3.         //选择中文  
  4.         Locale locale1 = Locale.SIMPLIFIED_CHINESE;  
  5.         //选择message这组文件  
  6.         ResourceBundle bundle1 = ResourceBundle.getBundle("message",locale1);  
  7.         //选择其中的labela这一项  
  8.         String message = bundle1.getString("labela");  
  9.         //将参数合成进读出的国际化信息  
  10.         String info = MessageFormat.format(message, "201009290001");  
  11.         System.out.println(info);  
  12.     }  
  13. }  

运行的结果为:

 

java代码:
  1. your order(201009290001) is confirmed,can not be modified  

有朋友可能会说,那怎么传入多个参数呢?比如把国际化的信息修改成如下示例:

 

java代码:
  1. labela ={0},your order({1}) is confirmed,can not be modified  

那么在程序里面,只要把传入的参数改成数组就可以了,示例如下:

 

java代码:
  1. public class Test {  
  2.     public static void main(String[] args) {          
  3.         //选择中文  
  4.         Locale locale1 = Locale.SIMPLIFIED_CHINESE;  
  5.         //选择message这组文件  
  6.         ResourceBundle bundle1 = ResourceBundle.getBundle("message",locale1);  
  7.         //选择其中的labela这一项  
  8.         String message = bundle1.getString("labela");  
  9.         //将参数合成进读出的国际化信息  
  10.         String[] params = new String[2];  
  11.         params[0] = "Petter";  
  12.         params[1] = "201009290001";  
  13.         String info = MessageFormat.format(message, params);  
  14.         System.out.println(info);  
  15.     }  
  16. }  

运行的结果如下:

 

java代码:
  1. Petter,your order(201009290001) is confirmed,can not be modified  

9.2.4小结

本节中介绍的都是Java内置的国际化信息的使用,而Struts2的国际化,是在Java内置的国际化支持的基础上对其包装使用,因此,以上的特性在Struts2中都得到了体现,也就是说在这节中学到的知识,到Struts2中仍然有用。

 

私塾在线网站原创《研磨struts2》系列

转自请注明出处:【http://sishuok.com/forum/blogPost/list/0/4084.html

欢迎访问http://sishuok.com获取更多内容

猜你喜欢

转载自rubbing-struts2.iteye.com/blog/1525887