Spring国际化的应用及原理详解

1. 简介

Spring国际化(Spring Internationalization,简称i18n)是Spring框架提供的一种机制,用于支持多语言的应用程序。它使得开发者能够轻松地在应用程序中实现不同语言的支持,从而满足全球化的需求。通过Spring国际化,开发者可以将应用程序的文本、标签、消息等资源抽取出来,并使用合适的语言文件进行翻译,使得应用程序能够根据用户的语言偏好自动切换语言。这种机制不仅简化了多语言支持的实现,还使得应用程序更加易于维护和扩展。在Spring国际化的实现中,主要涉及到了MessageSource、LocaleResolver等核心组件,它们共同协作,实现了语言切换的功能。通过使用Spring国际化的API,开发者可以方便地定义语言区域、加载资源文件、处理消息等操作,从而快速构建多语言的应用程序。

2. API介绍

ApplicationContext 接口扩展了一个名为 MessageSource 的接口,因此提供了国际化("i18n")功能。Spring 还提供了 HierarchicalMessageSource 接口,该接口可以分层解析消息。这些接口共同构成了 Spring 实现消息解析的基础。这些接口定义的方法包括:

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

用于从 MessageSource 获取消息的基本方法。如果在指定的本地没有找到消息,则使用默认消息。通过标准库提供的 MessageFormat 功能,传入的任何参数都会成为替换值。

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

与前一种方法基本相同,但有一点不同:不能指定默认信息。如果找不到信息,就会抛出 NoSuchMessageException 异常。

  • String getMessage(MessageSourceResolvable resolvable, Locale locale)

前面方法中使用的所有属性也都封装在一个名为 MessageSourceResolvable 的类中,你可以使用该方法。

3. 国际化初始化

Spring容器ApplicationContext初始化过程中,会从容器中查找MessageSource类型的Bean。并且该Bean的名称必须是 messageSource。如果找到了这样一个 Bean,对前面方法的所有调用都会委托给消息源。如果没有找到消息源,ApplicationContext 会尝试查找包含同名Bean的父类。如果找到了,它就会使用该 bean 作为消息源。如果 ApplicationContext 无法找到任何消息源,则会实例化一个空的 DelegatingMessageSource,以便能够接受对上述方法的调用。


public abstract class AbstractApplicationContext {public void refresh() {// 初始化消息源initMessageSource();}/*** 初始化消息源。* 如果当前上下文中没有定义消息源,则使用父级消息源。*/
protected void initMessageSource() {ConfigurableListableBeanFactory beanFactory = getBeanFactory();if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);// 使消息源知道父级消息源。if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource hms &&hms.getParentMessageSource() == null) {// 只有当父级消息源尚未注册时,才将父上下文设置为父级消息源。hms.setParentMessageSource(getInternalParentMessageSource());}if (logger.isTraceEnabled()) {logger.trace("使用的消息源为 [" + this.messageSource + "]");}}else {// 使用空消息源以能够接受getMessage调用。DelegatingMessageSource dms = new DelegatingMessageSource();dms.setParentMessageSource(getInternalParentMessageSource());this.messageSource = dms;beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);if (logger.isTraceEnabled()) {logger.trace("没有'" + MESSAGE_SOURCE_BEAN_NAME + "' bean,使用 [" + this.messageSource + "]");}}
}
}


4. 国际化配置

基于Spring环境


@Bean(AbstractApplicationContext.MESSAGE_SOURCE_BEAN_NAME)
public MessageSource messageSource() {ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource() ;// 这里设置的是basename,message是文件的前缀(不是包)messageSource.addBasenames("classpath:com/pack/main/databinder/message") ;return messageSource ;
}

在包com/pack/main/databinder下建2个文件分别:message_zh_CN.properties和message_en_US.properties。文件内容如下:

message_zh_CN.properties

#姓名必须填写
user.name.empty=\u59D3\u540D\u5FC5\u987B\u586B\u5199

message_en_US.properties

user.name.empty=name is required

调用


try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class)) {// Locale.CHINA或者Locale.USSystem.out.println(context.getMessage("user.name.empty", null, Locale.CHINA)) ;
}

基于SpringBoot环境

spring:messages:basename: message

注意:你需要提供一个默认的message.properties文件


@RestController
@RequestMapping("/i18n")
public class I18NController {@Resourceprivate ApplicationContext context ;@GetMapping("/index")public String index() {return context.getMessage("user.name.empty", null, "默认消息", LocaleContextHolder.getLocale()) ;}}

Locale从当前线程上下文中获取。该Locale是在DispatcherServlet中初始化的。

在接口调用时,我们只需要指定Access-Language header

5. 其它配置

Spring为我们提供了一个便捷的类,可以更方便的访问消息源,项目中只需要注册如下bean:

@Bean
public MessageSourceAccessor messageSourceAccessor(MessageSource messageSource) {MessageSourceAccessor accessor = new MessageSourceAccessor(messageSource) ;return accessor ;
}

访问

@Resource
private MessageSourceAccessor accessor ;
@GetMapping("/index")
public String index() {return accessor.getMessage("user.name.empty") ;
}

