Java国际化

1. 基本概念

“国际化”也称为“本地化”,一般需要两个条件来确定,它们分别是“语言类型”和“国家/地区的类型”。如中文本地化既有中国大陆地区的中文,又有中国台湾、中国香港地区的中文,还有新加坡地区的中文。

Java通过 java.util.Locale 类表示一个本地化对象,它允许通过 语言参数国家/地区参数 创建一个确定的本地化对象。

语言参数使用ISO标准语言代码表示,这些代码是由ISO-639标准定义的,每一种语言由两个小写字母表示。下面的网址是提供了标准语言代码的信息:http://www.loc.gov/standards/iso639-2/php/English_list.php

ISO-639

国家/地区参数也由标准的ISO国家/地区代码表示,这些代码是由ISO-3166标准定义的,每个国家/地区由两个大写字母表示。下面网址查看ISO-3166的标准代码:https://www.iso.org/obp/ui/#search/code

ISO3166

2. Locale

java.util.Locale 是表示语言和国家/地区信息的本地化类,它是创建国际化应用的基础。下面给出几个创建本地化对象的示例:

//带有语言和国家(地区)信息的本地化对象
Locale zhcnLocale = new Locale("zh", "CN");

//只有语言信息的本地化对象
Locale zhLocale = new Locale("zh");

//等同于Locale("zh", "CN")
zhcnLocale = Locale.CHINA;

//等同于Locale("zh")
zhLocale = Locale.CHINESE;

//获取系统默认的本地化对象    
Locale locale = Locale.getDefault();

通过上述例子,可以看出创建本地化对象Locale的几种方式:
1. 同时指定 语言国家/地区 参数
2. 仅指定语言参数
3. Locale类的静态常量
4. 获取系统默认的本地化对象

如果希望改变系统默认的本地化设置,可以在启动JVM时通过命令参数指定:

java -Duser.language=en -Duser.region=US

3. 本地化工具类

JDK的java.util包中提供了几个支持本地化的格式化工具类:NumberFormat、DateFormat、MessageFormat,下面,我们分别通过实例了解它们的用法。

3.1 NumberFormat
Locale locale = new Locale("zh", "CN");
NumberFormat currencyFmt = NumberFormat.getCurrencyInstance(locale);
double currency = 12345.67;
System.out.println(currencyFmt.format(currency));

上述例子对金额进行格式化,输出的结果是:

¥12,345.67
3.2 DateFormat
Locale locale = new Locale("zh", "CN");
Date date = new Date();
DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, locale);
System.out.println(df.format(date));

通过DateFormat#getDateInstance(int style,Locale locale)方法按本地化的方式对日期进行格式化操作。该方法第一个入参为时间样式,第二个入参为本地化对象,输出的结果是:

2017-10-23
3.3 MessageFormat

MessageFormat在NumberFormat和DateFormat的基础上提供了强大的占位符字符串的格式化功能,它支持时间、货币、数字以及对象属性的格式化操作。

//信息格式化串    
String pattern1 = "{0},你好!你于 {1} 在工商银行存入 {2} 元。";  
String pattern2 = "At {1,time,short} On {1,date,long},{0} paid {2,number, currency}.";  

//用于动态替换占位符的参数    
Object[] params = {"John", new GregorianCalendar().getTime(), 1.0E3};  

//使用默认本地化对象格式化信息    
String msg1 = MessageFormat.format(pattern1, params);  

//使用指定的本地化对象格式化信息    
MessageFormat mf = new MessageFormat(pattern2, Locale.US);  
String msg2 = mf.format(params);  
System.out.println(msg1);  
System.out.println(msg2);

pattern1是简单形式的格式化信息串,通过{n}占位符指定动态参数的替换位置索引,{0}表示第一个参数,{1}表示第二个参数,以此类推。
  
pattern2格式化信息串比较复杂一些,除参数位置索引外,还指定了参数的类型和样式。从pattern2中可以看出格式化信息串的语法是很灵活的,一个参数甚至可以出现在两个地方。

如 {1,time,short}表示从第二个入参中获取时间部分的值,显示为短样式时间;而{1,date,long}表示从第二个入参中获取日期部分的值,显示为长样式时间。

运行上面的代码,输出以下信息:

John,你好!你于 17-10-23 下午9:26 在工商银行存入 1,000 元。
At 9:26 PM On October 23, 2017,John paid $1,000.00.

如果需要支持国际化功能,则必须为支持的不同本地化类型分别提供对应的资源文件,并以规范的方式进行命名。国际化资源文件的命名规范规定资源名称采用以下的方式进行命名:
  <资源名><语言代码><国家/地区代码>.properties

其中,语言代码国家/地区代码都是可选的。<资源名>.properties命名的国际化资源文件是默认的资源文件,即某个本地化类型在系统中找不到对应的资源文件,就采用这个默认的资源文件。

<资源名>_<语言代码>.properties命名的国际化资源文件是某一语言默认的资源文件,即某个本地化类型在系统中找不到精确匹配的资源文件,将采用相应语言默认的资源文件。

举一个例子:假设资源名为resource,则语言为英文,国家为美国,则与其对应的本地化资源文件命名为resource_en_US.properties。信息在资源文件以属性名/值的方式表示:

greeting.common=How are you!  
greeting.morning = Good morning!  
greeting.afternoon = Good Afternoon! 

对应语言为中文,国家/地区为中国大陆的本地化资源文件则命名为resource_zh_ CN.properties,资源文件内容如下:

greeting.common=\u60a8\u597d\uff01  
greeting.morning=\u65e9\u4e0a\u597d\uff01  
greeting.afternoon=\u4e0b\u5348\u597d\uff01 

本地化不同的同一资源文件,虽然属性值各不相同,但属性名却是相同的,这样应用程序就可以通过Locale对象和属性名精确调用到某个具体的属性值了。
  
读者可能已经注意到,上面中文的本地化资源文件内容采用了特殊的编码表示中文字符,这是因为资源文件对文件内容有严格的要求:只能包含ASCII字符。所以必须将非ASCII字符的内容转换为Unicode代码的表示方式。如上面中文的resource_zh_CN.properties资源文件的三个属性值分别是“您好!”、“早上好!”和“下午好!”三个中文字符串对应的Unicode代码串。

在IDEA中,为了直观显示该文件,可以通过以下方式设置来显示中文:
Preference->Editor->File Encoding->勾选 Transparent native-to-ascii conversion

greeting.common = 您好!
greeting.morning = 早上好!
greeting.afternoon = 下午好!

该功能使用的是JDK提供的工具native2ascii。

如果应用程序中拥有大量的本地化资源文件,直接通过传统的File操作资源文件显然不方便。Java为我们提供了用于加载本地化资源文件的方便类java.util.ResourceBoundle。

ResourceBoundle为加载及访问资源文件提供便捷的操作,下面的语句从相对于类路径的目录中加载一个名为resource的本地化资源文件:

ResourceBundle rb = ResourceBundle.getBundle("com/baobaotao/i18n/resource", locale);

可以通过如下方式访问资源文件属性值:

rb.getString("greeting.common");

假设我们再resource资源目录下创建了一个i18n的文件夹,在该文件夹中放了2个资源文件:

i18n

执行如下命令:

ResourceBundle rbChina = ResourceBundle.getBundle("i18n/resource", Locale.CHINA);
ResourceBundle rbEnglish = ResourceBundle.getBundle("i18n/resource", Locale.US);

System.out.println("cn:" + rbChina.getString("greeting.common"));
System.out.println("us:" + rbEnglish.getString("greeting.common"));

得到的输出为:

cn:您好!
us:How are you!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值