← 首页 / MessageFormat 2 · 给人看的消息怎么写 待审核 8 页

MessageFormat 2 · 给人看的消息怎么写

把「You have 3 new messages」翻成几十种语言,要应付复数(英语 2 档、波兰语 4 档、阿拉伯语 6 档)、语序、性别一致、还要在句中加粗 / 加链接。MessageFormat 2(MF2)是 Unicode 给这个老问题的新标准:一套既能被译者读懂、又能跨实现(ICU4C / ICU4J / JS)复用的消息语法,并正进入 ECMA-402 的 Intl.MessageFormat 提案。

本系列按官方文档的脉络铺开:先看消息的语法构成,再到内置函数选择变体声明标记,最后是 JavaScript 里的 messageformat 包 API 与错误处理。每页都能改消息源、传值、换 locale,实时看真实引擎(打包进来的 messageformat v4)的输出。

怎么读这个系列: 没接触过就从 为什么需要它消息的构成 顺着看;想查具体能力直接跳:格式化数字 / 日期 → 函数;复数 / 性别 → 选择;复用与本地变量 → 声明;富文本 → 标记;在代码里集成 → JS API;线上健壮性 → 错误与回退 why · 为什么需要它

为什么不能直接拼字符串

从朴素拼接到 printf 到 ICU MessageFormat 1,逐一看旧方案卡在哪:语序焊死、无法处理复数、嵌套语法难读。MF2 把「选择逻辑」与「分支文本」分离,并作为跨实现的 Unicode 标准收口。

message · 消息的构成

一条消息长什么样

最小语法:文本占位符 {…},里面是 变量 name字面量 |literal| 或带函数的表达式。看文本转义、引号内外两种字面量、user.name 点路径,以及 simple 何时升级成需要 {{…}} 的 complex message。

functions · 函数注册表

函数:给值挑一种本地化形式

内置函数全表:REQUIRED 的 :string / :number / :integer / :offset,DRAFT 的 :date / :time / :datetime / :currency / :unit / :percent。逐个跑、调选项——注意 MF2 用 length / fields / precision 这套可移植词汇,而非直接透传 Intl

match · 选择与变体

选择:同一条消息的多个版本

.match + 平铺变体 + 通配 * 解决复数 / 性别。拖 count、换 locale 看命中哪个变体与复数类别;精确键如何优先于类别、select=ordinal / exact、以及多选择子如何维度相乘。

declarations · 声明

声明:给输入注解、给中间值起名

.input {x :number … 给外部变量绑定默认格式(并兼任 .match 的选择子),.localy = {…} 命名中间结果复用。声明一次、正文处处用,使用处还能临时覆盖。出现声明即 complex message,正文要套 {{…}}

markup · 标记

标记:让译者也能安全地加粗、加链接

{#tag}…{/tag} / {#tag /} 只标出「这段要套某种装饰」,不绑定 HTML;宿主读 formatToParts() 自行渲染。左边写源、右边看标记被解释成真实 DOM,parts 里全是抽象标签——无法破坏结构、注入不了。

api · JavaScript 包

messageformat 包:在 JS 里跑 MF2

new MessageFormat(locales, source, options) + format() / formatToParts();自定义函数;以及数据模型层 parseMessage / stringifyMessage / validate / visit 与类型守卫。实时看消息解析成的对象树。

errors · 错误与回退

错误与回退:坏消息也要给个像样的输出

五类错误两个阶段:构建期(Syntax / DataModel)抛异常,运行期(Resolution / Function / Selection)回退到近似源占位串 + onError 上报、不中断。逐个触发看降级行为,以及那对看不见的 bidi 方向隔离符。

MF2 不是浏览器内置 API。 它仍是 Unicode 标准 + TC39 提案,JS 里要靠 messageformat 包(v4)。本系列的 demo 都跑这个真实引擎;日期 / 货币等 DRAFT 函数已替你用 DraftFunctions 注册好,故可直接体验。

相关链接

  • MessageFormat 2 · 官方站点 messageformat.unicode.org 本系列对照的官方文档:语法参考(Functions / Literals / Variables / Markup / Matchers / Patterns / Errors)、各语言集成指南,以及一个在线 Playground。
  • UTS #35 Part 9 · MessageFormat 规范本体 unicode.org LDML 的 MessageFormat 章节:消息语法的 ABNF、数据模型、解析 / 解析 / 格式化算法、默认函数注册表(含 REQUIRED / DRAFT 分档)与错误定义的权威来源。
  • messageformat · JS 实现 (v4) github.com 本系列 demo 打包的引擎:MessageFormat 类、messageformat/functionsDefaultFunctions / DraftFunctions、数据模型工具与 messageformat/cst 具体语法树。
  • TC39 · Intl.MessageFormat 提案 tc39.es 把 MF2 引入 ECMA-402、成为浏览器内置 Intl.MessageFormat 的提案。落地后,本系列的 JS 用法将不再需要安装包。
  • MDN · Intl 命名空间 developer.mozilla.org Intl 国际化对象总览:NumberFormat / DateTimeFormat / PluralRules 等现有构造器。MF2 的 :number / :date 等内置函数即建立在这套底层格式化能力之上;Intl.MessageFormat 提案落地后也将归入此页。

解析内核与二进制 AST

  • intlify · Binary AST Snapshot v0.1 Writer + Decoder github.com intlify 解析器 crate 为 MF2 解析树实现的二进制快照格式:字符串 interning(FNV-1a)、8 字节对齐的定长记录、zero-copy 遍历,把「解析后的 AST」序列化成可校验、可直接按偏移读取的字节流,跳过重复解析。
  • TC39 · JavaScript Binary AST (BinAST) 提案 github.com 把 JavaScript 源码预先解析成二进制 AST 再发给浏览器、跳过解析以加快启动的标准化尝试(现已搁置)。与上面 MF2 快照同源的思路:用紧凑二进制布局换取免重复 parse 的加载性能。
  • V8 · Code caching for JavaScript developers v8.dev V8 缓存编译产物(bytecode / code cache)以复用、规避重复 parse 与 compile 的工程方案,是 BinAST 之外解决「解析慢」问题的另一条主流路径。