找回密码
 立即注册
首页 业界区 业界 国际化利器 Intl Messageformat

国际化利器 Intl Messageformat

擒揭 2025-6-2 23:23:52
我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品。我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值。
本文作者:霜序
Formats ICU Message strings with number, date, plural, and select placeholders to create localized messages.
ICU 信息语法

ICU 是 International Components for Unicode 的简称。处理多语言和复杂文本模板提供了一种标准化的语法。它的主要用途是通过模板描述消息内容,并根据上下文(如语言、复数规则、性别等)动态生成格式化的字符串。
核心功能

动态插值

在模板中插入变量值,格式为{key, type, format}
  1. Hello, {name}!
  2. I have {workNum, number} things to do
  3. Almost {pctBlack, number, percent} of them are black.
复制代码
变量{key}会被实际值替换,例如:Hello, FBB!
复数规则(Plurals)

处理与数量相关的消息变化,格式为{key, plural, matches}
  1. {count, plural, =0{no items} one {1 item} other {# items}}
复制代码
会根据传入的 count 会动态处理成合适的文本
  1. count = 0   ===>   no items
  2. count = 1   ===>   1 item
  3. count = 4   ===>   4 items
复制代码
条件选择(Select)

基于条件选择消息内容,格式为{key, select, matches}
  1. {gender, select, male {He} female {She} other {They}} liked your post.
复制代码
会根据 gender 的传入动态输出
  1. gender = male     ===>   He liked your post.
  2. gender = female   ===>   She liked your post.
  3. gender = other    ===>   They liked your post.
复制代码
日期与时间格式化

格式化日期和时间值
  1. The event is scheduled on {date, date, long}.
复制代码
输出格式依赖于区域设置,如: January 1, 2024
总结


  • 强大的模版支持,提供了多种模式供用户选择
  • 跨平台支持,可以用于不同语言
Intl Messageformat

Intl MessageFormat 是一个基于 JavaScript 实现的库,用于处理多语言国际化场景,主要功能是动态格式化文本消息。
  1. pnpm add intl-messageformat
复制代码
基础使用
  1. import { IntlMessageFormat } from "intl-messageformat";
  2. const formatter = new IntlMessageFormat("Hello, {name}!");
  3. const message = formatter.format({ name: "World" });
复制代码
  1. const formatter = new IntlMessageFormat(
  2.   "{count, plural, =0{no items} one {1 item} other {# items}}"
  3. );
  4. const message = formatter.format({ count: 0 });
  5. const message1 = formatter.format({ count: 1 });
  6. const message2 = formatter.format({ count: 10 });
  7. console.log(message, message1, message2); // no items 1 items 10 items
复制代码
发现了一个小小的问题,为什么在{ count: 1 }的时候,输出的是1 items?
IntlMessageFormat还接受其他的参数,第二个参数为locales用于指定当前的语言。如果不特殊指定会通过new Intl.NumberFormat().resolvedOptions().locale获取默认值,此时的默认值为zh-CN,无法处理one这条规则,因此匹配到了other这条规则。在locale为en的语言下能够成为我们的期望值。
那么我们只能更改传入的message
  1. const formatter = new IntlMessageFormat(
  2.   "{count, plural, =0{no items} =1{1 item} other {# items}}"
  3. );
  4. const message = formatter.format({ count: 0 });
  5. const message1 = formatter.format({ count: 1 });
  6. const message2 = formatter.format({ count: 10 });
  7. console.log(message, message1, message2); // no items 1 item 10 items
复制代码
在我们的产品中会有这样的场景,每月 x 号,每周星期 x 的情况,当我们做国际化的时候就可以使用 ICU 信息来做。
  1. const message = `The {day, selectordinal,
  2.     one {#st}
  3.     two {#nd}
  4.     few {#rd}
  5.     other {#th}
  6. } day of month`;
  7. const formatter = new IntlMessageFormat(message, "en");
  8. console.log(formatter.format({ day: 22 }));  // The 22nd day of month
  9. console.log(formatter.format({ day: 26 }));  // The 26th day of month
复制代码
这里又出来一种新的类型selectordinal,主要用于处理序数词,适用于描述顺序或排名。
one/two/few/other 分别对应着不同的序数形式。one通常用于以1结尾的数字除了11),two 用于以2结尾的数字除了12),few用于以3结尾的数字(除了13),而other则用于所有其他情况。
嵌套 dom 的情况

常见例子,我们产品中需要使用 showTotal 中的 total 需要用  包裹做样式更改,最后可能提出的文本为
  1. showTotal={(total) => (
  2.    
  3.         共{total}
  4.         条数据,每页显示{pagination.pageSize}条
  5.    
  6. )}
  7. {
  8.   W: '共',
  9.   X: '条数据,每页显示',
  10.   Y: '条',
  11. }
复制代码
一句完整的话被切分的乱七八糟,翻译成英文的时候也会出现语序问题。
这个时候就需要更改当前的方法,用 IntlMessageFormat 的 tag 模式来支持
  1. 共 <BlueText>{val1}</BlueText> 条数据<Fragment>,每页显示 {val2} 条</Fragment>
复制代码
自定义 formatter

在intl-messageformat中,您可以为消息模板中的自定义类型定义自己的格式化逻辑。例如,默认支持number、date和time类型,但通过自定义formatters,您可以添加自己的格式化类型或扩展现有类型。
[code]const customFormatters = {  getDateTimeFormat(locales, options) {    const originalFormatter = new Intl.DateTimeFormat(locales, options);    return {      format: (value) => `
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册