@broberg/i18n (英语)
A 类 无头本地端引擎 相同的~120行i18n核心 线索,
sannyandersen和xrt81各一手卷出,取出一次. 探测到这个地方,
坚持下去 用后退链 + 解决一个点- 路径键 {var} 内插,
(单位:千美元) bilingual() 帮助 {da,en} 内容对象。 无框架,
安全无虞 安全无虞 这个 LanguageSwitcher 部件仍为副本所有
每叠.
npm i @broberg/i18n
使用量
import { createI18n } from "@broberg/i18n";
const i18n = createI18n({
locales: ["da", "en"], // first = default
fallbackLocale: "en", // the complete base dict
messages: {
da: { greeting: "Hej", nav: { home: "Hjem" } },
en: { greeting: "Hello", nav: { home: "Home" }, welcome: "Hi {name}" },
},
storageKey: "acme-locale",
});
i18n.getLocale(); // "da" (stored > navigator.language > default)
i18n.t("nav.home"); // "Hjem"
i18n.t("welcome", { name: "Sanne" }); // "Hi Sanne" (falls back to en, interpolates)
i18n.setLocale("en"); // persists, syncs <html lang>, notifies subscribers
i18n.bilingual({ da: "Goddag", en: "Good day" }); // active-locale string, plain-string tolerant
const off = i18n.subscribe((locale) => rerender()); // pub/sub, no context provider
说对了
- 后退链 —— 说
t(key)解决活动区域,然后是倒置 语言,然后返回生键(绝不是空白字符串). {var}插值 —— 说t("welcome", { name })填入占位符.bilingual()——从a取出活地-地域{da,en}对象和 容忍简单的字符串,所以LLM生成的双语内容和遗留的平原 字符串两个都有效.- 检测 - 储存的地盘
navigator.language准确匹配 =navigator.language前缀相配 → 默认,全部SSR守护. 下一个读取 在此处接受默认值之前 - 它决定你的语言 产品说话. - 平安无事 a 包括:
globalThis- 密钥登记意味着两个捆绑副本 同样的storageKey共享一个实例,所以活动区域永远不能 脱氧核糖核酸.
你想要哪个检测默认值?
detect 实值 true 除非你设定它 false. 后果,指出
很明显: 无 detect: false,您的产品语言是由一个
浏览器设置用户从未被触碰 .
这和"我们发现这个地方"不一样 区别在于 整个问题。 没有故障,没有出错,没有测试会红——引擎 做它所配置的, 而配置是我们的 默认.
当它被咬时是什么样子(一个真实的,fd-sundhed,2026年8月):a
丹麦第一产品, locales: ["da", "en"],还没有存储的选择。 一个市镇
头儿在笔记本电脑上打开她的第一页 en-US 浏览器和
获得 整个领导者都用英语出现 ——"请批准","等待你
决定。 她从来没有选择过英语。 没有人知道。 花了五队
几周前有人问及是否
想要的行为.
选择退出为一行:
const i18n = createI18n({
locales: ["da", "en"],
fallbackLocale: "en",
messages,
detect: false, // ← the product decides the language, not the browser
});
故意选择:
| 你的产品 | 设定 |
|---|---|
一种主要语言,一种明确语言 fallbackLocale用户 第一次访问时使用的语言 | detect: false - 普通案件 |
| 一个没有单一主语的真正的多语种受众,在浏览器语言中与用户相会是关键 | detect: true (今天的默认) |
不管怎样,一个明确的 setLocale() 从语言切换器总是赢
- 检测只能决定 第一个 提交用户
已经选择了.
在服务器上(下个服务器组件,Hono,Bun)——0.2.0
不使用共享实例( E)createI18n() → t()编号 :getLocale()) 上 时 间
服务器. 每个进程为一个地方;以不同语言提出请求
运行的同时,一个用户的语言会最终出现在另一个用户的页面上.
换成使用其中之一 globalThis数字 :
import { translate, createI18n } from "@broberg/i18n";
// A pure function: pass the request's locale every call.
translate(messages, locale, "docs.count", { count: 3 }, { fallbackLocale: "da" });
// Or a private instance per request, same API as in the browser.
const i18n = createI18n({ locales: ["da", "en"], messages, locale: requestLocale, singleton: false });
i18n.t("hello", { name });
复数——0.2.0
值可以是复数项; 选择表单时使用 Intl.PluralRules 页:1
地点,从 count表格缺失 − other。在 t() 财务报告和审定财务报表 translate()。 。 。 .
const messages = {
da: { docs: { one: "{count} dokument", other: "{count} dokumenter" } },
pl: { docs: { one: "{count} dokument", few: "{count} dokumenty", many: "{count} dokumentów", other: "{count} dokumentu" } },
};
translate(messages, "pl", "docs", { count: 5 }); // "5 dokumentów"
类别 : zero, (中文(简体) ), one, (中文(简体) ), two, (中文(简体) ), few, (中文(简体) ), many, (中文(简体) ), other (简体中文). 对象是
只有在有字符串时才读取为复数项 other 没有其他钥匙.
缺少译文,并附上LLM——0.3.0
import { missingKeys } from "@broberg/i18n";
// A CI gate: every key in Danish exists in English.
expect(missingKeys(da, en)).toEqual([]);
missingKeys(base, target) 列出在 base 目标缺乏(a)
复数条目计数为一键, 丢失直到它有 other) (中文(简体) ). 它拉进来了
没有别的了.
@broberg/i18n/llm 填补 仅限 这些密钥:
import { createAI } from "@broberg/ai-sdk";
import { fillMissing } from "@broberg/i18n/llm";
const { result, filled, rejected } = await fillMissing({ base: da, target: en, from: "da", to: "en", ai: createAI() });
- 现有密钥从未被触动 这就是人类的矫正方式
活下来了 输入没有变异;
result是新对象. - 位符字节为字节. 翻译:
{var}设定与 源(重新命名、丢弃或添加)因该密钥而被拒绝rejected,而不是写. - 欧盟路线,无后退: 每一次通话都是
override: { provider: "mistral", model: "mistral-large-2512" }. UI 文本不是个人资料,而是房子 规则是欧盟,而倒置则是可以离开欧盟的路线. - 多元条目:每个源表被翻译;目标返回到
other对于类别,只有它自己的语言.
CLI( 需求) @broberg/ai-sdk 安装在您的工程中 :
npx i18n-fill locales/da.json locales/en.json --from da --to en # dry run
npx i18n-fill locales/da.json locales/en.json --from da --to en --write # save
当任何密钥被拒绝时退出代码 1, 这样它就可以打开 CI.
API 密码
createI18n({ locales, defaultLocale?, fallbackLocale?, messages?, storageKey?, storage?, detect? }): I18n
// I18n: getLocale · setLocale · subscribe · t(key, vars?) · bilingual(text) · detectInitial · locales
词典保留 在您的回购中 (把它们捆入包里会合而为一)
每份消费者副本)——包裹只载发动机. 反应( 下一步)
URL - 前缀开关)和 Preact (pub/sub) LanguageSwitcher 适配器以此为基础
核心键.
许可证
麻省理工学院的一部分 @broberg/* 共享库存.