Java国际化与格式化
一、简介
国际化是指在程序运行时可以根据客户端请求中的国家(地区)、语言的信息而显示不同的界面。国际化的英文单词为Internationalization
,简称I18N
(I、N分别为第一个和最后一个字母,18为中间省略的字母数)。
1、国际化相关类
-
java.util.ResourceBundle
加载某个国家、语言的资源包。
-
java.util.Locale
表示一个特定的国家(地区)、语言环境。
-
java.text.MessageFormat
格式化带占位符的字符串。
2、国际化原理
将需要做国际化的内容(标签、提示信息等)放在资源文件中,并提供不同国家、语言的资源文件。资源文件命名如下:
其中,language
和country
必须是Java支持的语言和国家(Java支持的语言和国家可以通过Locale.getAvailableLocales()
查看)。
-
baseName_language_country.properties
-
baseName_language.properties
-
baseName.properties
二、使用国际化
1、定义资源文件
app_en_US.properties
hi=Hello
app_zh_CN.properties
hi=\u4F60\u597D
如果资源文件中包含了非西欧字符,则需要将这些字符转为对应的Unicode编码,Java提供了native2ascii
的工具,此工具在Java安装目录的bin
目录下(%JAVA-HOME%/bin/native2ascii.exe
)。
在命令行下执行:native2ascii app_zh_CN.properties app.properties
即可将hi=你好
转换为hi=\u4F60\u597D
。
2、在程序中加载资源文件
public static void main(String[] args) {
Locale locale = Locale.getDefault();
String baseName = "app";
String key = "hi";
//按Locale加载指定的资源文件
ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale);
System.out.println(bundle.getString(key));
locale = Locale.US;
bundle = ResourceBundle.getBundle(baseName, locale);
System.out.println(bundle.getString(key));
}
- 程序输出
你好
Hello
3、处理包含占位符的字符串
可以使用MessageFormat
来处理包含占位符的字符串,例如:你好,{0}!现在是{1}。
;需要用到的方法为format
方法,方法定义如下:
java.text.MessageFormat.format(String, Object...)
- 样例
String pattern = "你好,{0}!现在是{1}。";
System.out.println(MessageFormat.format(pattern, "Tom", new Date()));
- 程序输出
你好,Tom!现在是18-8-4 下午6:42。
4、使用类文件代替资源文件
作为资源文件的Java类必须满足:
-
类名命名和属性文件命名的要求一致
-
类必须继承
java.util.ListResourceBundle
,重写getContents()
方法
import java.util.ListResourceBundle;
public class App_zh_CN extends ListResourceBundle{
@Override
protected Object[][] getContents() {
Object[][] contents = new Object[][]{
{"hi", "你好呀!"},
{"welcome", "热烈欢迎!"}
};
return contents;
}
}
在加载资源文件时需要注意大小写,我在测试时发现加载类名资源文件时区分大小写,加载属性资源文件时不区分大小写。
ResourceBundle bundle = ResourceBundle.getBundle("App", locale);
我在测试时xxx.properties
和Xxx_zh_CN.java
都需要放到src目录下。
5、ResourceBundle
资源加载顺序
ResourceBundle
会按以下顺序搜索资源文件,如果前面的文件不存在才会使用后面的。
-
baseName_zh_CN.class
-
baseName_zh_CN.properties
-
baseName_zh.class
-
baseName_zh.properties
-
baseName.class
-
baseName.properties
`
三、数值与日期的格式化
可以使用java.text.NumberFormat
和java.text.DateFormat
将数值和日期转换成字符串,这两个类中都包含了format
和parse
方法。其中,format
方法用于将数值、日期格式化成字符串,parse
方法用于将字符串解析成数值和日期。
1、数值格式化
可以使用NumberFormat
的getXxxInstance()
方法来创建NumberFormat
对象,创建时也可以指定Locale
。
format
double number = 66.5;
//货币
NumberFormat format = NumberFormat.getCurrencyInstance();
System.out.println(format.format(number));
format = NumberFormat.getCurrencyInstance(Locale.US);
System.out.println(format.format(number));
//整数
format = NumberFormat.getIntegerInstance();
System.out.println(format.format(number));
//百分数
format = NumberFormat.getPercentInstance();
System.out.println(format.format(number));
程序输出:
¥66.50
$66.50
66
6,650%
parse
try {
NumberFormat format = NumberFormat.getInstance();
System.out.println(format.parse("88.99"));
//整数
format = NumberFormat.getIntegerInstance();
System.out.println(format.parse("99.01"));
//货币
format = NumberFormat.getCurrencyInstance(Locale.US);
System.out.println(format.parse("$33.66"));
} catch (ParseException e) {
e.printStackTrace();
}
程序输出:
88.99
99
33.66
2、日期格式化
与NumberFormat
类似,可以使用DateFormat
的getXxxInstance()
方法来创建DateFormat
对象,创建时可以指定日期时间样式和Locale
。日期时间样式为DateFormat
的四个静态常量:FULL
、LONG
、MEDIUM
、SHORT
,默认为MEDIUM
。
format
Date date = new Date();
//日期
DateFormat format = DateFormat.getDateInstance(DateFormat.SHORT);
System.out.println(format.format(date));
format = DateFormat.getDateInstance(DateFormat.MEDIUM);
System.out.println(format.format(date));
format = DateFormat.getDateInstance(DateFormat.LONG);
System.out.println(format.format(date));
format = DateFormat.getDateInstance(DateFormat.FULL);
System.out.println(format.format(date));
//时间
format = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.US);
System.out.println(format.format(date));
format = DateFormat.getTimeInstance(DateFormat.MEDIUM, Locale.US);
System.out.println(format.format(date));
format = DateFormat.getTimeInstance(DateFormat.LONG, Locale.US);
System.out.println(format.format(date));
format = DateFormat.getTimeInstance(DateFormat.FULL, Locale.US);
System.out.println(format.format(date));
//日期时间
format = DateFormat.getDateTimeInstance();
System.out.println(format.format(date));
format = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.US);
System.out.println(format.format(date));
程序输出
18-8-4
2018-8-4
2018年8月4日
2018年8月4日 星期六
8:30 PM
8:30:25 PM
8:30:25 PM CST
8:30:25 PM CST
2018-8-4 20:30:25
Aug 4, 2018 8:30:25 PM
parse
try {
DateFormat format = DateFormat.getDateTimeInstance();
Date date = format.parse("2018-08-08 08:08:08");
System.out.println(DateFormat.getInstance().format(date));
} catch (ParseException e) {
e.printStackTrace();
}
程序输出:
18-8-8 上午8:08
SimpleDateFormat
使用java.text.SimpleDateFormat
类可以更方便地格式化(解析)日期。
Pattern | Output |
---|---|
dd.MM.yy | 30.06.09 |
yyyy.MM.dd G ‘at’ hh:mm:ss z | 2009.06.30 AD at 08:29:36 PDT |
EEE, MMM d, ‘‘yy | Tue, Jun 30, ‘09 |
h:mm a | 8:29 PM |
H:mm | 8:29 |
H:mm:ss:SSS | 8:28:36:249 |
K:mm a,z | 8:29 AM,PDT |
yyyy.MMMMM.dd GGG hh:mm aaa | 2009.June.30 AD 08:29 AM |
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(format.format(date));
try {
System.out.println(format.parse("2018-08-08"));
} catch (ParseException e) {
e.printStackTrace();
}
程序输出:
2018-08-04
Wed Aug 08 00:00:00 CST 2018
参考资料:
-
《疯狂Java》