【Spring4揭秘 基础4】国际化--MessageSource
来源:互联网 发布:centos7修改ssh端口号 编辑:程序博客网 时间:2024/06/07 09:15
假设我们正在开发一个支持多国语言的Web应用程序,要求系统能够根据客户端的系统的语言类型返回对应的界面:英文的操作系统返回英文界面,而中文的操作系统则返回中文界面——这便是典型的i18n国际化问题。对于有国际化要求的应用系统,我们不能简单地采用硬编码的方式编写用户界面信息、报错信息等内容,而必须为这些需要国际化的信息进行特殊处理。简单来说,就是为每种语言提供一套相应的资源文件,并以规范化命名的方式保存在特定的目录中,由系统自动根据客户端语言选择适合的资源文件。
一、基础知识
概念
“国际化信息”也称为“本地化信息”,一般需要两个条件才可以确定一个特定类型的本地化信息,它们分别是“语言类型”和“国家/地区的类型”。如中文本地化信息既有中国大陆地区的中文,又有中国台湾、中国香港地区的中文,还有新加坡地区的中文。
【部分国际化代码】
ar_sa 阿拉伯语(沙特阿拉伯)ar_iq 阿拉伯语(伊拉克) eu 巴斯克语bg 保加利亚语 zh_tw 中文(中国台湾)zh_cn 中文(中华人民共和国)zh_hk 中文(中国香港特别行政区)zh_sg 中文(新加坡)hr 克罗地亚语 en 英语en_us 英语(美国)en_gb 英语(英国)en_au 英语(澳大利亚)en_ca 英语(加拿大)
JDK中的国际化API
Java通过java.util.Locale类表示一个本地化对象,它允许通过语言参数和国家/地区参数创建一个确定的本地化对象。
Locale locale=new Locale("zh","cn");//中文,中国Locale locale2=new Locale("en","us");//英文,美国Locale locale3=new Locale("zh");//中文--不指定国家Locale locale4=Locale.CHINA;//中文,中国Locale locale5=Locale.CHINESE;//中文
支持国家化的JDK类NumberFormat、DateFormat、MessageFormat
【NumberFormat】可以处理数字,百分数,货币等。下面以货币为例:
Locale locale=new Locale("zh","cn");//中文,中国NumberFormat format=NumberFormat.getCurrencyInstance(locale);System.out.println(format.format(12.34));Locale locale2 =new Locale("en","us");//英文,美国NumberFormat format2=NumberFormat.getCurrencyInstance(locale2);System.out.println(format2.format(13.45));//输出//¥12.34//$13.45
【DateFormat】 通过DateFormat#getDateInstance(int style,Locale locale)方法按本地化的方式对日期进行格式化操作。该方法第一个入参为时间样式,第二个入参为本地化对象
Locale locale=new Locale("zh","cn");//中文,中国DateFormat dateFormat =DateFormat.getDateInstance(DateFormat.YEAR_FIELD,locale) ;System.out.println(dateFormat.format(new Date()));//2016年6月20日
【MessageFormat】在NumberFormat和DateFormat的基础上提供了强大的占位符字符串的格式化功能,它支持时间、货币、数字以及对象属性的格式化操作。
简单的占位符替换:
String str1 = "{0},你好!你于{1}在农业银行存入{2} 元。";String result = MessageFormat.format(str1, "小明", new Date(), 1245.12);System.out.println(result);//小明,你好!你于16-6-20 下午6:29在农业银行存入1,245.12 元。
占位符指定数据类型和格式化类型:
String str1 = "{0},你好!你于{1,date,long}在农业银行存入{2,number, currency}。";MessageFormat format = new MessageFormat(str1, Locale.CHINA);Object[] o = {"小红", new Date(), 1313};System.out.println(format.format(o));//小红,你好!你于2016年6月20日在农业银行存入¥1,313.00 。
加载资源文件
资源文件的命名规范如下
资源名_语言代码_国/地区代码.properties
举一个例子:假设资源名为msg,则语言为英文,国家为美国,则与其对应的本地化资源文件命名为msg_en_US.properties。
name=Xiaomingdescription=He is 19
如果对应语言为中文,文件则命名为resource_zh_ CN.properties。资源文件对文件内容有严格的要求:只能包含ASCII字符,所以必须将非ASCII字符的内容转换为Unicode代码的表示方式。 资源文件内容如下:
#小明name=\u5c0f\u660e#他十九岁了description=\u4ed6\u5341\u4e5d\u5c81\u4e86
Java为我们提供了用于加载本地化资源文件的方便类java.util.ResourceBoundle。
ResourceBoundle为加载及访问资源文件提供便捷的操作,下面的语句从相对于类路径的目录中加载一个名为msg的本地化资源文件:
//加载msg_zh_cn.propertiesResourceBundle bundle = ResourceBundle.getBundle("com/jazz/msg", Locale.CHINA);System.out.println(bundle.getString("name"));System.out.println(bundle.getString("description"));//加载msg_en_us.propertiesResourceBundle bundle2 = ResourceBundle.getBundle("com/jazz/msg", Locale.US);System.out.println(bundle2.getString("name"));System.out.println(bundle2.getString("description"));//=========输出============小明他十九岁了XiaomingHe is 19
在上面的资源文件中,属性值都是一般的字符串,它们不能结合运行时的动态参数构造出灵活的信息,而这种需求是很常见的。要解决这个问题很简单,只须使用带占位符的格式化串作为资源文件的属性值并结合使用MessageFormat就可以满足要求了。
二、MessageSource
接口定义:
public interface MessageSource { //code表示国际化资源中的属性名;args用于传递格式化串占位符所用的运行期参数; //当在资源找不到对应属性名时,返回defaultMessage参数所指定的默认信息; //locale表示本地化对象; String getMessage(String code, Object[] args, String defaultMessage, Locale locale); //与上面的方法类似,只不过在找不到资源中对应的属性名时, //直接抛出NoSuchMessageException异常; String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException; //将属性名、参数数组以及默认信息封装起来,它的功能和第一个接口方法相同。 String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;}
MessageSource的体系结构
【HierarchicalMessageSource接口】
添加了两个方法,建立父子层级的MessageSource结构。该接口的setParentMessageSource (..)方法用于设置父MessageSource,而getParentMessageSource()方法用于返回父MessageSource。
【ResourceBundleMessageSource和ReloadableResourceBundleMessageSource】
它们基于Java的ResourceBundle基础类实现,可以通过资源名加载国际化资源。ReloadableResourceBundleMessageSource提供了定时刷新功能,允许在不重启系统的情况下,更新资源的信息。StaticMessageSource主要用于程序测试,它允许通过编程的方式提供国际化信息。而DelegatingMessageSource是为方便操作父MessageSource而提供的代理类。
使用示例
ResourceBundleMessageSource,结合了JDK中ResourceBundle和MessageFormat的功能,使用实例:
#国际化文件 msg_en_us.propertiesdescription=He is {0},He has {1,number,currency}
ResourceBundleMessageSource source = new ResourceBundleMessageSource();source.setBasename("com/jazz/msg");String result=source.getMessage("description", new Object[]{19, 12.34}, Locale.US);System.out.println(result);//====输出===He is 19,He has $12.34
三、ApplicationContext与MessageSource
ApplicationContext实现了MessageSource的接口。也就是说ApplicationContext的实现类本身也是一个MessageSource对象。
ApplicationContext#initMessageSource()方法所执行的工作就是初始化容器中的国际化信息资源:它从BeanDefinitionRegistry中找出名称为“messageSource”且类型为MessageSource的Bean,将这个Bean定义的信息资源加载为容器级的国际化信息资源。
- 【Spring4揭秘 基础4】国际化--MessageSource
- 【Spring4揭秘 基础1】监听器和事件
- 【Spring4揭秘 基础2】PropertySource和Enviroment
- Spring 利用MessageSource实现国际化
- Spring 利用MessageSource实现国际化
- 利用MessageSource实现国际化[I18N]
- 【Spring4揭秘 基础3】统一抽象资源---Resource
- 【Spring4揭秘 基础5】BeanDefinition及读取、注册
- Spring国际化--从数据库读取messageSource
- spring中MessageSource实现国际化i18n
- 【Spring】Spring 利用MessageSource实现国际化
- Spring之国际化信息MessageSource源码阅读
- Spring-国际化信息02-MessageSource接口
- Spring(21)——国际化MessageSource
- messageSource
- MessageSource
- 【Spring4揭秘 BeanFactory】PropertyEditor
- Spring 国际化 bean的id必须是messageSource
- java.lang.ClassCastException: org.hibernate.impl.SQLQueryImpl cannot be cast to java.util.List
- Color-based object detection using Hue and Saturation thresholding
- Picasso如何直接加载缓存中的图片
- STF -- 数据库定义
- CodeForces 595B Pasha and Phone
- 【Spring4揭秘 基础4】国际化--MessageSource
- 【mysql】关联子查询的一种优化
- Spring-IoC的简单使用及bean的作用域属性
- hdu 3657(最小割求解最大点权独立集)
- fatal error C1189: #error : WRL requires NTDDI_VERSION to be #defined at least
- 常用三角函数公式
- 记一个复制黏贴的功能想法(黏贴剪切板中的数字自增,复制黏贴自增)
- PullrefreshLibrary(PullToRefreshGridView)上拉刷新,下拉加载+异步AsyncTask(二)
- autoware自动注入失败