Spring 国际化遇到的坑org.springframework.context.NoSuchMessageException: No message found under code ‘xxx.xxxx’ for locale ‘zh_CN’

背景

以前做的项目客户群体只有国内的客户,从来没有考虑过语言文字的问题。
这次有一个需求的返回内容,要根据客户设置的语言返回不同的语言。
尝试使用了以后,结果发现怎么都不好使,一直报的一个错误如下:

org.springframework.context.NoSuchMessageException: No message found under code 'user.name' for locale 'zh_CN'.at org.springframework.context.support.DelegatingMessageSource.getMessage(DelegatingMessageSource.java:76) ~[spring-context-5.3.23.jar:5.3.23]

详细用法

至于i18n具体用法就不详细说明了,网上也很多,这里推荐一个我感觉写的挺好的一篇。
大佬链接

错误原因

我出现这个错误主要是两个原因:

1、没有创建messages.properties文件。

我只创建了messages_en_US.propertiesmessages_zh_CN.properties两个文件。
messages.properties 这个是默认的配置,其他的则是不同语言环境下的配置。这个文件一定不能少。

2、自定义文件目录配置错误,配置中没有写文件名前缀messages

我解决完第一个问题后,还有一个问题就是,我把这些语言文件放到默认目录/resources目录下是好使的,可以根据报文头中的语言信息(或参数信息)返回不同语言的文本。
但是一旦我自定义文件位置,就又出现文章开头的错误。
搞了很久才发现(如果想debug源码,可参考这篇文章),
如果你的语言资源文件目录如下图:

那么,你的配置仅仅是这样不对的(如下错误示例):

spring.messages.basename=static/i18nspring.messages.encoding=UTF-8

正确的配置应该是这样的(如下正确示例):

spring.messages.basename=static/i18n/messagesspring.messages.encoding=UTF-8

中间用.分割也可以,spring会将.替换成/(如下正确示例)

spring.messages.basename=static.i18n.messagesspring.messages.encoding=UTF-8

spring.messages.basename的值不仅仅是目录,还包括文件的前缀

最后来一张完整的图和结果

controller部分代码

package com.example.i18n.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.MessageSource;import org.springframework.context.i18n.LocaleContextHolder;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class HelloController {@AutowiredMessageSource messageSource;@GetMapping("/hello")public String hello() {return messageSource.getMessage("user.name", null, LocaleContextHolder.getLocale());}}

zh_CN结果

en_US结果