SpringBoot国际化配置流程(超详细)

前言

最新第一次在做SpringBoot的国际化,网上搜了很多相关的资料,都是一些简单的使用例子,达不到在实际项目中使用的要求,因此本次将结合查询的资料以及自己的实践整理出SpringBoot配置国际化的流程。

SpringBoot国际化

"i18n"是国际化(internationalization)的缩写,数字18代表了国际化这个单词中间的字母数量。类似这样的缩写还有k8s(kubernetes)等

Spring Boot国际化是指在Spring Boot应用中实现多语言支持的功能。通过国际化,应用可以根据用户的语言偏好自动切换显示的语言版本,从而提供贴近用户的界面和文本信息。

SpringBoot官方国际化支持文档:7.5. Internationalization(请点击我)

由于SpringBoot默认集成国际化,因此本次实践也是基于SpringBoot的自动配置来进行。

准备环境

本次实践我使用的环境或工具版本如下:

SpringBoot 3.0.6IDEA社区版2023.1OpenJDK 17

引入依赖

<!-- web中提供国际化支持 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>3.0.6</version>
</dependency>
<!-- 参数校验 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId><version>3.0.6</version>
</dependency>

自定义配置

@AutoConfigureBefore(WebMvcAutoConfiguration.class)
public class LocaleConfig {/*** 国际化消息源*/@Resourceprivate MessageSource messageSource;/*** 区域解析器,供消息源@MessageSource根据不同的区域@java.util.Locale读取不同的properties文件** @return {@code LocaleResolver}*/@Beanpublic LocaleResolver localeResolver() {AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();// 设置默认区域:简体中文localeResolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);return localeResolver;}/*** 使用自定义LocalValidatorFactoryBean,* 设置Spring国际化消息源,用户jsr303验证信息实现自定义国际化**/@Beanpublic Validator getValidator() {LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();bean.setValidationMessageSource(messageSource);return bean;}
}

java.util.Locale: Locale对象表示特定的地理、政治或文化区域,用以区分区域。

org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver:通过请求头Accept-Language的值(zh-CN、en-US等)来改变当前的区域设置

org.springframework.context.MessageSource:用于解析消息的策略接口,支持此类消息的参数化和国际化。根据Locale区域读取不同的properties国际化文件

@AutoConfigureBefore(WebMvcAutoConfiguration.class):由于WebMvcAutoConfiguration会注入一个默认的LocaleResolver,因此自定义的LocaleConfig要在WebMvcAutoConfiguration之前先执行,且beanName是localeResolver,目的就是用我们配置的LocaleConfig替换掉WebMvcAutoConfiguration自动注入的LocaleConfig

以下代码片段是WebMvcAutoConfiguration自动注入LocaleResolver 的方法

/**
* DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME的值就是"localeResolver"
*/
@Override
@Bean
@ConditionalOnMissingBean(name = DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME)
public LocaleResolver localeResolver() {if (this.webProperties.getLocaleResolver() == WebProperties.LocaleResolver.FIXED) {return new FixedLocaleResolver(this.webProperties.getLocale());}AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();localeResolver.setDefaultLocale(this.webProperties.getLocale());return localeResolver;
}

国际化文件

在工程resources目录下新建目录i18n,在i18n目录下新建三个国际化文件:
messages.properties
messages_en_US.properties
messages_zh_CN.properties

zh-CN:简体中文
en-US:英语

在这里插入图片描述

在不配置默认的区域情况下,当没有找到匹配的语言文件时,会读取默认的messages.properties

如何快速编辑资源包.properties文件

配置application.yml

spring:## note: ---------------- 国际化配置 ----------------messages:basename: i18n/messagesfallback-to-system-locale: false

basename:基名,多个基名以逗号分隔(实质上是完全限定的类路径位置),每个基名都遵循 ResourceBundle 约定,对基于斜杠的位置提供了宽松的支持。如果它不包含包限定符(例如“org.mypackage”),则将从类路径根目录解析它。

基名可以理解为前缀,默认是从classpath根路径下找,配置的路径可以用斜杠/,也可以用.,即i18n/messagesi18n.messages,然后messages就是国际化文件的前缀,messages.properties就是默认国际化文件。

fallback-to-system-locale:如果未找到特定区域设置的文件,是否回退到系统区域设置。如果关闭此功能,则唯一的回退将是默认文件。就是我想要的区域语言文件没有的时候,就从系统中解析系统的区域,以系统的区域再找一次文件,找到就返回系统区域文件,如果找不到,就返回默认的文件。

国际化消息工具类

@Slf4j
@Component
public class LocaleUtil implements ApplicationContextAware {private static MessageSource messageSource;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {LocaleUtil.messageSource = applicationContext.getBean(MessageSource.class);}/*** 获取国际化message** @param code           code* @param args           占位参数* @param defaultMessage 默认值* @return 国际化文本*/public static String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage) {return messageSource.getMessage(code, args, defaultMessage, LocaleContextHolder.getLocale());}/*** 获取国际化message** @param code           code* @param args           占位参数* @param defaultMessage 默认值* @param locale         地区* @return 国际化文本*/public static String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale) {return messageSource.getMessage(code, args, defaultMessage, locale);}/*** 获取国际化message** @param code           code* @param defaultMessage 默认值* @return 国际化文本*/public static String getMessage(String code, @Nullable String defaultMessage) {return messageSource.getMessage(code, null, defaultMessage, LocaleContextHolder.getLocale());}

