@telorun/message-format

中文文档
0.127.0发布于 2026/11/02MITTypeScriptES Module零依赖

Telo's message core: a closed profile of Unicode MessageFormat 2 — placeholders, plural selection, CLDR plural rules and decimal formatting from pinned CLDR data, and RFC 4647 language lookup. No Intl, no dependencies; one answer in Node, Rust and every b

原始使用文档
文档目录4 节
  1. The profile
  2. What it answers
  3. Numbers
  4. CLDR data

@telorun/message-format

Telo's message core: a closed profile of Unicode MessageFormat 2, read into a plain-JSON model and formatted with pinned CLDR 48.2 data. It has no dependencies and calls no Intl, so a message formats identically in Node, in Rust (telorun-message-format) and in every browser.

import { formatMessage, lookupLanguage, readMessage } from "@telorun/message-format";

const read = readMessage({
  plural: "count",
  cases: { "=0": "No files", one: "{$count} file", other: "{$count} files" },
});
if (!read.ok) throw new Error(read.problems[0].message);

formatMessage(read.message, "en", { count: 0n }); // "No files"
formatMessage(read.message, "en", { count: 1234n }); // "1,234 files"
lookupLanguage("pl-PL", ["en", "pl"]); // "pl"

The profile

  • A pattern is text with {$name} placeholders and the escapes \{, \} and \\. A name follows the Telo name rule: a letter or _ first, then letters, digits or _, and not a CEL reserved word. Inside the braces, the whitespace and bidi marks MF2 allows are accepted. Anything else MF2 can write in braces is refused: a literal, a function, an option, an attribute or markup.
  • A plural selection is written { plural: <name>, cases: { <category> | =<integer>: Message } }. other is required. A case is itself a Message, so selections nest. =N keys are canonical integers inside int64 ∪ uint64.
  • A text is a Message, or { text: Message, context } with a non-empty context.

What it answers

FunctionAnswer
parsePattern, serializePatternA pattern's parts, and its one canonical spelling.
readMessage, readTextThe model, or every fault as MESSAGE_SYNTAX_INVALID with its path and, inside a pattern, its UTF-16 range.
messageIdentity, textIdentityA source text's key: the pattern reached by taking other at every selection, canonically written, plus its context.
messageVariablesEvery placeholder and selector a message reads.
unknownVariablesMESSAGE_PLACEHOLDER_UNKNOWN for each name a translation reads that its source does not.
pluralCategories, invalidPluralCategoriesA language's CLDR categories, and MESSAGE_PLURAL_CATEGORY_INVALID for each case naming one it lacks.
formatNumber, pluralCategory, pluralCategoryOfDecimalA number's text and category in a language.
formatMessageThe text. Refuses with MESSAGE_PLACEHOLDER_UNBOUND when a name the message reads has no value, on any branch. Refuses with MESSAGE_PLACEHOLDER_VALUE_UNSUPPORTED for a value other than a string or a number, and for a selector that is not a number.
truncationChain, lookupLanguageRFC 4647 lookup: pl-Latn-PL → pl-Latn → pl, case-insensitive. null when nothing matches, and the caller then uses its source.

Numbers

A number's text depends on its value alone, never on its host type:

  • A bigint inside int64 ∪ uint64 is written exactly, however large.
  • A number is a double: its shortest round-trip decimal, rounded half-to-even to the pattern's maximum fraction digits, with trailing zeros dropped and a zero result unsigned. So 1.0 is "1", and in en it selects one.
  • A non-finite double is refused.

The text then takes the language's CLDR standard decimal pattern, grouping (with minimumGroupingDigits), default-numbering digits, decimal separator and minus sign. Plural selection reads the operands of that rounded decimal. =N cases match numerically before the categories.

CLDR data

The data is CLDR 48.2 for every locale, generated into message-format/cldr/ from the exact-pinned cldr-core and cldr-numbers-full. A tag resolves through CLDR's own inheritance and ends at the root (other only, Latin digits, #,##0.###):

  • Number data goes through parentLocales, then the nonlikelyScript rule, then truncation.
  • Plural rules go through CLDR's plurals parent map.

The data is used under the Unicode License V3. The package ships the licence as LICENSE-CLDR, and every build of the core carries it as a /*! */ notice that survives bundling.

版本与发布记录

@telorun/message-format 共发布 10 个版本,首次发布于 2026/10/23;过去 12 个月发布了 10 个版本。

版本发布日期距今
0.127.0latest2026/11/02今天
0.126.02026/11/011 天前
0.125.12026/10/313 天前
0.125.02026/10/304 天前
0.124.02026/10/295 天前
0.123.12026/10/268 天前

关于 @telorun/message-format 的常见问题

@telorun/message-format 是什么?

Telo的消息核心:Unicode MessageFormat 2的封闭配置文件-占位符,复数选择,CLDR复数规则和固定CLDR数据的十进制格式,以及RFC 4647语言查找。没有Intl,没有依赖;在Node, Rust和每个b中都有一个答案

如何安装 @telorun/message-format?

在项目目录运行 npm install @telorun/message-format,或使用 pnpm add / yarn add / bun add。

@telorun/message-format 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@telorun/message-format 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@telorun/message-format 可以商用吗?

@telorun/message-format 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@telorun/message-format 还在维护吗?

最新版本 0.127.0 发布于 2026/11/02(今天);至今共发布 10 个版本,其中过去 12 个月发布了 10 个;首次发布于 2026/10/23。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。