国际化

/ Spring / 没有评论 / 362浏览

我们在开发项目时,常常会需要支持多国语言,这时就会要求我们的程序支持国际化,也就是可以根据客户端系统的语言类型显示相应的文案与界面。在spring中可以很方便的开发出支持国际化的Web项目。除了spring为我们开发国际化提供了支持,在java中也为我们提供了相应的API。例如java.util.Locale类。Locale类是表示语言和国家/地区信息的本地化类,也就是通过语言和国家或地区,来确定该系统的国际化版本。这时可能有人会想为什么要通过两个参数来确定,单纯的通过语言确定不了吗?答案当然是不能的。例如我们知道,美国和英国的母语都是英语,所以这两个国家的语言类型都是英语类型,在Locale类中用cn表示。既然它们的语言类型是一样的,所以我们并不能通过一个参数来确定。下面是一些国家的语言代码和国家或地区的代号。

QQ20170607-070119.png

下面我们简单看一下Locale类的基本使用。

@Test
public void test() {
Locale locale1 = new Locale("zh", "CN");
Locale locale2 = new Locale("zh");
Locale locale3 = Locale.CHINA;
Locale locale4 = Locale.getDefault();
System.out.println(String.format("locale1: %s", locale1.getDisplayName()));
System.out.println(String.format("locale2: %s", locale2.getDisplayName()));
System.out.println(String.format("locale3: %s", locale3.getDisplayName()));
System.out.println(String.format("locale4: %s", locale4.getDisplayName()));
}
locale1: 中文 (中国)
locale2: 中文
locale3: 中文 (中国)
locale4: 中文 (中国)

下面我们看一下Locale类的简单应用。我们知道不同的国家的货币符号和日期类型是不同的,所以接下来我们将通过Locale类来定制化的显示不同国家或地区的货币符号和日期类型。

@Test
public void test() {
Locale locale = new Locale("zh", "CN");
NumberFormat numberFormat = NumberFormat.getCurrencyInstance(locale);
double money = 123456.78;
System.out.println(String.format("money: %s", numberFormat.format(money)));

locale = new Locale("cn", "US");
DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM, locale);
Date time = new Date();
System.out.println(String.format("time: %s", dateFormat.format(time)));
}
money: ¥123,456.78
time: Jun 7, 2017

Locale类除了有上述的作用外,还可以为我们开发国际化程序时提供筛选定制化文件的功能,也就是通过Locale类来为我们选择不同语言和国家的语言文件。但在开发国际化程序时除了需要上述的功能外,还需要通过配置文件中的文案显示不同的内容,也可以理解为配置文件中的文案为模板,而不同用户访问程序时,提示的信息是不同的。这时我们就需要动态更改配置文件中的文案的功能 。在Java中我们可以用占位符来解决。但在本篇中我们将使用spring为我们提供了工具类来实现上述的功能,也就是MessageFormat类。因为MessageFormat类比Java为我们的提供的API提供了更加强大的占位符功能。下面我们看一下MessageFormat类使用。

@Test
public void test() {
String msg = "你好: {0},你于 {1} 在吉林乌拉银行存入人民币 {2} 元整。";
Object[] params = {"吉林乌拉", new GregorianCalendar().getTime(), 10000};
System.out.println(MessageFormat.format(msg, params));
}
你好: 吉林乌拉,你于 17-6-7 上午8:11 在吉林乌拉银行存入人民币 10,000 元整。

在开发国际化程序时除了动态选择不同语言的文件外,还需要的一个功能就是读取文件中的属性。在Java中我可以通过File类来读取配置文件中的属性。虽然这么做是可以的,但是这样不是很方便的获取我们想要的属性。Java为了方便我们获取配置文件中的属性,于是为我们提供了ResourceBundle类。下面我们看一下ResourceBundle类的使用。

app_en_US.properties

resource.message=Hello. Welcome to login.

app_zh_CN.properties

resource.message=你好,欢迎登陆。
@Test
public void test() {
ResourceBundle resourceBundleZh = ResourceBundle.getBundle("app", Locale.CHINA);
ResourceBundle resourceBundleEn = ResourceBundle.getBundle("app", Locale.US);
System.out.println(String.format("中文:%s", resourceBundleZh.getString("resource.message")));
System.out.println(String.format("英文:%s", resourceBundleEn.getString("resource.message")));
}
中文:你好,欢迎登陆。
英文:Hello. Welcome to login.

上述的功能基本能够实现我们开发国际化程序的需求,但是spring为了我们更方便的使用,于是提供了MessageSource接口。spring为这个接口提供了很多种实现类,我们可以通过spring.xml的方式来选择不同语言的配置文件。

app_en_US.properties

resource.message=Hello {0} . Welcome to login.

app_zh_CN.properties

resource.message=你好 {0} ,欢迎登陆。
<bean id="message" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>app</value>
</list>
</property>
</bean>
@Test
public void test() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
MessageSource messageSource = applicationContext.getBean("message", MessageSource.class);
System.out.println(messageSource.getMessage("resource.message", new Object[]{"吉林乌拉"}, Locale.CHINA));
System.out.println(messageSource.getMessage("resource.message", new Object[]{"jilinwula"}, Locale.US));
}
你好 吉林乌拉 ,欢迎登陆。
Hello jilinwula . Welcome to login.

spring除了提供ResourceBundleMessageSource类外还提供了ReloadableResourceBundleMessageSource类来加载国际化文件。它们的区别是后者支持定时的刷新国际化文件,也就是在程序不重启的情况下,可以设置刷新的周期,以达到动态更新文件的功能。具体的配置如下。

<bean id="message" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>app</value>
</list>
</property>
<!-- 5秒刷新一次 -->
<property name="cacheSeconds" value="5"/>
</bean>

ApplicationContext默认实现了MessageSource接口,所以我们在日常开发时,只需要将ResourceBundleMessageSource注入到ApplicationContext中我们就可以直接使用了,注入的名字为messageSource。具体的配置如下:

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>app</value>
</list>
</property>
<!-- 5秒刷新一次 -->
<property name="cacheSeconds" value="5"/>
</bean>
@Test
public void test() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
System.out.println(applicationContext.getMessage("resource.message", new Object[]{"吉林乌拉"}, Locale.CHINA));
System.out.println(applicationContext.getMessage("resource.message", new Object[]{"jilinwula"}, Locale.US));
}
你好 吉林乌拉 ,欢迎登陆。
Hello jilinwula . Welcome to login.