封装国际化文本的读取接口,主要方便在代码中使用,不需要每次@Autowired注入MessageSource来使用。

国际化使用

异常提示国际化

在业务代码中,业务异常我们通常是抛出异常,由统一异常处理来根据异常codemessage封装成统一的返回对象,国际化这里我们也是一样,code不变,message改成国际化消息的key

  • 定义业务异常对象
public class BussinessException extends RuntimeException {private String code;public BussinessException (String code, String message) {super(message);this.code= code;}
}
  • 定义异常类型枚举
public enum ErrorCodeEnum {DEMO_ERROR(99999, "i18n.user.check.username.err");/*** 提示*/private final String message;/*** 状态吗*/private final String code;ErrorCodeEnum (String code, String message) {this.code = code;this.message = message;}/*** 获取国际化错误提示** @return 错误提示文本*/public String getMessage() {return LocaleUtil.getMessage(message, message);}/*** 获取国际化错误提示** @param args 错误提示参数* @return 错误提示文本*/public String getMessage(Object[] args) {return LocaleUtil.getMessage(message, args, message);}/*** 获取错误code** @return 错误code*/public Integer getCode() {return code;}
}
  • 国际化文件配置

在国际化文件都配置上i18n.user.check.username.err不同语言的翻译

## messages.properties
i18n.user.check.username.err=用户名校验不通过## messages_en_US.properties
i18n.user.check.username.err=The username does not comply with regulations## messages_zh_CN.properties
i18n.user.check.username.err=用户名不符合规范

在这里插入图片描述

  • 业务逻辑校验(使用场景之一)
   /*** 校验用户名是否符合规范** @param userName 用户名* @return {@code String}*/public String checkUserName(String userName) {if (StringUtils.isBlank(userName)) {throw new BussinessException(ErrorCodeEnum.DEMO_ERROR.getCode(), ErrorCodeEnum.DEMO_ERROR.getMessage());}// check logic code ...return userName;}

参数校验国际化

SpringBoot项目我们在做参数校验通常会使用JSR303、jakarta.validation参数校验快速失败。

import jakarta.validation.constraints.NotEmpty;
import lombok.Data;@Data
public class TestReq {@NotEmptyprivate String userName;
}

我这里是导入开头的spring-boot-starter-validation依赖就可以使用hibernate-validator给我们提供的常用校验注解的国际化。
在这里插入图片描述

查看@NotEmpty注解源码,message默认就读国际化文件里jakarta.validation.constraints.NotEmpty.message

@Documented
@Constraint(validatedBy = { })
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Repeatable(List.class)
public @interface NotEmpty {String message() default "{jakarta.validation.constraints.NotEmpty.message}";Class<?>[] groups() default { };Class<? extends Payload>[] payload() default { };/*** Defines several {@code @NotEmpty} constraints on the same element.** @see NotEmpty*/@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })@Retention(RUNTIME)@Documentedpublic @interface List {NotEmpty[] value();}
}

这里就贴ValidationMessages.propertiesjakarta.validation.constraints.NotEmpty.message,其他文件大家自行查看。

jakarta.validation.constraints.NotEmpty.message        = must not be empty

自定义校验错误提示信息

当我们不想使用hibernate-validator给我们提供的默认提示信息时,我们可以自定义自己的错误提示信息。这里就复用前面配置的i18n.user.check.username.err

@Data
public class TestReq {@NotEmpty(message = "{i18n.user.check.username.err}")private String userName;
}

