vue-i18n-kit-sy
v1.0.3
Published
Vue i18n runtime and message extraction toolkit for Chinese-key workflows.
Readme
vue-i18n-kit-sy
这是一个面向 Vue 3 + Vue I18n 的国际化工具包:
- 统一创建项目里的 i18n 运行时实例
- 从源码中自动抽取中文 key 并回写语言包
- 对接平台翻译工具,导出lang.xlsx里待翻译的词条以及导入lang.xlsx翻译好的语言并回填到对应语言包
它适合“中文作为 key”的国际化方案,也就是代码里直接写中文,通过 t('中文')、$t('中文')、trans('中文') 标记词条,再用 CLI 扫描并生成 locale 文件。
目录
src/
cli.ts
runtime/
createAppI18n.ts
trans.ts
types.ts
extractor/
config.ts
extract.ts
index.ts设计原则
- runtime 创建 i18n 实例,不关心项目如何存储语言状态
- extractor 扫描、合并和输出语言包,不关心业务运行时逻辑
- 项目需要自己维护 messages、fallback、日期格式、数字格式和 Element Plus locale 映射
安装
pnpm add vue-i18n-kit-sy vue-i18n如果需要通过命令行抽词条,安装本包后可直接使用:
pnpm exec i18n-extract i18n-extract.config.tspnpm extract:i18n 如果你使用 npm,也可以执行:
npx i18n-extract i18n-extract.config.tsExcel 翻译表
除了直接维护 locales/*.json,还支持把词条导出到 lang.xlsx,以及把翻译后的 Excel 回填到语言包。
这两类操作和 extract:i18n 一样,都是按 i18n-extract.config.ts 中的 languages 配置执行。
导出到 Excel
pnpm exec i18n-extract excel:export i18n-extract.config.ts默认会把 Excel 写到 localeDir/lang.xlsx。如果你的配置里 localeDir 是 src/i18n/locales,那么默认输出就是:
src/i18n/locales/lang.xlsx也可以手动指定路径:
pnpm exec i18n-extract excel:export i18n-extract.config.ts src/i18n/locales/lang.xlsx生成的 Excel 规则如下:
- 第 1 行表格名称(自行填写)
- 第 2 行是表头
- 固定包含
词条、comment - 后面会追加语言列,例如
zh_CN、en_US、ru_RU,该语言列与i18n-extract.config.ts对应 - 如果 key 带语境,例如
打开 || 开关,会拆成:词条=打开、comment=开关
也就是说,导出哪些语言列,不是按 locales 目录中当前有哪些 JSON 文件决定的,而是按配置文件里的 languages 决定的。
从 Excel 回填语言包
pnpm exec i18n-extract excel:import i18n-extract.config.ts回填规则如下:
- 第 1 行表格名称
- 读取第 2 行表头
- 用
词条 + comment去匹配zh_CN.json里的原始 key - 把与语言文件同名的列,例如
en_US、ru_RU,回填到对应的en_US.json、ru_RU.json - 空白单元格不会覆盖已有翻译
如果 Excel 里新增了词条,只要这条记录对应的语言列已经在 i18n-extract.config.ts 的 languages 中声明,导入时也会把它补进对应 JSON。
该场景是用于把 lang.xlsx 导入到平台工具翻译审核后,再统一导回项目的语言包 JSON。
从零接入到可抽词条
目录结构
src/
App.vue
main.ts
constants/
status.ts
i18n/
index.ts
messages.ts
locales/
zh_CN.json
en_US.json
i18n-extract.config.ts
package.jsonpackage.json
{
"scripts": {
"dev": "vite",
"extract:i18n": "i18n-extract i18n-extract.config.ts"
}
}i18n-extract.config.ts
import { defineI18nExtractConfig } from 'vue-i18n-kit-sy/extractor'
export default defineI18nExtractConfig({
srcDir: 'src',
localeDir: 'src/i18n/locales',
languages: [
{ code: 'zh_CN', defaultValue: 'key' },
{ code: 'en_US', defaultValue: '' },
],
sort: true,
removeUnused: true,
})src/i18n/messages.ts
import zhCN from './locales/zh_CN.json'
import enUS from './locales/en_US.json'
import type { LocaleMessages } from 'vue-i18n-kit-sy/runtime'
export type Lang = 'zh-CN' | 'en-US'
export const LANG_STORAGE_KEY = 'lang'
export const messages: Record<Lang, LocaleMessages> = {
'zh-CN': zhCN,
'en-US': enUS,
}
export const fallbackMap: Partial<Record<Lang, Lang[]>> = {
'en-US': ['zh-CN'],
'zh-CN': ['en-US'],
}src/i18n/index.ts
import { createAppI18n } from 'vue-i18n-kit-sy/runtime'
import { LANG_STORAGE_KEY, fallbackMap, messages } from './messages'
export default createAppI18n({
defaultLocale: 'zh-CN',
localeStorageKey: LANG_STORAGE_KEY,
fallbackMap,
messages,
missingWarn: false,
fallbackWarn: false,
globalInjection: true,
})src/main.ts
import { createApp } from 'vue'
import App from './App.vue'
import i18n from './i18n'
createApp(App).use(i18n).mount('#app')src/constants/status.ts
import { trans } from 'vue-i18n-kit-sy/runtime'
export const STATUS_MAP = {
pending: trans('待确认'),
pushed: trans('已推送'),
}src/App.vue
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import { STATUS_MAP } from './constants/status'
const { t, locale } = useI18n()
function toggleLang() {
locale.value = locale.value === 'zh-CN' ? 'en-US' : 'zh-CN'
}
</script>
<template>
<main>
<button @click="toggleLang">
{{ $t('切换语言') }}
</button>
<h1>{{ t('首页标题') }}</h1>
<p>{{ $t('欢迎使用') }}</p>
<p>{{ STATUS_MAP.pending }}</p>
</main>
</template>src/i18n/locales/zh_CN.json
{}src/i18n/locales/en_US.json
{}执行顺序
第一次接入时,按下面顺序执行即可:
pnpm install
pnpm dev
pnpm extract:i18n执行完 pnpm extract:i18n 后,语言包会自动生成类似下面的内容:
{
"切换语言": "切换语言",
"已推送": "已推送",
"待确认": "待确认",
"欢迎使用": "欢迎使用",
"首页标题": "首页标题"
}至此已经完成了“运行时可翻译 + 源码可抽词条”的最小闭环。
预期接入方式
运行时
import { createAppI18n, trans } from 'vue-i18n-kit-sy/runtime'抽词条
import { defineI18nExtractConfig } from 'vue-i18n-kit-sy/extractor'新项目接入
1. 创建抽取配置
在项目根目录新增 i18n-extract.config.ts:
import { defineI18nExtractConfig } from 'vue-i18n-kit-sy/extractor'
export default defineI18nExtractConfig({
srcDir: 'src',
localeDir: 'src/i18n/locales',
languages: [
{ code: 'zh_CN', defaultValue: 'key' },
{ code: 'en_US', defaultValue: '' },
],
})2. 创建运行时实例
import { createAppI18n } from 'vue-i18n-kit-sy/runtime'
import { messages, fallbackMap, LANG_STORAGE_KEY } from './messages'
export default createAppI18n({
defaultLocale: 'zh-CN',
localeStorageKey: LANG_STORAGE_KEY,
fallbackMap,
messages,
})3. 在非组件文件中标记词条
import { trans } from 'vue-i18n-kit-sy/runtime'
export const STATUS_MAP = {
'1': trans('待确认'),
}4. 运行抽词条
npx i18n-extract i18n-extract.config.ts或在 package.json 中写:
{
"scripts": {
"extract:i18n": "i18n-extract i18n-extract.config.ts"
}
}Workspace 开发
常用命令:
pnpm install
pnpm --dir packages/vue-i18n-kit-sy build
pnpm --dir packages/vue-i18n-kit-sy release:check
pnpm exec vue-tsc --build
npm run extract:i18npnpm exec i18n-extract i18n-extract.config.tspnpm exec i18n-extract excel:export i18n-extract.config.ts src/i18n/locales/lang.xlsxpnpm exec i18n-extract excel:import i18n-extract.config.ts src/i18n/locales/lang.xlsx可以在package.json的scripts里添加以下配置:
"extract:i18n": "pnpm exec i18n-extract i18n-extract.config.ts",
"export:i18n": "pnpm exec i18n-extract excel:export i18n-extract.config.ts src/i18n/locales/lang.xlsx",
"import:i18n": "pnpm exec i18n-extract excel:import i18n-extract.config.ts src/i18n/locales/lang.xlsx"后续直接执行:
pnpm run extract:i18n
pnpm run export:i18n
pnpm run import:i18n