小工具知识网

当前位置: 首页 > 行业知识 > SpringBoot国际化配置流程(超详细)

行业知识

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

2026-11-05 20:48:09 来源:互联网转载

前言

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

SpringBoot国际化

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

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

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

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

准备环境

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

SpringBoot 3.0.6、IDEA社区版2023.1、OpenJDK 17

引入依赖

  org.springframework.boot  >spring-boot-starter-web  3.0.6    org.springframework.boot    >spring-boot-starter-validation    3.0.6

自定义配置

@AutoConfigureBefore(WebMvcAutoConfiguration.class)public class LocaleConfig {    /**     * 国际化消息源     */    @Resource    private MessageSource messageSource;    /**     * 区域解析器,供消息源@MessageSource根据不同的区域@java.util.Locale读取不同的properties文件     *     * @return {@code LocaleResolver}     */    @Bean    public LocaleResolver localeResolver() {        AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();        // 设置默认区域:简体中文        localeResolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);        return localeResolver;    }    /**     * 使用自定义LocalValidatorFactoryBean,     * 设置Spring国际化消息源,用户jsr303验证信息实现自定义国际化     *     */    @Bean    public 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/messages    fallback-to-system-locale: false

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

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

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

国际化消息工具类

@Slf4j@Componentpublic class LocaleUtil implements ApplicationContextAware {    private static MessageSource messageSource;    @Override    public 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来使用。

国际化使用

异常提示国际化

在业务代码中,业务异常我们通常是抛出异常,由统一异常处理来根据异常code和message封装成统一的返回对象,国际化这里我们也是一样,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.propertiesi18n.user.check.username.err=用户名校验不通过## messages_en_US.propertiesi18n.user.check.username.err=The username does not comply with regulations## messages_zh_CN.propertiesi18n.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;@Datapublic class TestReq {    @NotEmpty    private 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

上一篇:杰奇小说,一键轻松搜索指南!

下一篇:STM32 FSMC/FMC原理保姆级讲解(一)