如此,在Accept-Language=en-US即我想返回的信息是英文,参数校验不通过时,提示的不是must not be empty,而是我们自定义的The username does not comply with regulations

结语

时间有限,国际化的实践流程截图没提供,大家根据文中的操作步骤也可以完成国际化的demo,后续有时间再完善,大家也期待下一篇的源码解读吧。

文中如有描述不清楚、读者不理解意思的地方,大家评论区打出,我来完善哈。

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

猫,路由器,WIFI

家庭网络常识 1&#xff1a;猫、路由器、wifi_哔哩哔哩_bilibili 入户光纤插到猫上面&#xff0c;网线连接猫和路由器&#xff0c;网线连接路由器和电脑。路由器可以发射WIFI。 手机通过WIFI连接到路由器。 左边是猫&#xff0c;右边是光猫。 &#xff08;modem&#xff09; …

JAVA面试八股文之集合

JAVA集合相关 集合&#xff1f;说一说Java提供的常见集合&#xff1f;hashmap的key可以为null嘛&#xff1f;hashMap线程是否安全, 如果不安全, 如何解决&#xff1f;HashSet和TreeSet&#xff1f;ArrayList底层是如何实现的&#xff1f;ArrayList listnew ArrayList(10)中的li…

《QT实用小工具·一》电池电量组件

1、概述 项目源码放在文章末尾 本项目实现了一个电池电量控件&#xff0c;包含如下功能&#xff1a; 可设置电池电量&#xff0c;动态切换电池电量变化。可设置电池电量警戒值。可设置电池电量正常颜色和报警颜色。可设置边框渐变颜色。可设置电量变化时每次移动的步长。可设置…

淘宝订单中的涉及红包检测、优惠券检测方案|工具|API

首先&#xff0c;检测订单红包的核心价值是什么&#xff1f; “红包的本质就是薅平台羊毛&#xff1a;不用怀疑&#xff0c;平台对于这种损害平台利益的行为肯定是最高等级的稽查”。那么&#xff0c;在日常运营中&#xff0c;需要尽可能过滤这类订单。 其次&#xff0c;如何使…

堆的应用(堆排序,TOP-K问题)详细讲解

所有人都关心我飞的高不高&#xff0c;只有我妈关心我翅膀硬不硬 一、堆的应用 1. 堆排序 1.1 建堆 1.2 利用堆删除思想来进行排序 2.TOP-K问题 二、完结撒❀ –❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀-正文开始-❀–❀–❀–❀–❀–❀–❀–❀–…

斜率优化dp 笔记

任务安排1 有 N 个任务排成一个序列在一台机器上等待执行&#xff0c;它们的顺序不得改变。 机器会把这 N 个任务分成若干批&#xff0c;每一批包含连续的若干个任务。 从时刻 00 开始&#xff0c;任务被分批加工&#xff0c;执行第 i 个任务所需的时间是 Ti。 另外&#x…

【LVGL-字库应用】

LVGL-中文字库应用 ■ LVGL-内部字库■ LVGL 内部字库的使用流程&#xff1a; ■ LVGL-自定义字库■ 方法一&#xff1a;C 语言数组&#xff08;内部读取&#xff09;-在线转换工具■ 方法二&#xff1a;C 语言数组&#xff08;内部读取&#xff09;-利用离线字体转换软件&…

销售的业绩和合同无法统一管理可以通过系统实现吗?

这个问题我们在日常管理中也遇到过&#xff0c;在没有使用软件之前&#xff0c;合同原件没有专人负责打理&#xff0c;销售人员签了合同后&#xff0c;直接把原件随手放在柜子里&#xff0c;或者把数据记录到excel表中。 但是每个人的工作习惯不一样&#xff0c;记录的表格也不…

Spring boot 发送文本邮件 和 html模板邮件

Spring boot 发送文本邮件 和 html模板邮件 提示&#xff1a;这里使用 spring-boot-starter-mail 发送文本邮件 和 html模板邮件 文章目录 Spring boot 发送文本邮件 和 html模板邮件一、开启QQ邮箱里的POP3/SMTP服务①&#xff1a;开启步骤 二、简单配置①&#xff1a;引入依赖…

Linux系统使用Docker部署MinIO结合内网穿透实现公网访问本地存储服务

文章目录 前言1. Docker 部署MinIO2. 本地访问MinIO3. Linux安装Cpolar4. 配置MinIO公网地址5. 远程访问MinIO管理界面6. 固定MinIO公网地址 前言 MinIO是一个开源的对象存储服务器&#xff0c;可以在各种环境中运行&#xff0c;例如本地、Docker容器、Kubernetes集群等。它兼…

