MessageFormat.format 是 Java 多语言动态填充核心工具,支持语序切换、复数、日期数字格式化;需用 {0} 等位置索引占位符,严格匹配参数顺序,并结合 ResourceBundle 按 Locale 加载对应 properties 模板。

MessageFormat.format 是 Java 中专为多语言消息动态填充设计的核心工具,它不只替换变量,更支持语序切换、复数规则、日期数字格式化等国际化刚需能力。关键在于:占位符用 {n}(从 0 开始),配合 ResourceBundle 加载对应语言的模板,才能真正实现“一套逻辑、多套语言”。
占位符写法与参数顺序必须严格匹配
MessageFormat 使用位置索引({0}、{1}…)而非命名,参数数组顺序决定填入内容:
- 模板字符串中写
user.login.fail={0} 在 {1} 登录失败,调用时必须按顺序传入用户名和时间:MessageFormat.format(pattern, "zhangsan", "2026-05-10") - 不能写成
{1} 在 {0} 登录失败却仍按原顺序传参,否则语义错乱 - 索引仅支持 0–9,超过需拆分或改用其他方案(如 String.format + 多语言资源分离)
结合 ResourceBundle 实现语言自动切换
把带占位符的模板存进不同 locale 的 properties 文件,运行时由 Locale 决定加载哪一份:
-
messages_zh_CN.properties:order.cancel=订单 {0} 已取消,原因:{1} -
messages_en_US.properties:order.cancel=Order {0} has been cancelled. Reason: {1} - Java 中通过
ResourceBundle.getBundle("messages", locale)获取对应 bundle,再rb.getString("order.cancel")拿到模板 - Locale 可来自请求头
Accept-Language、用户设置或线程上下文,无需硬编码语言分支
支持高级格式化:日期、数字、复数(需手动扩展)
MessageFormat 原生支持类型化格式控制,提升可读性与本地习惯适配度:
- 日期:
{1,date,yyyy-MM-dd HH:mm}→ 自动按 locale 格式化时间 - 货币:
{2,number,currency}→ 显示 ¥123.00 或 $123.00 - 复数(简单版):
{0,plural,one{1 条消息}other{# 条消息}},注意 Java 原生 MessageFormat 不直接支持 ICU 风格复数语法,需搭配ChoiceFormat或引入icu4j库
封装成工具方法,避免重复样板代码
每次手动查 ResourceBundle + 调用 MessageFormat 容易出错且冗余,建议统一封装:
- 提供静态入口,如
I18nUtil.msg("user.notfound", userId) - 内部自动获取当前线程绑定的 Locale(如 Spring 的
LocaleContextHolder.getLocale()) - 加载资源、取模板、填充参数、捕获异常(如 MissingResourceException 或 IllegalArgumentException)并友好提示
- 返回已格式化的字符串,供异常抛出、日志记录或前端响应直接使用

















