Skip to content

语言工具 ​

语言包和 Vue 国际化实例统一由 @axewo/fin-locale 提供,应用只注入实例并维护业务词条。core 的 /locale 提供可脱离 Vue 使用的底层函数,fin-locale 复用相同实现。

语言标识 ​

ts
import { normalizeFinLocale } from '@axewo/fin-core/locale'
import type { FinLocale } from '@axewo/fin-core/locale'

const locale: FinLocale = normalizeFinLocale('en_US') // 'en'
normalizeFinLocale('zh-Hans') // 'zh-CN'
normalizeFinLocale('unknown', 'en') // 'en'

内置语言为 zh-CN、en。未知值使用第二个参数,默认简体中文。该函数只规范化 Fin 内置语言,不是任意 BCP 47 标识的通用校验器。旧的 fin-locale 导入入口保留。

应用需要日文等扩展语言时使用 normalizeAppLocale;保留有效的 BCP 47 标识,兼容中英文别名,非法输入才使用回退值。该函数由 fin-locale 同名重导出,语言切换、持久化和微前端宿主同步共同复用。

ts
import { normalizeAppLocale } from '@axewo/fin-core/locale'
normalizeAppLocale('ja_jp') // 'ja-JP'
normalizeAppLocale('en-US') // 'en'
normalizeAppLocale('../invalid', '') // '',可用于校验

合并词条 ​

ts
import { mergeLocaleMessages } from '@axewo/fin-core/locale'

const messages = mergeLocaleMessages(
  { order: { title: '订单', save: '保存' } },
  { order: { title: '采购订单' } },
)
// { order: { title: '采购订单', save: '保存' } }

后者覆盖同名叶子,保留其他键;数组整体替换。返回新的对象,嵌套普通对象和数组也复制。仅遍历自有可枚举属性,忽略 __proto__、constructor、prototype,避免配置改变对象原型。

输入应是无循环的词条树,函数消息等特殊叶子保持原引用且不执行。它不处理插值、复数和语言回退,这些仍交给国际化引擎。createFinI18n 已完成内置词条合并,普通 Vue 应用不必再手动调用本函数。

无框架翻译适配 ​

ts
import { translateCoreLabel, translateCoreLabels } from '@axewo/fin-core/locale'

const t = (key: string) => key === 'order.status.draft' ? 'Draft' : key
translateCoreLabel(t, 'order.status.draft', '草稿') // 'Draft'
translateCoreLabels(t, 'order.status', { draft: '草稿', done: '完成' })
// { draft: 'Draft', done: '完成' }

翻译函数缺失、返回空字符串或原键时,使用调用方默认文案。CoreTranslate 类型和这两个函数也保留根入口导出。

Vue 接入 ​

ts
import { createApp } from 'vue'
import { createFinI18n } from '@axewo/fin-locale'
import App from './App.vue'

const i18n = createFinI18n({
  locale: 'zh-CN',
  messages: {
    'zh-CN': { order: { title: '订单管理' } },
    en: { order: { title: 'Orders' } },
  },
})
createApp(App).use(i18n).mount('#app')

组件使用 useFinLocale,Fin UI 与 Element Plus 的语言同步交给 FinLocaleProvider。详见国际化指南。不要在子应用另建一套公共语言映射,core 也不会反向依赖 fin-locale。

请求与字典等 setup 外代码 ​

使用 createFinLocaleContext() 创建应用独立的访问器,在启动入口调用 bind(installFinI18n(app, options)!),卸载时调用返回的释放函数。访问器的 locale.value、t、te 始终读取绑定的当前实例;不会创建另一份 i18n,也不会依赖包级共享的当前应用变量。

ts
import { createFinLocaleContext } from '@axewo/fin-locale'

// 每个项目自己的模块;SSR 则每个请求创建。
export const appLocale = createFinLocaleContext()
// 请求时读取当前值,而不是模块加载时缓存。
const language = () => appLocale.locale.value

未绑定时 locale.value 为 zh-CN、t 返回原键、te 返回 false。绑定支持重挂载,旧释放不会清除新实例。组件内继续使用 useFinLocale();zh-CN 转成后台所需的 zh_CN 属于项目协议,不放入公共访问器。

后台多语言业务字段 ​

后台的 LocaleString 字段与 UI 语言标识不同:英文默认字段键为 en-US,不能用会折叠成 en 的 normalizeAppLocale 改写提交数据。以下函数从 @axewo/fin-locale 导入:

函数用途
toLocaleKey(locale)规范大小写、下划线,默认 zh → zh-CN、en → en-US,保留扩展语种及地区
normalizeLocaleString(value, legacyChinese?)规范后台映射,兼容旧单语字段并补中文
buildLocaleString(value)去除清空的翻译,用于构建提交数据
getExactLocaleText(value, locale)编辑时只读指定语言及无地区键,不跨语言回退
getLocaleText(value, locale?, fallback?)展示时按精确语言、同语言族、中文、首个翻译、默认文案回退
ts
import { getLocaleText, normalizeLocaleString, useFinLocale } from '@axewo/fin-locale'
import { computed } from 'vue'

const { locale } = useFinLocale()
const names = normalizeLocaleString({ en_US: 'System', ja_JP: 'システム' }, '系统')
const label = computed(() => getLocaleText(names, locale.value))

这些工具不依赖业务项目的 @/lang,也不连接后台语言字典。显示回退只用于读文案,不能将回退结果当成另一语言的编辑值提交。