①胃癌单细胞和配对转录组揭示胃肿瘤微环境(文献和数据)

目录 文献内容 胃癌细胞微环境格局 肿瘤基质的特征存在活化的成纤维细胞 肿瘤内皮细胞与血管生成途径 巨噬细胞显示炎症二分法 淋巴细胞转向免疫抑制和分化表型 细胞通信网络揭示了胃癌发展的潜在驱动因素 胃癌免疫治疗批量RNA-seq的整合揭示了细胞和分子的反应倾向 数…

Web漏洞-深入WAF注入绕过

目录 简要其他测试绕过 方式一:白名单&#xff08;实战中意义不大&#xff09; 方式二:静态资源 方式三: url白名单 方式四:爬虫白名单 #阿里云盾防SQL注入简要分析 #安全狗云盾SQL注入插件脚本编写 在攻防实战中&#xff0c;往往需要掌握一些特性&#xff0c;比如服务…

Zabbix6 - Centos7源码编译部署HA高可用集群手册

Zabbix6 - Centos7源码编译部署HA高可用集群手册 HA高可用集群 总所周知,在我们IT运维的圈圈中,HA高可用集群服务算是逼格最高的吧也是运维里保障力度最大的环境。 HA是HighlyAvailable缩写,是双机集群系统简称,提高可用性集群,是保证业务连续性的有效解决方案,一般有两个…

6款好用的AI写作助手,为大家解决创作困难

写作出高质量的文章对于每个创作者来说是非常重要&#xff0c;但有时候在面对繁重的写作任务时&#xff0c;大家可能会陷入创作困境&#xff0c;思绪纷乱、灵感枯竭。&#xff0c;但随着人工智能技术的不断发展&#xff0c;AI写作助手已经成为了许多创作者的得力帮手&#xff0…

Java代码混淆技术在应用程序保护中的关键作用与应用

摘要 本文探讨了代码混淆在保护Java代码安全性和知识产权方面的重要意义。通过混淆技术&#xff0c;可以有效防止代码被反编译、逆向工程或恶意篡改&#xff0c;提高代码的安全性。常见的Java代码混淆工具如IPAGuard、Allatori、DashO、Zelix KlassMaster和yGuard等&#xff0…

Acwing_795前缀和 【一维前缀和】+【模板】二维前缀和

Acwing_795前缀和 【一维前缀和】 题目&#xff1a; 代码&#xff1a; #include <bits/stdc.h> #define int long long #define INF 0X3f3f3f3f #define endl \n using namespace std; const int N 100010; int arr[N];int n,m; int l,r; signed main(){std::ios::s…

OpenHarmony实战开发-Web组件的使用

介绍 本篇Codelab使用ArkTS语言实现一个简单的免登录过程&#xff0c;向大家介绍基本的cookie管理操作。主要包含以下功能&#xff1a; 获取指定url对应的cookie的值。设置cookie。清除所有cookie。免登录访问账户中心。 原理说明 本应用旨在说明Web组件中cookie的管理操作。…

Siemens S7-1500TCPU 运动机构系统功能简介

目录 引言&#xff1a; 1.0 术语定义 2.0 基本知识 2.1 运动系统工艺对象 2.2 坐标系与标架 3.0 运动机构系统类型 3.1 直角坐标型 3.2 轮腿型 3.3 平面关节型 3.4 关节型 3.5 并联型 3.6 圆柱坐标型 3.7 三轴型 4.0 运动系统的运动 4.1 运动类型 4.1.1 线性运动…

OpenHarmony中的LLDB高性能调试器

概述 LLDB&#xff08;Low Lever Debugger&#xff09;是新一代高性能调试器。详细说明参考 LLDB官方文档 。 当前OpenHarmony中的LLDB工具是在 llvm15.0.4 基础上适配演进出来的工具&#xff0c;是HUAWEI DevEco Studio工具中默认的调试器&#xff0c;支持调试C和C应用。 工…

C++ Primer (第五版)第七章习题部分答案(上)

在我自学C过程中&#xff0c;我选择了CPrimer这本书&#xff0c;并对部分代码习题进行了求解以及运行结果。接下来几个月我将为大家定时按章节更新习题答案与运行结果&#xff0c;运行环境&#xff08;Visual Studio Code&#xff0c;windows 11&#xff09;&#xff1a; C P…