better-i18n
v1.0.0
Published
Modern i18n library designed from 2026 perspective - ultra-simple API with ES2025+ features
Maintainers
Readme
better-i18n
零依赖的现代 JavaScript 国际化库。
特性
- 零依赖(< 3KB gzipped)
- 单 API 设计(
t()) - 智能复数(数组形式)
- 格式化后缀(6 种格式化器)
- 自动持久化(localStorage)
- 默认语言内联(零闪烁)
- Alpine.js 集成 - 唯一支持的框架适配器
- Vanilla JS 优先 - 无框架也能完美使用
安装
bun add better-i18n或使用 esm.sh:
<script type="module">
import { i18n } from "https://esm.sh/better-i18n";
</script>快速开始
import { i18n } from "better-i18n";
import defaultMessages from "virtual:better-i18n-default-messages";
await i18n.init({ defaultMessages });
console.log(i18n.t("welcome")); // "欢迎"
console.log(i18n.t("greeting", { name: "世界" })); // "你好,世界!"API 参考
t(key, values?)
获取翻译字符串。
i18n.t("welcome"); // "欢迎"
i18n.t("greeting", { name: "Alice" }); // "你好,Alice!"
i18n.t("items", { count: 1 }); // "1 项"
i18n.t("items", { count: 5 }); // "5 项"set(locale)
切换当前语言。
await i18n.set("zh-CN");get()
获取当前语言。
i18n.get(); // 'zh-CN'onChange(callback)
监听语言变化。
const unsubscribe = i18n.onChange((newLocale) => {
console.log("语言已切换为:", newLocale);
});
// 稍后取消订阅
unsubscribe();init(options)
初始化 i18n 实例。
await i18n.init({
defaultLocale: "en",
defaultMessages, // 内联以避免闪烁
supportedLocales: ["en", "zh-CN", "ja"],
localesPath: "./locales",
persist: true, // 自动保存到 localStorage
storageKey: "better-i18n-locale",
strict: false, // 生产环境开启严格模式
});bindDataAttributes()
自动绑定翻译到带有 data-i18n 属性的元素。
i18n.bindDataAttributes(); // 初始化和语言切换时自动翻译HTML:
<!-- 简单 key -->
<h1 data-i18n="welcome"></h1>
<!-- 带 args 的 key -->
<p data-i18n='greeting|{"name": "Alice"}'></p>
<!-- 嵌套 key -->
<span data-i18n="nested.title"></span>autoTranslate()
手动触发所有 data-i18n 元素的翻译。
i18n.autoTranslate(); // 立即扫描并翻译data-i18n 属性格式
| 格式 | 示例 | 描述 |
| -------- | ----------------------------------------- | ---------------------- |
| 简单 key | data-i18n="welcome" | 仅翻译 key |
| 带 args | data-i18n='greeting\|{"name": "Alice"}' | key 和参数用 \| 分隔 |
注意:参数作为 JSON 字符串在 \| 分隔符后传递。
格式化器
better-i18n 支持在翻译字符串中使用格式化后缀:
数字
{
"price": "价格:{value:number}"
}i18n.t("price", { value: 1234.56 }); // "价格:1,234.56"货币
{
"cost": "成本:{value:currency,CNY}"
}i18n.t("cost", { value: 100 }); // "成本:¥100.00"日期
{
"updated": "更新于:{value:date,long}"
}i18n.t("updated", { value: new Date() }); // "更新于:2025年1月1日"相对时间
{
"ago": "{value:relative,day}"
}i18n.t("ago", { value: -2 }); // "2 天前"时长
{
"duration": "耗时:{value:duration}"
}i18n.t("duration", { value: { hours: 2, minutes: 30 } }); // "耗时:2 小时 30 分钟"列表
{
"items": "项目:{value:list,conjunction}"
}i18n.t("items", { value: ["苹果", "橙子", "香蕉"] }); // "项目:苹果、橙子和香蕉"翻译文件格式
标准 JSON 格式:
{
"welcome": "欢迎",
"greeting": "你好,{name}!",
"items": ["{count} 项", "{count} 项"],
"price": "价格:{value:number}",
"nested": {
"title": "标题",
"subtitle": "副标题"
}
}框架集成
Alpine.js
better-i18n 提供官方 Alpine.js 适配器:
import Alpine from 'alpinejs'
import { alpineI18nPlugin } from 'better-i18n/adapters/alpine'
Alpine.plugin(alpineI18nPlugin({
messages: {
en: { welcome: 'Welcome' },
'zh-CN': { welcome: '欢迎' }
}
}))
Alpine.start()<div x-data>
<h1 x-i18n="welcome"></h1>
<button @click="$i18n.set('zh-CN')">中文</button>
</div>注意:better-i18n 专注于无框架场景。Vue/React 用户请使用官方方案:
- Vue: vue-i18n
- React: react-i18next
Vite 插件
安装
// vite.config.js
import { defineConfig } from "vite";
import { betterI18nPlugin } from "better-i18n/vite-plugin.js";
export default defineConfig({
plugins: [
betterI18nPlugin({
defaultLocale: "en",
localesPath: "./locales",
}),
],
});使用
import { i18n } from "better-i18n";
import defaultMessages from "virtual:better-i18n-default-messages";
await i18n.init({ defaultMessages }); // 无闪烁!插件自动:
- 构建时内联默认语言
- 支持翻译文件变化时的 HMR
许可证
MIT