带占位符的消息访问

在消息文件中定义如下:


#年龄的取值范围从{0}~{1}
user.age.range=\u5E74\u9F84\u7684\u53D6\u503C\u8303\u56F4\u4ECE{0}~{1}

访问

@GetMapping("/index")
public String index() {return accessor.getMessage("user.age.range", new Object[] {1, 100}) ;
}

注:Spring 还提供了一个ReloadableResourceBundleMessageSource 类。该变体支持相同的捆绑文件格式,但比基于 JDK 的标准 ResourceBundleMessageSource 实现更灵活。特别是,它允许从任何 Spring 资源位置(而不仅仅是从类路径)读取文件,并支持捆绑属性文件的热重载(同时在两者之间有效地缓存它们)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/323607.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源可视化表单优点多,靠它进入流程化办公!

最近有很多粉丝在询问开源可视化表单。众所周知,现在流程化办公和数字化转型已经成为发展潮流了,如果还采用传统的表格制作,显然已经满足不了业务量越来越多的办公需求了。开源可视化表单优点多,进入高效优质的流程化办公&#xf…

【2023中国汽车年出口量赶超日本,让世界见证中国力量,LT9211-车载显示器专家】

据中国汽车工业协会(以下称“中汽协”)发布的数据显示,今年1-11月中国乘用车和商用车出口分别同比增长65.1%与29.8%,总体汽车出口量同比增长超过50%,达到441.2万辆。 日本媒体判断,中国汽车2023年出口量将超…

网络割接为什么经常是半夜进行?

你们好,我的网工朋友。 假设你最近遇到了一个客户,客户有个新的园区刚刚建成,园区内包括建筑物若干,地理覆盖面也较广,园区建成后,肯定是需要一个专用网络的,用于承载公司的业务流量。 这时候&…

图形阴影面积-第11届蓝桥杯省赛Python真题精选

[导读]:超平老师的Scratch蓝桥杯真题解读系列在推出之后,受到了广大老师和家长的好评,非常感谢各位的认可和厚爱。作为回馈,超平老师计划推出《Python蓝桥杯真题解析100讲》,这是解读系列的第28讲。 图形阴影面积&…

c# windows10大小端试

测试代码: unsafe public void ceshi() {byte[] by BitConverter.GetBytes(0x12345678);Debug.WriteLine(" byte[0] 0x" by[0].ToString("x2"));Debug.WriteLine(" byte[1] 0x" by[1].ToString("x2"));Debug.WriteLi…

车位关键点检测-车位识别-车辆识别检测(教程+代码)

车位关键点检测、车位识别和车辆识别检测是现代智能交通系统中的重要技术,它们在提高停车管理效率和交通流畅度方面起着重要作用。以下是对这三个技术的分点阐述: 1. 车位关键点检测: 车位关键点检测是指通过计算机视觉技术,自动…

Mp3tag for Mac:音乐文件的智能管理助手,让你的音乐库井然有序!

Mp3tag for Mac 是一个专业的音乐标签编辑软件,它可以帮助用户快速编辑音乐文件的元数据,如歌曲名称、艺术家、专辑、封面、流派、年份等等。它支持多种音频格式,包括 MP3、M4A、FLAC、OGG、WMA 等等。它还可以自动获取互联网上的音乐元数据&…

开源协议简介和选择

软件国产化已经提到日程上了,先来研究一下开源协议。 引言 在追求“自由”的开源软件领域的同时不能忽视程序员的权益。为了激发程序员的创造力,现今世界上有超过60种的开源许可协议被开源促进组织(Open Source Initiative)所认可…

计算化学顶刊封面!玻色量子联合上海交大张健课题组发表量子计算重要成果

​2023年12月13日,北京玻色量子科技有限公司(以下简称“玻色量子”)联合上海交通大学在中科院分区1区、计算化学领域Top刊物JCTC(Journal of Chemical Theory and Computation)内刊的封面上发表了以“Encoding Molecul…

仓库管理软件有哪些比较好用?

“仓库管理软件有哪些比较好用?” “好用,却不一定适合。” 有时候,不是某个仓库管理软件不好用,而是它不适合你们企业。 制造业企业的仓库管理场景,随着制造业企业规模的扩大,逐步精细化,企…

ruoyi-ai 基于ruoyi-plus实现AI聊天和绘画功能-后端

基于ruoyi-plus实现AI聊天和绘画功能-后端 本项目完全开源免费! 后台管理界面使用elementUI服务端使用Java17SpringBoot3.X ruoyi-ai: 基于ruoyi-plus实现AI聊天和绘画功能-后端 实现功能 集成OpenAi API (gpt-4-vision-preview dall-e-3)接入文生图模型&#xf…

HTTP3/QUIC 性能测试与配套组件

背景 最近一年很多关于QUIC的文章层出,但是发现一个问题,这些文章都是在介绍QUIC或HTTP3是怎样的一个东西,以及它的优点和机制,将它夸的近乎上天了。然而有心的人估计会亲手做一些测试,就会发现这个被捧上天的东西性能…