飞道的博客

SpringBoot国际化

422人阅读  评论(0)


软件的国际化

软件的国际化:软件开发时,要使它能同时应对世界不同地区和国家的访问,并针对不同地区和国家的访问,提供相应的、符合来访者阅读习惯的页面或数据。国际化internationalization,在i和n之间有 18 个字母,所以叫i18n

MessageSource组件

Spring定义了 MessageSource 接口,用于访问国际化信息。

getMessage(String code, Object[] args, String defaultMessage, Locale locale)

getMessage(String code, Object[] args, Locale locale)

getMessage(MessageSourceResolvable resolvable, Locale locale)

属性

说明

code

国际化资源中的属性名

args

传递格式化串占位符所用的运行期参数,当在资源找不到对应属性名时,会返回defaultMessage参数所指定的默认信息

locale

表示本地化对象

resolvable

封装了属性名、参数数组以及默认信息的大类

其内部实现(MessageSource 是如何从 properties 文件中读取国际化的值的?),大致看了一下源码并进行了调试,最终了解到它是将 properties文件中的msgKey、value都load到了一个lookup的HashMap中(第一次加载时会缓存起来,后面直接走的缓存,有兴趣的同学可以在 PropertyResourceBundle.java:157 中寻找答案),得到 msgKey -> value,外层还有一个 locale 做索引,即 locale -> (msgKey -> value),最后是通过 locale + msgKey 得到相应的 value 。

最终,一个 properties 文件对应于一个 PropertyResourceBundle 对象。

Spring区域信息解析器

spring 支持获取请求头Accept-Language区域信息解析器。

不需重写。只需要Http请求头中带有Accept-Language就可以实现国际化语言支持。

其他文章多次提到自定义编写此部分,大家一定要避免此坑。

关于Accept-Language如下

Accept-Language

Accept-Language:表示浏览器所支持的语言。

当我们在开发国际化的网站时,后端接口的信息需要根据用户所使用的语言返回对应的内容。作为后端我需要前端在请求头的Accept-Language属性声明需要返回的语言。

格式

Accept-Language: lange-range[weight]

示例

  • Accept-Language: zh-cn,zh;q=0.5

意思: 支持的语言分别是简体中文和中文,优先支持简体中文。

zh-cn:表示简体中文,zh:表示中文(包括简体中文,繁体中文)

  • Accept-Language: zh-CN,zh;q=0.9,en;q=0.8

意思:优先支持中文,如果没有中文则支持英文。

q:表示他之前语言的权重, 0 <= q <= 1

  • Accept-Language: zh-cn;q=0.8,en-US;q=0.9

意思:优先支持英文,如果没有英文则支持中文。

  • Accept-Language: zh-cn;q=0.8,en-US;q=0.6

意思:优先支持中文,如果没有中文则支持英文。

  • **Accept-Language: ***

意思: 支持所有语言

配置国际化资源文件

在application.yml中指定资源文件配置


   
  1. spring:
  2.  messages:
  3. basename: i18n/messages
  4. encoding: UTF-8

然后在resource下创建i18n目录,然后在其下创建文件

messages.properties不带后缀为默认语言资源

可以按照一定规则分类编写,后期会很多信息。


   
  1. # 参数校验信息
  2. validation.UserVo.NAME_NOT_EMPTY=姓名不能为空
  3. validation.UserVo.AGE_NOT_EMPTY=年龄不能为空
  4. # 异常信息
  5. exception.userBizException .10000 = 用户保存异常
  6. # 断言校验信息
  7. assert.userService.CHECK_ITEM_KEY = 姓名[{ 0}]已经存在,请勿重复创建

支持占位符参数。

