il8n国际化

支持多国语言的web应用,根据客户端系统的语言类型返回对应的界面


方案

为每种语言提供一套相应的资源文件,并以规范化命名的方式保存在特定的目录中,由系统自动根据客户端语言选择适合的资源文件返回


JDK对国际化的支持

1、国际化信息,也称为本地化信息,一般需要两个条件可以确定,即语言类型和国家/地区类型。java通过java.util.Locale类表示一个本地化对象

    @Test
public void testLocale() {
// 语言参数和国家/地区参数都使用ISO标准语言代码表示,每种语言由两位小写字母表示,每个国家/地区由两个大写字母表示
Locale locale = new Locale("zh", "CN");
}
@Test
public void testLocale1() {
Locale locale = Locale.getDefault();
System.out.println(locale); // zh_CN
}

2、java.util包中还提供了几个支持本地化工具类,如NumberFormat、DateFormat、MessageFormat

    @Test
public void numberFormat() {
double amt = 123456.78;
Locale locale = new Locale("zh", "CN");
NumberFormat currFmt = NumberFormat.getCurrencyInstance(locale);
System.out.println(currFmt.format(amt)); // ¥123,456.78
}
@Test
public void dateFormat() {
Date date = new Date();
Locale locale = new Locale("en", "US");
DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, locale); // 第一个参数是时间样式
System.out.println(df.format(date)); // Jan 17, 2019
}
@Test
public void messageFormat1() {
// 以下两行是不同本地化的资源,{n}是占位符
String pattern1 = "{0},你好!你于{1}在工商银行存入{2} 元。";
String pattern2 = "At {1,time,short} On {1,date,long},{0} paid {2,number,currency}.";// short表示获取时分秒部分,long获取日期部分
// 将要替换的变量
Object[] params = {"John", new GregorianCalendar().getTime(),1.0E3};
// 中国格式
String msg1 = MessageFormat.format(pattern1,params);
System.out.println(msg1); // John,你好!你于19-1-17 上午11:56在工商银行存入1,000 元。
// 美国格式
MessageFormat mf = new MessageFormat(pattern2, Locale.US);
String msg2 = mf.format(params);
System.out.println(msg2); // At 11:56 AM On January 17, 2019,John paid $1,000.00.
}

国际化资源的命名规范

国际化资源的命名规范:资源名_语言代码_国家/地区代码.properties;资源名.properties是默认的资源文件,即系统按照命名规范在系统中找不到对应的文件时就使用默认的资源文件;资源名_语言代码.properties是某一语言的默认资源文件
示例:my_zh_CN.properties、my_en_US.properties


JDK ResourceBoundle 加载国际化资源

如果应用中有大量的本地化资源文件,直接通过File操作太笨拙。java提供了专门用于加载本地化资源文件的java.util.ResourceBoundle

1、资源文件

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

resource.properties

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

resource_en_US.properties

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

resource_zh_CN.properties

greeting.common=How are you! {0},today is {1}
greeting.morning = Good morning! {0},now is {1,time,short}
greeting.afternoon = Good Afternoon! {0} now is {1,date,long}

fmt_resource.properties

greeting.common=How are you! {0},today is {1}
greeting.morning = Good morning! {0},now is {1,time,short}
greeting.afternoon = Good Afternoon! {0}, now is {1,date,long}

fmt_resource_en_US.properties

greeting.common=\u60a8\u597d\uff01 {0}\uff0c\u4eca\u5929\u662f {1}
greeting.morning=\u65e9\u4e0a\u597d\uff01 {0}\uff0c\u73b0\u5728\u662f{1,time,short}
greeting.afternoon=\u4e0b\u5348\u597d\uff01 {0}\uff0c\u73b0\u5728\u662f{1,date,long}

fmt_resource_zh_CN.properties

2、程序

    @Test
