记录生活中的点点滴滴

0%

Java实现简单国际化

程序多语言实际就是在不同的地区根据主机不同的设定去匹配与之对应的语言环境。

Local类

要实现多语言环境首先可以通过 Locale 类创建一个本地语言环境对象,我们要获取本机默认的 Locale 类:

1
2
3
//获取本地系统默认的本地化对象
Locale locale = Locale.getDefault();
System.out.println(locale);//zh_CN

创建 Locale 类有如下几种方式:

1
2
3
4
5
6
7
8
9
10
11
//带有语言和国家/地区信息的本地化对象
Locale locale1 = new Locale("zh", "CN");

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

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

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

本地化工具类

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

NumberFormat

1
2
3
4
5
6
7
8
//NumberFormat使用
@Test
public void Test2(){
Locale locale = new Locale("zh", "CN");
NumberFormat format = NumberFormat.getCurrencyInstance(locale);
double val = 123456.78;
System.out.println(format.format(val));//¥123,456.78
}

上面的实例通过 NumberFormat 按本地化的方式对货币金额进行格式化操作

DateFormat

1
2
3
4
5
6
7
8
9
//DateFormat使用
@Test
public void Test3(){
Locale locale = new Locale("zh", "CN");
Date date = new Date();
//该方法第一个入参为时间样式,第二个入参为本地化对象。
DateFormat format = DateFormat.getDateInstance(DateFormat.DEFAULT,locale);
System.out.println(format.format(date));//2020年11月15日
}

通过 DateFormatgetDateInstance(int style,Locale locale) 方法按本地化的方式对日期进行格式化操作。该方法第一个入参为时间样式,第二个入参为本地化对象

MessageFormat

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//MessageFormat使用
@Test
public void Test4(){
//①信息格式化串
String pattern1 = "{0},你好!你于 {1} 在工商银行存入 {2} 元。";
String pattern2 = "At {1,time,short} On {1,date,long},{0} paid {2,number, currency}.";

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

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

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

//John,你好!你于 2020/11/17 下午9:41 在工商银行存入 1,000 元。
System.out.println(msg1);
//At 9:41 PM On November 17, 2020,John paid $1,000.00.
System.out.println(msg2);
}

ResourceBundle工具类

如果应用系统中某些信息需要支持国际化功能,则必须为希望支持的不同本地化类型分别提供对应的资源文件,并以规范的方式进行命名。国际化资源文件的命名规范规定资源名称采用以下的方式进行命名:

资源名_语言代码_国家/地区代码.properties

如下图所示:

资源名是 myResource

我们在 myResource_en_US.properties 中填入下面内容:

1
2
3
4
5
username=username
passwd=passwd
input=input
info.success=welcome,{0}
info.error=error

myResource_zh_CN.properties 中填入下面内容:

1
2
3
4
5
username=\u7528\u6237\u540d
passwd=\u5BC6\u7801
input=\u8BF7\u8F93\u5165
info.success=\u6B22\u8FCE\uff0c{0}
info.error=\u767B\u5f55

本地化不同的同一资源文件,虽然属性值各不相同,但属性名却是相同的,这样应用程序就可以通过Locale对象和属性名精确调用到某个具体的属性值了。如下:

1
2
3
4
5
6
7
8
//加载本地化资源文件
@Test
public void Test1(){
Locale locale = new Locale("zh", "CN");
ResourceBundle rb = ResourceBundle.getBundle("cn.gs.international.myResource",locale);
String s = rb.getString("input");//请输入
System.out.println(s);
}

下面我们做一个用户登录的小案例,提供中文和英文两种格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//小案例
public static void main(String[] args) {
//创建语言环境对象
Locale locale1 = new Locale("zh", "CN");
Locale locale2 = Locale.US;

//通过ResourceBundle工具类绑定资源文件(包名.文件名)
ResourceBundle rb = ResourceBundle.getBundle("cn.gs.international.myResource", locale1);

//从属性文件中根据key获取value值
String username = rb.getString("username");
String passwd = rb.getString("passwd");
String input = rb.getString("input");
String success = rb.getString("info.success");
String error = rb.getString("info.error");

//模拟用户登录
Scanner scanner = new Scanner(System.in);
System.out.println(input+username);
String userName = scanner.next();
System.out.println(input+passwd);
String passWord = scanner.next();
if("admin".equals(userName) && "123".equals(passWord)){
//处理动态文本(模式, 要替换的值……)
String s = MessageFormat.format(success, userName);
System.out.println(s);
}else {
System.out.println(error);
}
}

中文情况下:

英文情况下: