[Java] JDK与Spring国际化支持 - 综合 -

当前位置:首页  >  综合  > 正文

[Java] JDK与Spring国际化支持

[Java] JDK与Spring国际化支持
2023-05-22 15:21:24 来源:博客园

0 序言

Spring contextSpring IoCApplicationContext以及Context相关的设计模式进行了介绍。

ApplicationContext作为一个Context在应用的运行层提供了IoC容器事件国际化等功能接口。

Spring的国际化(i18n)功能是通过MessageSource接口实现的,他提供了MessageSource::getMessage方法从预设的资源中获取对应的数据。


(相关资料图)

1 JDK 国际化核心组件 : Java 标准资源绑定

1.1 java.util.ResourceBundle

1.1.1 概述

在介绍MessageSource之前,得先说清楚Java(J2SE)对国际化的基本实现——ResourceBundle,因为MessageSource是用它实现的。ResourceBundle很好理解,他就是按照规范的格式放置*.properties资源文件,然后根据输入的语言环境来返回资源。

ResourceBundle类提供了软件国际化的捷径。通过此类,可以使您所编写的程序可以:

  • 轻松地本地化或翻译成不同的语言
  • 一次处理多个语言环境
  • 以后可以轻松地进行修改,支持更多的语言环境

说的简单点,这个类的作用就是读取资源属性文件(properties),然后根据.properties文件的名称信息(本地化信息),匹配当前系统的国别语言信息(也可以程序指定),然后获取相应的properties文件的内容。使用这个类,要注意的一点是,这个properties文件的名字是有规范的:一般的命名规范是: 自定义名_语言代码_国别代码.properties如果是默认的,直接写为:自定义名.properties比如:

myres_en_US.propertiesmyres_zh_CN.propertiesmyres.properties

当在中文操作系统下,如果myres_zh_CN.properties、myres.properties两个文件都存在,则优先会使用myres_zh_CN.properties,当myres_zh_CN.properties不存在时候,会使用默认的myres.properties。

  • 没有提供语言和地区的资源文件是系统默认的资源文件
  • 资源文件都必须是ISO-8859-1编码。
  • 因此,对于所有非西方语系的处理,都必须先将之转换为Java Unicode Escape格式。转换方法是通过JDK自带的工具native2ascii.

1.1.2 示例1

  • Step1 我们有3个资源文件放置在classpath的根目录(本例是放在src/main/resource)中,文件名分别为:
  • i18n_en_US.properties
  • i18n_zh_CN.properties
  • i18n_web_BASE64.properties

文件中的内容如下:

#i18n_en_US.propertiessay=Hallo world!#i18n_zh_CN.propertiessay=\u5927\u5BB6\u597D\uFF01#i18n_web_BASE64.propertiessay=+-+-+-ABC
  • Step2 然后,我们通过ResourceBundle类来使用这些i18n的资源文件:
public class I18nApp {public static void main(String[] args) {        //使用当前操作系统的语言环境ResourceBundle rb = ResourceBundle.getBundle("i18n", Locale.getDefault());System.out.println(rb.getString("say"));        //指定简体中文环境        rb = ResourceBundle.getBundle("i18n", new Locale("zh", "CN"));System.out.println(rb.getString("say"));        //通过预设指定简体英文环境rb = ResourceBundle.getBundle("i18n", Locale.SIMPLIFIED_CHINESE);System.out.println(rb.getString("say"));        //指定美国英语rb = ResourceBundle.getBundle("i18n", Locale.US);System.out.println(rb.getString("say"));        //使用自定义的语言环境Locale locale = new Locale("web", "BASE64");rb = ResourceBundle.getBundle("i18n", locale);System.out.println(rb.getString("say"));}}

按照开发文档的要求:

  • 使用ResourceBundle加载的资源文件都必须放置在根目录
  • 且必须按照${resourceName}_${language}_${region}的方式来命名。这个命名方式正好能对应ResourceBundle::getBundle方法中的参数。

例如: ResourceBundle.getBundle("i18n", new Locale("zh", "CN"))

  • "i18n"对应${name}
  • "zh"对应${language}
  • 而“CN”对应$

这样我们就可以通过传导参数来使用不同的资源。如果不指定${language}${region},该文件就是一个默认文件。

Locale类预设了很多资源类型,比如:Locale.SIMPLIFIED_CHINESELocale.US,实际上他们就等价于new Locale("zh", "CN")new Locale("en", "US")。只是Java的开发人员做了一些静态的预设。

除了预设内容的Locale,我们还可以像Locale locale = new Locale("web", "BASE64")这样添加自定义的内容,他对应名为i18n_web_BASE64.properties的资源文件。

1.1.3 示例2

定义三个资源文件,放到src的根目录下面(必须这样,或者你放到自己配置的calsspath下面。

  • myres.properties
bbb=thanks
  • myres_en_US.properties
aaa=goodbbb=thanks
  • myres_zh_CN.properties
aaa=\u597dbbb=\u591a\u8c22
  • 使用
import java.util.Locale;import java.util.ResourceBundle;/*** 国际化资源绑定测试** @author leizhimin 2009-7-29 21:17:42*/public class TestResourceBundle {public static void main(String[] args) {Locale locale1 = new Locale("zh", "CN");ResourceBundle resb1 = ResourceBundle.getBundle("myres", locale1);System.out.println(resb1.getString("aaa"));ResourceBundle resb2 = ResourceBundle.getBundle("myres", Locale.getDefault());System.out.println(resb1.getString("aaa"));Locale locale3 = new Locale("en", "US");ResourceBundle resb3 = ResourceBundle.getBundle("myres", locale3);System.out.println(resb3.getString("aaa"));}}

运行结果:

好好goodProcess finished with exit code 0

如果使用默认的Locale,那么在英文操作系统上,会选择myres_en_US.propertiesmyres.properties资源文件。

1.2 Locale

Locale对象表示了特定的地理政治文化地区。需要 Locale 来执行其任务的操作称为语言环境敏感的操作,它使用 Locale 为用户量身定制信息。例如,显示一个数值就是语言环境敏感的操作,应该根据用户的国家、地区或文化的风俗/传统来格式化该数值。使用此类中的构造方法来创建 Locale:

  • Locale(String language)
  • Locale(String language, String country)
  • Locale(String language, String country, String variant)创建完 Locale 后,就可以查询有关其自身的信息。使用 getCountry 可获取 ISO 国家代码,使用 getLanguage 则获取 ISO 语言代码。可用使用 getDisplayCountry 来获取适合向用户显示的国家名。同样,可用使用 getDisplayLanguage 来获取适合向用户显示的语言名。有趣的是,getDisplayXXX 方法本身是语言环境敏感的,它有两个版本:一个使用默认的语言环境作为参数,另一个则使用指定的语言环境作为参数。
语言参数是一个有效的 ISO 语言代码。这些代码是由 ISO-639 定义的小写两字母代码。在许多网站上都可以找到这些代码的完整列表,如:http://www.loc.gov/standards/iso639-2/englangn.html。国家参数是一个有效的 ISO 国家代码。这些代码是由 ISO-3166 定义的大写两字母代码。在许多网站上都可以找到这些代码的完整列表,如:http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html。

1.3 native2ascii | 中文资源文件的转码

如果觉得麻烦,可以直接将中文粘贴到里面,回车就可以看到转码后的结果了。

2 Spring 国际化 核心组件

2.1 MessageSource 接口

2.1.1 概述

ApplicationContext接口扩展了MessageSource接口,因而提供了消息处理的功能(i18n国际化)。与HierarchicalMessageSource一起使用,它还能够处理嵌套的消息,这些是spring提供的处理消息的基本接口。

2.1.2 核心方法

让我们快速浏览一下它所定义的方法:

  • String getMessage(String code, Object[] args, String default, Locale loc)

用来从MessageSource获取消息的基本方法。如果在指定的locale中没有找到消息,则使用默认的消息。args中的参数将使用标准类库中的MessageFormat来作消息中替换值。

  • String getMessage(String code, Object[] args, Locale loc)

本质上和上一个方法相同,其区别在:没有指定默认值,如果没找到消息,会抛出一个NoSuchMessageException异常。

  • String getMessage(MessageSourceResolvable resolvable, Locale locale)

上面方法中所使用的属性都封装到一个MessageSourceResolvable实现中,而本方法可以指定MessageSourceResolvable实现。

2.1.3 ApplicationContext与MessageSource的工作原理

  • 当一个ApplicationContext被加载时,它会自动在context中查找已定义为MessageSource类型的bean。

bean的名称须为messageSource

  • 如果找到,则:所有对上述方法的调用将被委托给该bean

  • 否则,ApplicationContext会在其父类中查找是否含有同名的bean。如果有,就把它作为MessageSource

  • 如果它最终没有找到任何的消息源,一个空的StaticMessageSource将会被实例化,使它能够接受上述方法的调用。

2.1.4 MessageSource 接口的实现

Spring目前提供了两个MessageSource的实现:

  • ResourceBundleMessageSource
  • StaticMessageSource

它们都继承NestingMessageSource以便能够处理嵌套的消息。StaticMessageSource很少被使用,但能以编程方式消息源(Message Source)添加消息(Message)

ResourceBundleMessageSource会用得更多一些,为此提供了一下实例化的示例:

                    format        exceptions        windows            

2.1.5 SpringMVC中MessageSource的获取方法

// 资源文件ApplicationResources.properties放在src目录下,也就是classes目录// 配置文件messages.xml也放在src目录下,也就是classes目录// 第1种方法MessageSource resources = new ClassPathXmlApplicationContext("messages.xml");String msg = resources.getMessage("XXXXX", new String[] { "OOOOO" }, null);// 第2种方法ReloadableResourceBundleMessageSource messageSource;messageSource = new ReloadableResourceBundleMessageSource();messageSource.setBasename("classpath:/ApplicationResources");messageSource.setUseCodeAsDefaultMessage(true);msg = messageSource.getMessage("XXXXX", new String[] { "OOOOO" }, Locale.CHINA);// 第3种方法 | 此方式中, messageSource Bean 是配置在 spring-servlet.xml 中的WebApplicationContext wac = RequestContextUtils.getWebApplicationContext(request);msg = wac.getMessage("XXXXX", new String[] { "OOOOO" }, Locale.CHINA);

2.2 ResourceBundleMessageSource

2.2.1 概述

ResourceBundleMessageSource: 提供国际化的类。

ResourceBundleMessageSource的底层实现依赖于java.util.ResourceBundle说的简单点,这个类的作用就是读取资源属性文件.properties)然后,根据.properties文件的名称信息(本地化信息),匹配当前系统的国别语言信息(也可以程序指定)然后,获取相应的properties文件的内容。

2.2.2 配置步骤:示例1

ResourceBundleMessageSource的功能就是用Java标准库的ResourceBundle实现的,所以使用起来和ResourceBundle也差不多。

  • Step1 首先,得将用于处理国际化资源的Bean添加到IoC容器中:
@Configurationpublic class I18nApp {@Bean("messageSource")ResourceBundleMessageSource resourceBundleMessageSource() {ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();messageSource.setBasenames(new String[] { "i18n", "extend" });//添加资源名称return messageSource;}}

                                        i18n                extend                        

切记一定要标记id=messageSourcebasenames这个Setter用于指定*.properties资源文件的名称,规则和前面介绍的ResourceBundle一样。

  • Step2 然后,就可以通过ApplicationContext::getMessage方法获取对应的资源了:
@Configurationpublic class I18nApp {@Bean("messageSource")ResourceBundleMessageSource resourceBundleMessageSource() {ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();messageSource.setBasenames(new String[] { "i18n", "extend" });return messageSource;}public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(I18nApp.class);System.out.println("Spring Default 1:" + context.getMessage("say", null, Locale.getDefault()));System.out.println("Spring Default 2:" + context.getMessage("say", null, null));System.out.println("Spring Chinese:" + context.getMessage("say", null, Locale.SIMPLIFIED_CHINESE));System.out.println("Spring Us English:" + context.getMessage("say", null, Locale.US));System.out.println("Spring Custom:" + context.getMessage("say", null, new Locale("web", "BASE64")));System.out.println("Spring Argument:" + context.getMessage("info", new String[] {"chkui"},null));System.out.println("Spring Info:" + context.getMessage("say", null, null));}}

2.2.2 配置步骤:示例2

  • Step1 新建国际化资源文件
# i18n_en_US.propertiesmessage=welcome:{0}# i18n_zh_CN.propertiesmessage=欢迎:{0}
  • Step2 配置 Spring Bean
    
  • Step3 使用
@Test    public void test() {        ApplicationContext context = new ClassPathXmlApplicationContext("SpringMVC.xml");        System.out.println(context.getMessage("message", new Object[]{"lgh"}, Locale.SIMPLIFIED_CHINESE));        System.out.println(context.getMessage("message", new Object[]{"lgh"}, Locale.US));    }
@Controllerpublic class TestController {    @Autowired    private ResourceBundleMessageSource messageSource;    @RequestMapping(value = "/test4", method = RequestMethod.GET)    public String test4(Locale locale) {        System.out.println(messageSource.getMessage("message", null, locale));        return "i18n";    }}

2.3 占位符替换

注意上面的示例代码的这一行:

context.getMessage("info", new String[] {"chkui"},null))

这里的getMessage向方法传递了一个数组,它用于替换资源文件中的占位符号

在例子中我们除了i18n还加载了一个extend.properties文件,文件内容如下:

info={0}\u5E05\u7684\u8BA9\u4EBA\u6CA1\u813E\u6C14\u3002

文件中的{0}表示这个位置用数组中的[0]位置的元素替换。还有一点需要注意的是,*.properties文件输入中文等UTF-8的符号时需要保留上面这种ACSII的格式,现在大部分IDE都会自动处理的,切记不要为了方便看内容将*.properties的编码格式切换为UTF-8

2.4 获取MessageSource接口

我们有三种方式获取MessageSource接口:

//直接使用ApplicationContext context = new AnnotationConfigApplicationContext(I18nApp.class);context.getMessage("say", null, Locale.getDefault()));//MessageSourceAware(ApplicationContextAware)接口public class ExtendBean implements MessageSourceAware {@Overridepublic void setMessageSource(MessageSource messageSource) {this.setterMs = messageSource;}}//从容器直接注入public class ExtendBean implements MessageSourceAware {@Autowiredprivate MessageSource autowiredMs;}

需要注意的是,使用@Autowired等方式直接获取MessageSource类型的数据得到的是添加到容器的那个Bean,而其他方式获取到的是ApplicationContext。

X 参考文献