public void resourceBoundle(){
// 如果不指定本地化对象,将使用本地系统默认的本地化对象。
ResourceBundle rb1 = ResourceBundle.getBundle("resource",Locale.US);
ResourceBundle rb2 = ResourceBundle.getBundle("resource",Locale.CANADA);
System.out.println("us:"+rb1.getString("greeting.common")); // us:How are you!
System.out.println("cn:"+rb2.getString("greeting.common")); // cn:您好!
}
@Test
// 在资源文件中使用占位符
public void resourceBoundleFmt(){
ResourceBundle rb1 = ResourceBundle.getBundle("fmt_resource",Locale.US);
ResourceBundle rb2 = ResourceBundle.getBundle("fmt_resource",Locale.CHINA);
Object[] params = {"John", new GregorianCalendar().getTime()}; String str1 = new MessageFormat(rb1.getString("greeting.common"),Locale.US).format(params);
String str2 =new MessageFormat(rb2.getString("greeting.morning"),Locale.CHINA).format(params);
String str3 =new MessageFormat(rb2.getString("greeting.afternoon"),Locale.CHINA).format(params);
System.out.println(str1);
System.out.println(str2);
System.out.println(str3);
}

Spring的MessageSource接口 

Spring定义了访问国际化信息的MessageSource接口,MessageSource接口被HierarchicalMessageSource、ApplicationContext这两个接口扩展。
HierarchicalMessageSource添加了两个方法,setParentMessageSource()和getParentMessageSource(),用来设置父子层级的MessageSource。
HierarchicalMessageSource最重要的两个实现类是ResourceBundleMessageSource、ReloadableResourceBundleMessageSource,它们基于java的ResourceBundle实现。ReloadableResourceBundleMessageSource提供了定时刷新功能,在不重启系统的情况下可以更新资源。
ApplicationContext也实现了MessageSource接口,在AbstractApplicationContext的refresh()方法中调用initMessageSource()就是初始化容器中的国际化信息资源,它根据反射机制从BeanDefinitionRegistry中找出名为messageSource且类型为org.springframework.context.MessageSource的bean,并将这个bean定义的信息资源加载为容器级的国际化信息资源,假设bean没有被命名为messageSource,会抛出异常。

资源文件使用上面的properties文件

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="myResource" class="org.springframework.context.support.ResourceBundleMessageSource">
<!-- basenames要写死,父类源码里有这个属性 -->
<property name="basenames">
<list>
<value>fmt_resource</value>
</list>
</property>
</bean>
</beans>

my.xml

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="myResource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<!-- basenames要写死,父类源码里有这个属性 -->
<property name="basenames">
<list>
<value>fmt_resource</value>
</list>
</property>
<property name="cacheSeconds" value="5"/>
</bean>
</beans>

my2.xml

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- id的值messageSource是写死的,默认为找它 -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<!-- basenames要写死,父类源码里有这个属性 -->
<property name="basenames">
<list>
<value>fmt_resource</value>
</list>
</property>
</bean>
</beans>

my3.xml

    @Test
public void TestResourceBundleMessageSource() throws InterruptedException {
//ApplicationContext context = new ClassPathXmlApplicationContext("xml/my.xml");
ApplicationContext context = new ClassPathXmlApplicationContext("xml/my2.xml");
MessageSource messageSource = context.getBean("myResource", MessageSource.class);
// 数据
Object[] params = {"John", new GregorianCalendar().getTime()};
// 得到了最终的字符串
String message1 = messageSource.getMessage("greeting.common", params, Locale.US);
String message2 = messageSource.getMessage("greeting.morning", params, Locale.CHINA);
String message3 = messageSource.getMessage("greeting.afternoon", params, Locale.CHINA);
System.out.println(message1);
System.out.println(message2);
System.out.println(message3);
}
@Test
public void TestApplication() throws InterruptedException {
ApplicationContext context = new ClassPathXmlApplicationContext("xml/my3.xml");
// 下面这行代码是可以省略的,因为默认加载messageSource的bean;当然不省略也可以
//MessageSource messageSource = context.getBean("messageSource", MessageSource.class);
// 数据
Object[] params = {"John", new GregorianCalendar().getTime()};
// 得到了最终的字符串
String message1 = context.getMessage("greeting.common", params, Locale.US);
String message2 = context.getMessage("greeting.morning", params, Locale.CHINA);
String message3 = context.getMessage("greeting.afternoon", params, Locale.CHINA);
System.out.println(message1);
System.out.println(message2);
System.out.println(message3);
}

java

     <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.14.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>

pom.xml

 

