locale对象仅是语言地区标识,需显式传给resourcebundle、dateformat等api才生效;文件命名须严格匹配zh_cn格式,语言代码小写、国家代码大写,否则静默回退。

Java 的 Locale 类本身不提供翻译或资源加载能力,它只是标识“用哪种语言、在哪个地区”,真正实现国际化要靠 ResourceBundle、DateFormat、NumberFormat 等配合使用。
为什么 new Locale("zh", "CN") 有时不生效?
常见误区是以为构造出 Locale 对象就自动切换了语言。实际它只是个“标签”,必须显式传给支持 locale 的 API 才起作用:
-
ResourceBundle.getBundle("messages", locale)—— 加载对应messages_zh_CN.properties -
NumberFormat.getInstance(locale)—— 控制数字分组符(如 1,000.00 vs 1.000,00) -
DateFormat.getDateInstance(DateFormat.LONG, locale)—— 影响日期格式(如 “2024年5月6日” vs “May 6, 2024”) - 直接调用
Locale.getDefault()并修改它(比如Locale.setDefault(new Locale("ja")))会影响全局,但不推荐——线程不安全,且对 Web 应用无效
如何正确加载多语言 properties 文件?
文件命名必须严格匹配 Locale 的语言+国家(可选)组合,否则 ResourceBundle 找不到:
- 基础文件:
messages.properties(默认,无 locale 匹配时回退) - 中文简体:
messages_zh_CN.properties→ 对应new Locale("zh", "CN") - 英文美国:
messages_en_US.properties→ 对应new Locale("en", "US") - 注意:不是
zh-CN或zh_CN_#Hans,下划线是分隔符,不能用短横或井号 - 如果只写
new Locale("zh"),会尝试找messages_zh.properties;没找到就回退到默认文件
Web 应用中怎么获取用户真实 Locale?
Servlet 容器(如 Tomcat)会从 HTTP 请求头 Accept-Language 解析出客户端首选语言,但需手动提取,不能依赖 Locale.getDefault():
立即学习“Java免费学习笔记(深入)”;
-
request.getLocale()返回最匹配的单个Locale(已解析并按权重排序) -
request.getLocales()返回Enumeration<locale></locale>,含所有候选 locale(按浏览器顺序) - Spring MVC 中可用
@RequestHeader("Accept-Language") String lang手动解析,或配置AcceptHeaderLocaleResolver - 注意:某些代理或 CDN 可能剥离该 header,导致返回
en_US或空 —— 建议前端通过 URL 参数(如?lang=ja_JP)或 Cookie 补充兜底
最容易被忽略的是:locale 的语言代码必须用 ISO 639-1(两位小写),国家代码用 ISO 3166-1 alpha-2(两位大写),大小写错一位(比如 "ZH_CN")就会导致 ResourceBundle 加载失败且静默回退到默认,很难排查。