  • java.util.ResourceBundle使用详解 - 51CTO
  • SpringMVC-ResourceBundleMessageSource使用 - CSDN
  • spring-MessageSource的配置--ResourceBundleMessageSource - CSDN
  • Spring核心——MessageSource实现国际化 - 腾讯云

标签:

(责任编辑:news01)
考生注意!青岛电影学院新增4个本科招生专业

考生注意!青岛电影学院新增4个本科招生专业

青岛日报社/观海新闻5月19日讯19日,青岛电影学院举行2023年艺术招生工作研讨会,介绍学校办学情况。研讨
05-19 16:09:19
天天速看:女子尝试“秦昊减肥法”致发烧住院,医生:极低能量饮食疗法会造成人体损伤,明星可能通过其他方法补充营养

天天速看:女子尝试“秦昊减肥法”致发烧住院,医生:极低能量饮食疗法会造成人体损伤,明星可能通过其他方法补充营养

女子尝试“秦昊减肥法”致发烧住院,医生:极低能量饮食疗法会造成人体损伤,明星可能通过其他方法补充...
05-19 15:58:52
1229!这位河南大学生真酷! 每日消息

1229!这位河南大学生真酷! 每日消息

“其实老祖宗早就告诉我们了:‘穷则独善其身,达则兼济天下’我延续了一条和我年龄相仿的生命让他可以...
05-19 15:17:20
半衰期计算例题及解析_半衰期

半衰期计算例题及解析_半衰期

1、测定方法有两种,一是核物理法,利用核物理仪器直接测定放射性同位素的放射性强度随时间的减少量,因此
05-19 14:43:21
原油交易提醒:普京喊话“油市稳定”,美债务上限谈判和需求乐观情绪助力,油价劲升逾3% 每日资讯

原油交易提醒:普京喊话“油市稳定”,美债务上限谈判和需求乐观情绪助力,油价劲升逾3% 每日资讯

5月18日(周四)亚市盘初,美原油交投于72 66美元 桶附近;油价周三上涨超3%,美股创近两周最大百分比涨幅
05-19 14:02:51
末节7中6轰23分!穆雷神奇救赎 一人得分几乎顶湖人全队

末节7中6轰23分!穆雷神奇救赎 一人得分几乎顶湖人全队

北京时间5月19日,NBA季后赛西决G2,掘金主场108-103战胜湖人,
05-19 13:20:59
“居民健康的守门人”!全国已组建家庭医生团队超42万个-世界热推荐

“居民健康的守门人”!全国已组建家庭医生团队超42万个-世界热推荐

今天(19日)是第13个“世界家庭医生日”,主题是“签而有约 共享健康”。家庭医生并非“私人医生”,...
05-19 12:16:45
七旬老人被抬到现场取款? 银行:都是误会

七旬老人被抬到现场取款? 银行:都是误会

这家银行,别再折腾老人啦。江苏泰州一位腿脚不便的七旬老太太,忘记了银行密码,银行说重置密码可以啊,你
05-19 12:07:09
世界观察:图片新闻

世界观察:图片新闻

4月10日,本科教育教学审核评估专家组入校开展评估集中考察工作,审核评估专家组依次走访雁山校区各考察点
05-19 11:32:57
世界速讯:如何在Windows10和11上放大和缩小

世界速讯:如何在Windows10和11上放大和缩小

更高分辨率的屏幕正变得越来越普遍,这意味着我们的眼睛压力更小。但更高的分辨率也会使某些功能变得如此详
05-19 10:58:43
日媒:拜登携“核按钮手提箱”抵达广岛-短讯

日媒:拜登携“核按钮手提箱”抵达广岛-短讯

据日媒报道,美国总统拜登18日抵达日本,参加在广岛举行的七国集团(G7)峰会。而拜登助手们携带的公文包中,
05-19 10:27:45
今日嘀嗒打车能微信付吗_嘀嘀打车如何用微信支付|环球微资讯

今日嘀嗒打车能微信付吗_嘀嘀打车如何用微信支付|环球微资讯

1、登录自己的微信,点击右下角的“我”,点了之后再点击“钱包”。2、进去之后点击里面的“滴滴出行”...
05-19 10:12:02
世界热点评!万科551亿元广信资产包两宗地块挂牌  知情人士:目前为政府收储项目

世界热点评!万科551亿元广信资产包两宗地块挂牌 知情人士:目前为政府收储项目

551亿元的广信资产包,6年时间“解包”进度还未达到30%。而万科光找“解包思路”就花费了近三年,这注定...
05-19 09:37:18
每日速讯:大众将推全新MPV车型!6月2号全球首发,尺寸比别克GL8还大

每日速讯:大众将推全新MPV车型!6月2号全球首发,尺寸比别克GL8还大

日前智电出行获取了大众ID BUZZLWB长轴距版车型最新消息,新车计划在6月2日于加利福尼亚州亨廷顿海滩举办全
05-19 09:02:55
天天即时看!瓜尔佳胤霆历史上有这个人吗 镇南王瓜尔佳胤霆历史

天天即时看!瓜尔佳胤霆历史上有这个人吗 镇南王瓜尔佳胤霆历史

今天来聊聊关于瓜尔佳胤霆历史上有这个人吗,镇南王瓜尔佳胤霆历史的文章,现在就为大家来简单介绍下瓜尔佳
05-19 07:56:37
【快播报】真兰仪表(301303.SZ):2022年在中亚五国中已有客户实现销售发货

【快播报】真兰仪表(301303.SZ):2022年在中亚五国中已有客户实现销售发货

格隆汇5月19日丨有投资者在投资者互动平台向真兰仪表提问,“贵公司在中亚五国的业务占比多少?”。真兰...
05-19 07:06:51
美联储:美国5月17日当周未经季节性调整的商业票据余额增加233亿美元

美联储:美国5月17日当周未经季节性调整的商业票据余额增加233亿美元

美联储:美国5月17日当周未经季节性调整的商业票据余额增加233亿美元
05-19 06:31:49
便利蜂被罚5万关店1000家_速读

便利蜂被罚5万关店1000家_速读

出品:创业最前线5月18日消息,据天眼查平台显示,今年5月5日上海便利蜂商贸有限公司江场路店因为存在“生
05-19 04:57:27
灯火阑珊处小说_灯火阑珊处 当前看点

灯火阑珊处小说_灯火阑珊处 当前看点

1、阑珊:零落稀疏的样子。2、灯火阑珊处--昏黑的幽暗之处“灯火阑珊”勿作“良夜将逝”解,“灯火阑珊”...
05-19 02:43:12
当前观察:我爱我家品牌“焕新” 做居住服务的价值重构者

当前观察:我爱我家品牌“焕新” 做居住服务的价值重构者

随着房地产长效机制逐步建立,居住服务业也进入新的发展阶段。新阶段、新需求、新服务,寻找与时代共振、与
05-19 00:39:08
焦点简讯:华钰矿业:目前持有“塔铝金业”封闭式股份公司50%股权

焦点简讯:华钰矿业:目前持有“塔铝金业”封闭式股份公司50%股权

券中社5月18日讯,华钰矿业:目前公司持有“塔铝金业”封闭式股份公司50%股权。塔金项目可控黄金资源量...
05-18 22:26:19
并购财务协同效应_财务协同效应-世界播报

并购财务协同效应_财务协同效应-世界播报

1、20世纪70年代以后,兼并活动已从单纯的横向兼并、纵向兼并发展为混合型兼并,从财务管理的角度看,企业
05-18 21:56:24
环球要闻:巴菲特驱动了日本进入牛市?

环球要闻:巴菲特驱动了日本进入牛市?

在CNBC的采访中,巴菲特对日本五大商社赞赏有加,称其为优秀企业,同时表示将继续投资日本,并在海外寻找更
05-18 20:57:50
全球速看:龙头烤的做法_龙头烤

全球速看:龙头烤的做法_龙头烤

今天小编肥嘟来为大家解答以上的问题。龙头烤的做法,龙头烤相信很多小伙伴还不知道,现在让我们一起来看看
05-18 20:14:30
【天天时快讯】nba2kol2官网在哪下载 最新官方下载安装地址

【天天时快讯】nba2kol2官网在哪下载 最新官方下载安装地址

nba2kol2怎么下载?想要比别人更加抢先抢快的玩到这款游戏,那么你获取游戏开测消息是关键,能够获取到第一
05-18 19:29:15
银行板块涨0.8% 华夏银行涨4.15%居首-视点

银行板块涨0.8% 华夏银行涨4.15%居首-视点

银行板块涨0 8%华夏银行涨4 15%居首
05-18 18:07:32
金桥信息涨9.99% 三个交易日机构净买入5476万元-最资讯

金桥信息涨9.99% 三个交易日机构净买入5476万元-最资讯

金桥信息涨9 99%三个交易日机构净买入5476万元
05-18 17:47:27
自由基学说 自由基-天天播资讯

自由基学说 自由基-天天播资讯

今天来聊聊关于自由基学说,自由基的文章,现在就为大家来简单介绍下自由基学说,自由基,希望对各位小伙伴
05-18 16:59:48
罗马诺:马内与拜仁讨论自己的未来,球员希望留队

罗马诺:马内与拜仁讨论自己的未来,球员希望留队

直播吧5月18日讯据意大利记者罗马诺透露,马内与拜仁讨论未来,球员希望留队。罗马诺指出,马内及其经纪人
05-18 16:53:53
科技部部长王志刚:加大人工智能基础理论和前沿技术研发布局 打造一批人工智能区域高地和技术平台_视点

科技部部长王志刚:加大人工智能基础理论和前沿技术研发布局 打造一批人工智能区域高地和技术平台_视点

第七届世界智能大会18日在天津开幕。科学技术部部长王志刚在会上表示,将紧紧把握全球人工智能发展的新机遇
05-18 16:07:13

为您推荐

精彩推送