解决Spring MessageSource获取消息不符合预期的问题

前言

最近我参与的产品要做国际化支持,选择了用Spring MessageSource来实现,这个Spring 框架提供的工具使用很简单,网上有各种教程文章,这里不做赘述,只说一个实际遇到的问题及解决方案。

场景

  1. 项目需要支持中、英文,所以在 spring boot 项目 resources 目录下创建两个消息配置文件 messages.propertiesmessages_en.properties 分别对应中文和英文消息。
  2. 项目中使用以下代码获取对应语种的消息(通过code)
java 复制代码
@Component
@RequiredArgsConstructor
public class LocalizationUtils {

    private final MessageSource messageSource;

    public String getLocalizedMessageFromCode(String code) {
        // 语种信息由请求通过请求头携带,例如英文为en_us
        final Locale locale = new Locale(language);
        return messageSource.getMessage(code, null, locale);
    }

}
  1. 项目打包为docker镜像,部署到了K8S集群上,关键信息是:构建docker镜像的基础镜像的默认语言是英文

问题

当浏览器请求接口,携带请求头信息为zh(期望获取中文消息时),通过上面的工具类方法始终获取到的是英文消息,不符合预期!

Spring 的 MessageSource 的工作方式

MessageSource在查找消息时,会首先尝试使用与当前Locale完全匹配的消息文件。如果没有找到完全匹配的文件,它会逐步回退到更通用的语言设置,最后回退到默认的messages.properties文件。

  1. 我创建了一个新的Locale对象,其语言设置为zh。然而,我的项目中没有一个名为messages_zh.properties的文件,那么MessageSource将无法找到与zh完全匹配的消息文件。在这种情况下,它会回退到默认的messages.properties文件。
  2. 我的产品构建成docker镜像,实际运行在docker中,构建docker镜像的基础镜像的默认语言设置是英文。MessageSource在回退到默认消息文件之前,会尝试使用与操作系统语言设置匹配的消息文件。 在我的项目中对应的就是 messages_en.properties
  3. 最后才会根据默认消息配置文件messages.properties返回消息。
  4. 另外,new Locale(language)方法创建Locale时,参数language大小写 会影响结果,所以最好把language参数转换成小写,然后调用该方法。

解决办法

  1. Dockerfile 中添加行设置默认语言为中文,根据上面提到的机制,先找完全匹配的messages_zh.properties,然后尝试使用与操作系统语言设置匹配的消息文件messages_zh.properties,因为这个消息文件不存在,所以使用messages.properties

    ENV LANG zh_CN.UTF-8

  2. 设置应用程序的默认语言为中文,在启动类中添加一行代码

typescript 复制代码
@SpringBootApplication
public class AppApplication {

    public static void main(String[] args) {
        // 设置默认语言为中文
        Locale.setDefault(new Locale("zh"));
        SpringApplication.run(AppApplication.class, args);
    }

}
  1. 在resources目录下新建messages_zh.properties消息文件。

附录

Locale对象在Java中用于表示特定的地理、政治或文化区域。在创建Locale对象时,我们通常会传入一个语言代码,这个代码通常是一个ISO 639 alpha-2alpha-3语言代码。 以下是一些常见的语言代码和对应的语言:

  • "en" - 英语
  • "zh" - 中文
  • "fr" - 法语
  • "de" - 德语
  • "ja" - 日语
  • "ko" - 韩语
  • "ru" - 俄语
  • "es" - 西班牙语
相关推荐
想用offer打牌2 小时前
MCP (Model Context Protocol) 技术理解 - 第二篇
后端·aigc·mcp
KYGALYX3 小时前
服务异步通信
开发语言·后端·微服务·ruby
掘了3 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
爬山算法4 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
猫头虎4 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven
Moment4 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
Cobyte5 小时前
AI全栈实战:使用 Python+LangChain+Vue3 构建一个 LLM 聊天应用
前端·后端·aigc
程序员侠客行6 小时前
Mybatis连接池实现及池化模式
java·后端·架构·mybatis
Honmaple6 小时前
QMD (Quarto Markdown) 搭建与使用指南
后端
MZ_ZXD0016 小时前
springboot旅游信息管理系统-计算机毕业设计源码21675
java·c++·vue.js·spring boot·python·django·php