Skip to content

国际化 ​

日期与时间组件(DatePicker、DateInput、TimePicker、TimeInput)的文案、数字日期顺序与默认时钟格式 来自组件库的国际化模块。语言是模块级单例,和 useTheme() 一样:切换后所有组件立即重新渲染。

月份、星期名与日期格式化全部交给浏览器的 Intl,组件库只维护少量界面文案,因此自定义语言不用手抄月名表。

内置语言 ​

代码日期顺序时钟格式
enMM/DD/YYYY12 小时制
zh-HansYYYY/MM/DD24 小时制
zh-HantYYYY/MM/DD24 小时制
jaYYYY/MM/DD24 小时制

默认语言是 en。组件库不会自动读取浏览器语言,也不会持久化选择——这两件事由应用决定, 例如在挂载前根据 matchLocale 设置,并把结果存进 localStorage。

文档站是中文站点,因此在 docs/.vitepress/theme/index.ts 里调用 setLocale("zh-Hans"),演示中的月份、 日期顺序与操作按钮都按简体中文显示。

切换语言 ​

ts
import { setLocale, useI18n } from "@sharpdotnut/dotsharp";

setLocale("ja"); // true;未注册的代码会被忽略并给出警告

const { locale, t } = useI18n();
console.log(locale.value); // "ja"
console.log(t("cancel")); // "キャンセル"

useI18n() 返回:

成员类型说明
localeReadonly<Ref<string>>当前语言代码
intlLocaleComputedRef<string>交给 Intl 的合法标签
orderComputedRef<"mdy" | "dmy" | "ymd">数字日期顺序
firstDayOfWeekComputedRef<1…7>一周首日,1 = 周一,7 = 周日
timeFormatComputedRef<"12h" | "24h">默认时钟格式
setLocale(code: string) => boolean切换语言
registerLocale(code, messages, options?) => void注册或覆盖语言
t(key: keyof LocaleMessages) => string当前语言的文案
matchLocale(supported, requested?) => string | undefined从候选里挑最合适的语言

setLocale、registerLocale、matchLocale 也从包入口直接导出。

获取当前语言 ​

matchLocale 用 Intl 规范化并补全语言标签(zh-TW 补全为 zh-Hant-TW),再按 完整匹配 → 同语言同书写系统 → 同语言同地区 → 同语言唯一候选 的顺序选出结果:

ts
import { matchLocale } from "@sharpdotnut/dotsharp";

const supported = ["en", "zh-Hans", "zh-Hant", "ja"];

matchLocale(supported, ["zh-TW"]); // "zh-Hant"
matchLocale(supported, ["zh-CN"]); // "zh-Hans"
matchLocale(supported, ["ja-JP"]); // "ja"
matchLocale(supported, ["fr-FR"]); // undefined

省略第二个参数时读取 navigator.languages(服务端没有 navigator,返回 undefined):

ts
const locale = matchLocale(supported) ?? "en";
setLocale(locale);

加载自定义语言 ​

registerLocale 只覆盖提供的字段,其余回退到英文;order 与 firstDayOfWeek 是可选的语言级设置。 语言代码应当是合法的 BCP 47 标签,月份与星期名由它决定:

ts
import { registerLocale, setLocale } from "@sharpdotnut/dotsharp";

registerLocale(
  "fr",
  {
    date: "Date",
    enterDate: "Saisir une date",
    selectDate: "Choisir une date",
    invalidDate: "Date invalide",
    cancel: "Annuler",
    ok: "Valider",
    previousMonth: "Mois précédent",
    nextMonth: "Mois suivant",
    time: "Heure",
    selectTime: "Choisir une heure",
    invalidTime: "Heure invalide",
    hour: "Heure",
    minute: "Minute",
    second: "Seconde",
    am: "AM",
    pm: "PM",
    clock: "Ouvrir l'horloge",
    chooseMonth: "Choisir le mois",
    chooseYear: "Choisir l'année",
    calendar: "Ouvrir le calendrier",
  },
  { order: "dmy", firstDayOfWeek: 1, timeFormat: "24h" },
);

setLocale("fr");

也可以覆盖内置语言的部分字段:

ts
registerLocale("ja", { ok: "決定" });

firstDayOfWeek 省略时从 Intl.Locale 的区域周信息读取,读不到则回退到周日; timeFormat 省略时也按该语言的区域小时制推断(h11 / h12 为 12 小时制,其余为 24 小时制)。

服务端渲染 ​

语言状态在模块作用域里,服务端与浏览器各有一份。为了让 SSR 输出与首次水合一致:

  • 服务端与浏览器都用同一个初始语言(默认 en),或把语言放在应用的根上下文里统一设置;
  • 依赖 navigator / localStorage 的自动检测放到 onMounted,不要让首次渲染读到浏览器状态;
  • 文档站里所有触碰浏览器状态的示例都用 mounted ref 包一层。

新增文案 ​

组件的界面文案集中在 src/i18n/index.ts 的 LocaleMessages;新增日期组件文案时先加英文键, 再补三种内置翻译,t 的键类型会自动覆盖到自定义语言。