il8n国际化的更多相关文章

  1. 20145320 《Java程序设计》第8周学习总结

    20145320 <Java程序设计>第8周学习总结 教材学习内容总结 15.1日志 java.util.logging包提供了日志功能相关类与接口,不必额外配置日志组件,就可以在标准ja ...

  2. Spring源码分析(二十三)BeanFactory的后处理

    摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 目录 一.激活注册的 BeanFactoryPostProcessor ...

  3. Spring学习(一)IOC

     Spring是一站式框架: (1)Spring在javaee三层结构中,每一层都提供不同的解决技术. web层:SpringMVC service层:Spring的Ioc dao层:Spring的J ...

  4. BeanFactory和ApplicationContext

    BeanFactory是一个类的通用工厂,可以创建并管理各种类的对象 Bean工厂是Spring框架最核心的接口,它提供了高级Ioc的配置机制.BeanFeactory使管理不同类的Java对象成为可 ...

  5. ASP.NET MVC之国际化(十一)

    前言 在项目中遇到国际化语言的问题是常有的事情,之前在做关于MVC国际化语言时,刚开始打算全部利用AngularJS来实现,但是渐渐发现对于页面Title难以去控制其语言转换,于是对于页面Tiltle ...

  6. 利用angular结合translate为项目实现国际化

    前言 利用H5项目第一版本已经上线,话说有了第一期就有了第二期,这不要为第二期做准备了,老大发话第一件事就要利用Angular JS实现项目的国际化以及后续要借助这个框架来实现其他功能,好吧我表示没怎 ...

  7. MVC之国际化

    MVC之国际化 前言 在项目中遇到国际化语言的问题是常有的事情,之前在做关于MVC国际化语言时,刚开始打算全部利用AngularJS来实现,但是渐渐发现对于页面Title难以去控制其语言转换,于是对于 ...

  8. JavaWeb框架_Struts2_(八)----->Struts2的国际化

    这一篇博文拖了蛮久了,现在先把它完成,结束struts2这个版块,当然这只是最基础的部分,做项目还需要更深的理解.下一个web后端的版块准备做Spring框架的学习-嗯,加油! 1. Struts2的 ...

  9. springboot配置il8n

    springMvc下,配置il8n: 1.配置ResourceBundleMessageSource管理国际化资源文件 2.在页面使用fmt标签取出国际化内容 springBoot下,自动配置了il8 ...

随机推荐

  1. Linux 进程一直占用单核CPU分析

    pidstat 1信息

  2. 一个linux内核编译时遇到的perl语法导致的编译问题解决

    在编译linux内核时,遇到了一个比较诡异的问题.具体log如下: Can't locate strict.pm in @INC (you may need to install the strict ...

  3. Spring Boot Tomcat配置详解

    参数配置容器 server.xx开头的是所有servlet容器通用的配置,server.tomcat.xx开头的是tomcat特有的参数,其它类似. 所有参数绑定配置类:org.springframe ...

  4. Win10手记-IIS部署网站问题解决

    最近在自己的Win10电脑上尝试部署ASP.NET网站时出现了问题,经过多方查找定位到IIS为问题来源. 开始之前 先描述下技术环境: 1.Windows 10 PC 2.Windows 自带的IIS ...

  5. centos7 安装oracle11g

    创建数据库的系统用户和用户组 $ su root #切换到root # groupadd oinstall #创建用户组oinstall # groupadd dba #创建用户组dba # user ...

  6. 用eclipse导入打war包的maven项目

    最近遇到Maven管理下的Spring MVC项目,组内某位将项目代码扔过来,一脸懵逼(囧),查阅了一些资料后终于将此项目运行通了(>_<),特此记录下来与各位分享. 通俗的来说,Mave ...

  7. php 对中文字符串的处理- 随机取出指定个数的汉字

    mb_internal_encoding("UTF-8"); $str="们以我到他会作时要动国产的一是工就年阶义发成部民可出能方进在岭骗休借了不和有大这主中人上为来分生 ...

  8. 使用 Notification API 开启浏览器桌面提醒

    Notifications API 允许网页控制向最终用户显示系统通知 —这些都在顶级浏览上下文视口之外,因此即使用户已经切换标签页或移动到不同的应用程序,也可以显示.该API被设计成与不同平台上的现 ...

  9. SpringBoot全局配置文件

    SpringBoot项目使用一个全局的配置文件application.properties或者是application.yml,在resources目录下或者类路径下的/config下,一般我们放到r ...

  10. 只知道ajax?你已经out了

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由前端林子发表于云+社区专栏 随着前端技术的发展,请求服务器数据的方法早已不局限于ajax.jQuery的ajax方法.各种js库已如雨 ...