8.1 国际化实现原理
8.1.1 资源文件命名规则
前面几章曾介绍过校验提示信息国际化、类型转换提示信息国际化和JSP页面国际化等。本章将详细介绍Struts 2的国际化。
Struts 2实现国际化非常简单,但是只知道如何实现国际化还不行,还必须了解国际化实现的原理。
首先来看实现国际化最重要的是什么,答案是国际化资源文件。那国际化资源文件中最重要的是什么呢?答案是资源文件的命名。
资源文件的命名规则是非常重要的,主要分3种形式。
❑ baseName.properties
❑ baseName_language.properties
❑ baseName_language_country.properties
baseName是资源文件的基本名称,由用户自由定义。但是language和country就必须为Java所支持的语言和国家/地区代码。
目前暂时只知道zh_CN代表中文简体,en_US代表美国英语,可以通过自己写程序来获得Java所支持的语言和国家/地区代码信息。
8.1.2 Java支持的国家与地区名
首先来看java.util.Local类,该类对应一个特定的国家/地区或语言。通过调用Locale类的getAvailableLocales()方法可以获得Java支持的所有的语言及国家。
通过调用locale实例的getDisplayCountry()方法以及getCountry()方法,可以分别获得国家/地区名以及国家/地区代码,代码如下所示。
public class ShowAllCountry { public static void main(String[] args) { //返回Java支持的所有的语言及国家的数组 Locale[] allLocale = Locale.getAvailableLocales(); System.out.println("国家/地区名" + " 国家/地区代码"); //循环遍历所有Locale for(Locale locale : allLocale) { //控制台打印国家或者地区名以及国家/地区代码 System.out.println(locale.getDisplayCountry() + " " + locale.getCountry()); } } }
程序运行结果,系统打印出Java所支持全部国家/地区名以及国家/地区代码。
国家/地区名 国家/地区代码 ... 阿拉伯联合酋长国 AE 巴林 BH 阿尔及利亚 DZ 埃及 EG 伊拉克 IQ 约旦 JO 科威特 KW 黎巴嫩 LB 利比亚 LY 摩洛哥 MA 阿曼 OM 卡塔尔 QA 沙特阿拉伯 SA 苏丹 SD 叙利亚 SY 突尼斯 TN 也门 YE 印度 IN ... ...
8.1.3 Java支持的语言
通过调用locale实例的getDisplayLanguage()方法以及getLanguage()方法,可以分别获得语言名称以及语言代码,如下所示。
import java.util.Locale; public class ShowAllLanguage { public static void main(String[] args) { //返回Java支持的所有语言及国家的数组 Locale[] allLocale = Locale.getAvailableLocales(); System.out.println("语言名" + " 语言代码"); //循环遍历所有Locale for(Locale locale : allLocale) { //控制台打印语言名称以语言代码 System.out.println(locale.getDisplayLanguage() + " " + locale.getLanguage()); } } }
程序运行结果,系统打印出Java所支持全部语言名称以及语言代码。
语言名 语言代码 阿拉伯文 ar 阿拉伯文 ar 阿拉伯文 ar ... ... 印地文 hi 希伯来文 iw 希伯来文 iw 日文 ja 日文 ja 朝鲜文 ko 朝鲜文 ko 泰文 th 泰文 th 泰文 th 越南文 vi 越南文 vi 中文 zh 中文 zh 中文 zh 中文 zh 白俄罗斯文 be 白俄罗斯文 be 保加利亚文 bg 保加利亚文 bg 加泰罗尼亚文 ca 加泰罗尼亚文 ca 捷克文 cs 捷克文 cs ... ...
结合前面两个程序,可以获得Java支持的所有国家/地区名以及国家/地区代码、语言名称以语言代码,如下所示。
import java.util.Locale; public class ShowAllCountryAndLanguage { public static void main(String[] args) { //返回Java支持的所有的语言及国家的数组 Locale[] allLocale = Locale.getAvailableLocales(); System.out.println("国家/地区名" + " 国家/地区代码" + " 语言名" + " 语言代码"); // 循环遍历所有的Locale for (Locale locale : allLocale) { //控制台打印国家或者地区名以及国家/地区代码,语言名称以语言代码 System.out.println(locale.getDisplayCountry() + " " + locale.getCountry() + " " + locale.getDisplayLanguage() + " " + locale.getLanguage()); } } }
程序运行结果,打印出所有国家/地区名以及国家/地区代码、语言名称以语言代码。
国家/地区名 国家/地区代码 语言名 语言代码 阿拉伯联合酋长国 AE 阿拉伯文 ar 巴林 BH 阿拉伯文 ar 阿尔及利亚 DZ 阿拉伯文 ar 埃及 EG 阿拉伯文 ar 伊拉克 IQ 阿拉伯文 ar 约旦 JO 阿拉伯文 ar 科威特 KW 阿拉伯文 ar 黎巴嫩 LB 阿拉伯文 ar 利比亚 LY 阿拉伯文 ar 摩洛哥 MA 阿拉伯文 ar 阿曼 OM 阿拉伯文 ar 卡塔尔 QA 阿拉伯文 ar ... ... 中国 CN 中文 zh 香港 HK 中文 zh 台湾地区 TW 中文 zh ... 美国 US 英文 en
通过如上方式获得了完整的Java所支持的语言和国家/地区代码信息,这时可以将这些信息好好地保存起来,以后用的时候就可以随时查看。
8.1.4 完成Java程序国际化
下面来看一个简单的Java程序示例,代码如下所示。
public class HelloBeiJing {
public static void main(String[] args) {
System.out.println("北京奥运欢迎你");
}
}
程序非常简单,其执行结果肯定是打印出“北京奥运欢迎你”。
下面来为该程序完成国际化,使得程序能够在不同的国家/语言环境下能够打印出不同欢迎信息。
下面给该程序提供简体中文和美国英语两种国际/语言环境国际化支持。首先需要给该程序提供两个国际化资源文件。
❑ 第一个资源文件:hello_zh_CN.properties。
message.welcome =北京奥运欢迎你
使用native2ascii命令来处理转换成Unicode编码。
message.welcome = \u5317\u4EAC\u5965\u8FD0\u6B22\u8FCE\u4F60
❑ 第二个资源文件:hello_en_US.properties。
message.welcome = Welcome come to beijing Olympic Games
将Java程序示例修改代码如下。
import java.util.Locale; import java.util.ResourceBundle; public class HelloBeiJing { public static void main(String[] args) { //设定国家/语言环境为美国英语 Locale locale = Locale.US; //根据locale加载资源文件 ResourceBundle rb = ResourceBundle.getBundle("hello", locale); //打印key为message.welcome对应的value值 System.out.println(rb.getString("message.welcome")); } }
程序首先设定国家/语言环境为美国英语,然后为ResourceBundle的getBundle()方法加载hello_en_US.properties资源文件。通过调用ResourceBundle实例的getString()方法将打印key为message.welcome对应的value值。
Welcome come to beijing Olympic Games
下面修改该程序,将国家/语言环境设置为中文简体,代码如下所示。
import java.util.Locale; import java.util.ResourceBundle; public class HelloBeiJing { public static void main(String[] args) { //设定国家/语言环境为中文简体 Locale locale = Locale.SIMPLIFIED_CHINESE; //根据locale加载资源文件 ResourceBundle rb = ResourceBundle.getBundle("hello", locale); //打印key为message.welcome对应的value值 System.out.println(rb.getString("message.welcome")); } }
因为设定国家/语言环境为中文简体,所以ResourceBundle的getBundle()方法将加载hello_zh_CN.properties资源文件。通过调用ResourceBundle实例的getString()方法将打印key为message. welcome对应的中文欢迎信息。
北京奥运欢迎你
这时发现了一个问题,程序虽然实现了国际化,但是需要设定国家/语言环境,这样还是比较麻烦。那下面来看如何根据系统语言环境加载相应的国际化资源文件,修改代码如下所示。
import java.util.Locale; import java.util.ResourceBundle; public class HelloBeiJing { public static void main(String[] args) { //取得系统当前默认的国家/语言环境 Locale locale = Locale.getDefault(); //根据locale加载资源文件 ResourceBundle rb = ResourceBundle.getBundle("hello", locale); //打印key为message.welcome对应的value值 System.out.println(rb.getString("message.welcome")); } }
程序运行打印出中文欢迎信息。
北京奥运欢迎你
只需更改系统语言环境,在控制面板中选择“区域和语言”选项,打开“区域和语言选项”对话框,如图8.1所示。将系统的语言环境设置成美国英语,这样就能输出英文的欢迎信息。
图8.1 “区域和语言选项”对话框
再次运行程序,打印出美国英语欢迎信息。
Welcome come to beijing Olympic Games
8.1.5 使用占位符
前面示例输出的消息都非常简单,如果输出的消息要包含动态的内容该如何实现呢?这时可以通过占位符来实现。
下面来看如何修改程序,使得程序能够输出欢迎信息加上欢迎对象的名字,比如“xiao qiang”这个名字。首先需要修改国际化资源文件,为其添加占位符。
❑ 第一个资源文件:hello_zh_CN.properties。
message.welcome =北京奥运欢迎你 {0}
使用native2ascii命令来处理转换成Unicode编码。
message.welcome = \u5317\u4EAC\u5965\u8FD0\u6B22\u8FCE\u4F60 {0}
❑ 第二个资源文件:hello_en_US.properties。
message.welcome = Welcome come to beijing Olympic Games {0}
修改程序,在程序中使用MessageFormat类中的format()静态方法格式化字符串。其中format()方法的第一个参数为需要格式化的字符串,后面的多个参数值(其实是可变参数)用来给占位符赋值,代码如下所示。
import java.text.MessageFormat;
import java.util.Locale; import java.util.ResourceBundle; public class HelloBeiJing2 { public static void main(String[] args) { //取得系统当前默认的国家/语言环境 Locale locale = Locale.getDefault(); //根据locale加载资源文件 ResourceBundle rb = ResourceBundle.getBundle("hello02", locale); //获得key为message.welcome对应的字符串信息 String welcomeMsg = rb.getString("message.welcome"); //打印格式化后的字符串 System.out.println(MessageFormat.format(welcomeMsg, "xiaoqiang")); } }
程序在简体中文语言环境下打印如下欢迎信息。
北京奥运欢迎你xiaoqiang
更改系统语言环境,将系统的语言环境设置成美国英语。程序打印如下欢迎信息。
Welcome come to beijing Olympic Games xiaoqiang
比起Java程序的国际化,Struts 2中的国际化要简单很多。在Struts 2中实现国际化都只是简单调用其提供的方法,而真正实现国际化的过程则交由Struts 2框架底层来实现。