环境:Spring5.3.23
Spring国际化(Spring Internationalization,简称i18n)是Spring框架提供的一种机制,用于支持多语言的应用程序。它使得开发者能够轻松地在应用程序中实现不同语言的支持,从而满足全球化的需求。通过Spring国际化,开发者可以将应用程序的文本、标签、消息等资源抽取出来,并使用合适的语言文件进行翻译,使得应用程序能够根据用户的语言偏好自动切换语言。这种机制不仅简化了多语言支持的实现,还使得应用程序更加易于维护和扩展。在Spring国际化的实现中,主要涉及到了MessageSource、LocaleResolver等核心组件,它们共同协作,实现了语言切换的功能。通过使用Spring国际化的API,开发者可以方便地定义语言区域、加载资源文件、处理消息等操作,从而快速构建多语言的应用程序。
ApplicationContext 接口扩展了一个名为 MessageSource 的接口,因此提供了国际化("i18n")功能。Spring 还提供了 HierarchicalMessageSource 接口,该接口可以分层解析消息。这些接口共同构成了 Spring 实现消息解析的基础。这些接口定义的方法包括:
用于从 MessageSource 获取消息的基本方法。如果在指定的本地没有找到消息,则使用默认消息。通过标准库提供的 MessageFormat 功能,传入的任何参数都会成为替换值。
与前一种方法基本相同,但有一点不同:不能指定默认信息。如果找不到信息,就会抛出 NoSuchMessageException 异常。
前面方法中使用的所有属性也都封装在一个名为 MessageSourceResolvable 的类中,你可以使用该方法。
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(); // 判断容器中是否有messageSource 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) { HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource; if (hms.getParentMessageSource() == null) { hms.setParentMessageSource(getInternalParentMessageSource()); } } } else { // Use empty MessageSource to be able to accept getMessage calls. DelegatingMessageSource dms = new DelegatingMessageSource(); dms.setParentMessageSource(getInternalParentMessageSource()); this.messageSource = dms; beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource); } }}
@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.US System.out.println(context.getMessage("user.name.empty", null, Locale.CHINA)) ;}
基于SpringBoot环境
spring: messages: basename: message
注意:你需要提供一个默认的message.properties文件
@RestController@RequestMapping("/i18n")public class I18NController { @Resource private ApplicationContext context ; @GetMapping("/index") public String index() { return context.getMessage("user.name.empty", null, "默认消息", LocaleContextHolder.getLocale()) ; } }
Locale从当前线程上下文中获取。该Locale是在DispatcherServlet中初始化的。
在接口调用时,我们只需要指定Access-Language header
图片
Spring为我们提供了一个便捷的类,可以更方便的访问消息源,项目中只需要注册如下bean:
@Beanpublic MessageSourceAccessor messageSourceAccessor(MessageSource messageSource) { MessageSourceAccessor accessor = new MessageSourceAccessor(messageSource) ; return accessor ;}
访问
@Resourceprivate 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.28at.com/showinfo-26-57390-0.htmlSpring国际化的应用及原理详解
声明:本网页内容旨在传播知识,不代表本站观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。