OneScript
基础

i18n

让脚本按设备语言显示对应的文案。

onescript/i18n 会按 system.locale.languages(设备的语言偏好)从你提供的文案中选出一种语言,并提供文案查找、插值、复数,以及日期和数字的格式化。

快速开始

在项目中为每种语言准备一个 JSON 文件:

src/
  app.tsx
  locales/
    en.json
    zh-Hans.json

locales/en.json:

{
  "greeting": "Hello, {name}!",
  "cart": {
    "items": { "one": "{count} item", "other": "{count} items" }
  }
}

locales/zh-Hans.json:

{
  "greeting": "你好,{name}!",
  "cart": {
    "items": { "other": "{count} 件商品" }
  }
}

src/app.tsx:

import { createI18n } from "onescript/i18n"
import en from "./locales/en.json"
import zhHans from "./locales/zh-Hans.json"

const i18n = createI18n({
  fallback: "en",
  messages: { en, "zh-Hans": zhHans },
})

// 设备语言为简体中文时:
i18n.locale                           // "zh-Hans"
i18n.t("greeting", { name: "Ada" })   // "你好,Ada!"
i18n.t("cart.items", { count: 3 })    // "3 件商品"

// 设备语言为英文时:
i18n.locale                           // "en"
i18n.t("cart.items", { count: 1 })    // "1 item"
i18n.t("cart.items", { count: 3 })    // "3 items"

文案

  • 文案是嵌套对象,用点分路径作为 key,例如 "cart.items"。key 按 fallback 语言的文案做类型检查,写错时编辑器会报错。
  • {name} 会被替换为传入的值。数字会按文案语言格式化,例如英文中 1234 显示为 1,234。缺少对应的值时会报错。
  • 带 other 键的对象是复数文案,调用时需要传入 count。分支按 Intl.PluralRules 选择(zero、one、two、few、many、other),对应的分支不存在时使用 other。
  • 其他语言可以缺少部分文案。缺少时使用 fallback 语言的文案,并对每个 key 只提示一次警告。

语言匹配

createI18n 按顺序检查 system.locale.languages,使用第一个能匹配到的语言;都匹配不到时使用 fallback。

  • 地区不同也能匹配:en-GB 匹配 en,pt-BR 匹配 pt。
  • 中文按书写文字匹配:zh-CN 匹配 zh-Hans,zh-TW、zh-HK 匹配 zh-Hant。
  • 书写文字不同不会匹配:只提供了 zh-Hans 时,繁体中文用户会继续尝试下一个偏好语言,而不是看到简体文案。

假设提供了 en、zh-Hans、zh-Hant 三种文案,fallback 为 en:

system.locale.languagesi18n.locale
["zh-CN"]"zh-Hans"
["zh-HK"]"zh-Hant"
["en-GB"]"en"
["ja-JP", "zh-TW"]"zh-Hant"(没有日语,使用下一个偏好语言)
["ja-JP"]"en"(都匹配不到,使用 fallback)

如果不想跟随设备语言,可以通过 locale 指定:

const i18n = createI18n({
  fallback: "en",
  locale: "zh-Hans",
  messages: { en, "zh-Hans": zhHans },
})

i18n.locale // 始终为 "zh-Hans"

日期与数字

i18n.date(value, options) 和 i18n.number(value, options) 使用与文案相同的语言格式化,options 与 Intl.DateTimeFormat、Intl.NumberFormat 的选项相同。

const date = new Date(2026, 9, 7)

// i18n.locale 为 "en" 时:
i18n.date(date, { dateStyle: "long" })                    // "October 7, 2026"
i18n.number(1234.5)                                       // "1,234.5"
i18n.number(9.5, { style: "currency", currency: "USD" })  // "$9.50"
i18n.number(0.25, { style: "percent" })                   // "25%"
i18n.number(12500, { notation: "compact" })               // "13K"

// i18n.locale 为 "zh-Hans" 时:
i18n.date(date, { dateStyle: "long" })                    // "2026年10月7日"
i18n.number(12500, { notation: "compact" })               // "1.3万"

API

createI18n(options) 的参数:

参数类型说明
fallbackstring文案最完整的语言。其他语言缺少文案时使用它,key 的类型也从它推导。
messagesRecord<string, object>各语言的文案,key 为语言标签,例如 "en"、"zh-Hans"。
localestring可选。指定使用的语言,不再跟随设备语言。

返回值:

成员说明
locale匹配到的语言。
t(key, values?)返回文案,values 用于插值和复数。
date(value, options?)按 locale 格式化日期。
number(value, options?)按 locale 格式化数字。

另外导出了 matchLocale(requested, available, fallback),可以单独使用上面的匹配规则,例如 matchLocale(["zh-TW"], ["en", "zh-Hant"], "en") 返回 "zh-Hant"。

使用其他库

如果需要 ICU MessageFormat 等更完整的功能,可以安装 i18next 等库,并用 system.locale.languages 决定语言:

import i18next from "i18next"
import { system } from "onescript"

await i18next.init({
  lng: system.locale.languages[0],
  fallbackLng: "en",
  resources: {
    en: { translation: { greeting: "Hello, {{name}}!" } },
  },
})

How is this guide?

最后更新于

本页目录