国际化工具类


   
  1. import org.springframework.context.MessageSource;
  2. import org.springframework.context.i18n.LocaleContextHolder;
  3. import org.springframework.stereotype.Component;
  4. /**
  5. * 国际化工具类
  6. * @Author : xiayi
  7. * @Date: 2023-01-31 14:59
  8. */
  9. @Component
  10. public class I18nUtil {
  11. public static MessageSource messageSource;
  12. public I18nUtil (MessageSource messageSource) {
  13. // spring的bean注入
  14. I18nUtil.messageSource = messageSource;
  15. }
  16. /**
  17. * 获取国际化翻译值
  18. */
  19. public static String get (String msgKey) {
  20. return messageSource.getMessage(msgKey, null, LocaleContextHolder.getLocale());
  21. }
  22. /**
  23. * 获取国际化翻译值(包括占位符)
  24. */
  25. public static String get (String msgKey, Object... args) {
  26. return messageSource.getMessage(msgKey, args, LocaleContextHolder.getLocale());
  27. }
  28. }

使用方式:

I18nUtil.get("assert.userService.CHECK_ITEM_KEY",user.getName())

Validation国际化

Spring Boot Validation支持JSR-380(aka. Bean Validation 2.0,part of Jakarta EE and JavaSE)注解,可通过验证注解的message属性设置验证错误提示信息,且每个验证注解都有默认的message配置,例如@NotEmpty的message属性值设置如下图:


   
  1.     /**
  2. * 名称
  3. */
  4. @NotEmpty(message = "{validation.DictSaveVO.name.NAME_NOT_EMPTY}")
  5. private String name;

注意:

默认的message = "{...}"的形式即指定国际化属性的名称,后续会根据语言环境替换为对应的值,而这些国际化属性的定义可参见hibernate-validator中的org.hibernate.validator.ValidationMessages.properties等一些列国际化属性定义:

Spring Boot Validation起初其并不直接支持读取Spring Boot自身的国际化配置(通过spring.messages进行配置),而是需要在resources/ValidationMessages.properties中进行配置的国际化属性才会生效,而后续在Spring Boot 2.6+版本才支持Validation与Spring Boot自身的国际化配置相结合。接下来结合Spring Boot 2.5和2.6版本分别介绍下Spring Boot Validation如何集成自定义国际化验证提示信息。

在Spring Boot 2.5.x版本中,Spring Boot Validation默认只支持读取resources/ValidationMessages.properties系列文件的中的国际化属性,且中文需要进行ASCII转码才可正确显示而就算Spring Boot应用亦声明了自身的国际化配置,但是Spring Boot Validation框架是读取不到的,而想要Spring Boot Validation框架和Spring Boot自身使用同样的国际化配置,则可通过如下方式进行配置:


   
  1. import org.springframework.context.MessageSource;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.validation.Validator;
  5. import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
  6. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  7. /**
  8. * Spring Web验证器自定义国际化文件配置<br/>
  9. * 注:适用于Spring Boot 2.5.*
  10. *
  11. */
  12. @Configuration
  13. public class WebValidationConfig implements WebMvcConfigurer {
  14. /**
  15. * 国际化消息源
  16. */
  17. private MessageSource messageSource;
  18. public WebValidationConfig (MessageSource messageSource) {
  19. //注入Spring Boot国际化消息源(需通过spring.messages明确指定)
  20. this.messageSource = messageSource;
  21. }
  22. /**
  23. * 使用自定义LocalValidatorFactoryBean,
  24. * 设置Spring国际化消息源
  25. */
  26. @Bean
  27. @Override
  28. public Validator getValidator () {
  29. LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
  30. //仅兼容Spring Boot spring.messages设置的国际化文件和原hibernate-validator的国际化文件
  31. //不支持resource/ValidationMessages.properties系列
  32. bean.setValidationMessageSource( this.messageSource);
  33. return bean;
  34. }
  35. }

Spring Boot 2.6.x版本之后已支持验证注解message属性引用Spring Boot自身国际化配置,无需上面自定义配置。

SpringBoot2.7.6已设置ApplicationContext实现MessageSource

避坑:

使用原始validator校验,不要自定义注解来实现拦截,否则无法国际化。

参考:

https://blog.csdn.net/u013565163/article/details/104262975

https://blog.csdn.net/GAOXINXINGgaoxinxing/article/details/92642470

https://blog.csdn.net/haihui_yang/article/details/83987839

https://blog.csdn.net/qq_42315935/article/details/125337214

https://blog.csdn.net/luo15242208310/article/details/124897389


转载:https://blog.csdn.net/star20100906/article/details/128831095
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场