pretty-i18n-cli
v0.2.0
Published
由配置驱动的 Excel/Google Sheets 与多语言 locale 文件双向转换 CLI
Downloads
28
Maintainers
Readme
pretty-i18n-cli
一个由 i18n.config.json 驱动的 Node.js CLI,用来在 Excel / Google Sheets 与项目 locale 文件之间双向转换。
它覆盖参考桌面工具的核心能力:
- 从
.xlsx、.xls或 Google Sheets 导入翻译; - 从已有 locale 反向导出 CSV / XLSX;
- 跨 sheet 检查重复 key、空 key、缺失翻译;
- 导入前输出完整 diff;
- 支持 JSON、JavaScript、TypeScript、Apple
.xcstrings; - 支持多 sheet、逐 sheet 列覆盖、模块拆分/筛选/重命名;
- 支持覆盖/跳过已有 key,保留/删除 Excel 缺失的 key;
- 保留已有 JS/TS 文件中导出对象以外的代码、注释和换行风格;
- 自带完整中文 JSON Schema,并随 CLI npm 包一同发布。
环境要求
- Node.js >= 20.11
- 需要导入的项目对 locale 输出目录有写权限
安装
全局安装:
npm install --global pretty-i18n-cli或作为项目开发依赖:
npm install --save-dev pretty-i18n-cli项目内执行时可使用:
npx --no-install i18n --help5 分钟开始
在需要管理多语言的项目根目录运行:
i18n init它会创建 i18n.config.json。把 Excel 放到配置中的位置,然后依次执行:
# 检查翻译表
i18n check
# 查看将要写入的文件和完整 diff
i18n preview
# 写入 locale 文件
i18n import
# 把 locale 反向导出为 Excel
i18n export也可以临时指定另一份配置:
i18n --config configs/mobile.i18n.json import配置文件所在目录就是项目根目录。Excel、locale 和导出文件路径都相对于它解析,因此配置可以直接提交到 Git,不需要保存每台机器不同的绝对路径。
Excel 格式
最简单的工作表:
| key | 中文 | English | |---|---|---| | common.ok | 确定 | OK | | common.cancel | 取消 | Cancel |
对应配置:
{
"$schema": "https://raw.githubusercontent.com/oloshe/pretty-i18n-cli/v0.2.0/schema/config.schema.json",
"schemaVersion": 1,
"source": {
"file": "translations/i18n.xlsx",
"sheet": "i18n",
"keyColumn": "key",
"languageColumns": {
"zh-CN": "中文",
"en-US": "English"
}
},
"output": {
"pathTemplate": "src/locales/{lang}.json",
"format": "json"
}
}导入结果:
src/locales/zh-CN.json
src/locales/en-US.json空翻译单元格不会生成 key,便于应用自身的 fallback language 生效。
命令手册
i18n init [path]
创建一份包含 $schema 的示例配置。默认路径是 i18n.config.json。
i18n init
i18n init configs/mobile.json
i18n init --force默认不会覆盖已有文件;只有显式传入 --force 才覆盖。
i18n upgrade
检查 npm registry 中的最新版本。有新版本时,CLI 会识别当前全局安装使用的 npm、pnpm、Yarn Classic 或 Bun,并使用同一个包管理器升级。检测和安装过程会显示进度:
i18n upgrade当前已是最新版本时不会执行安装。无法可靠识别安装来源时,CLI 会停止并提示手动处理,避免产生重复的全局安装。
i18n uninstall
识别当前安装来源并请求确认;只有输入 y、yes 或 是 才会使用原包管理器全局卸载:
i18n uninstall直接回车或输入其他内容会取消卸载。
i18n check
检查:
- 跨选中 sheet 的重复 key;
- 有翻译但没有 key 的行;
- 某个 key 缺少个别语言翻译。
发现问题时默认返回退出码 1,适合放进 CI:
i18n check
i18n check --json
i18n check --no-fail只有 key、没有任何翻译的模块分节行不会被当作空翻译错误。
i18n preview
读取 Excel 和已有 locale,输出:
- 将创建/更新的文件;
- 新增、覆盖、跳过、删除的 key 数量;
- 每个文件的完整 unified diff。
该命令不写文件。
i18n import
生成并合并 locale 文件:
i18n import
i18n import --dry-run--dry-run 等价于在 import 路径上做一次预览,不写文件。
i18n export
读取 locale 文件并聚合为表格:
i18n export
i18n export --format csv --output translations/current.csv
i18n export --format xlsx --output translations/current.xlsx命令行的 --format 和 --output 只覆盖本次执行,不修改配置。
完整配置
一份覆盖主要能力的配置见 examples/i18n.config.json。
根字段
| 字段 | 必填 | 说明 |
|---|---:|---|
| $schema | 否 | 供 VS Code 使用的精确 Git tag Schema URL |
| schemaVersion | 是 | 供 CLI 使用的配置版本,当前必须是 1 |
| source | 是 | Excel / Google Sheets 和列映射 |
| output | 是 | locale 输出和合并策略 |
| export | 否 | locale 反向导出的格式、路径和模块 |
source
| 字段 | 默认值 | 说明 |
|---|---|---|
| file | — | 项目内 Excel 路径,与 url 二选一 |
| url | — | 单个链接或链接数组,与 file 二选一;数组顺序决定同名 Sheet 的优先级 |
| sheet | 第一个 sheet | 读取一个工作表 |
| sheets | — | 读取多个工作表,优先于 sheet |
| skipRows | 0 | 顶部跳过行数 |
| headerRow | 1 | 表头行号,从 1 开始 |
| keyColumn | 必填 | 标准 key 列名 |
| languageColumns | 必填 | {语言标识: 标准 Excel 列名} |
| sheetColumnOverrides | {} | 特殊 sheet 的实际列名覆盖 |
多 sheet 的表头不一致时:
{
"source": {
"file": "translations/i18n.xlsx",
"sheets": ["Default", "Special"],
"keyColumn": "key",
"languageColumns": {
"zh-CN": "中文",
"en-US": "English"
},
"sheetColumnOverrides": {
"Special": {
"keyColumn": "id",
"languageColumns": {
"zh-CN": "zh_CN_text",
"en-US": "en_US_text"
}
}
}
}
}Google Sheets 必须允许当前运行环境访问。CLI 会把普通分享链接转换为 format=xlsx 的导出链接,并保留 gid。
多个在线来源按数组顺序加载;同名 Sheet 只采用第一次出现的版本,后续来源中的其他 Sheet 仍会合并:
{
"source": {
"url": [
"https://example.com/translations-primary.xlsx",
"https://example.com/translations-secondary.xlsx"
],
"sheets": ["H5", "Admin"],
"keyColumn": "key",
"languageColumns": {
"zh-CN": "中文",
"en-US": "English"
}
}
}加载在线来源时,check、preview 和 import 都会显示逐 URL 下载进度。
output.pathTemplate
- JSON / JS / TS 必须包含
{lang}; - 按模块分文件时可以包含
{module}; - xcstrings 是单文件,不使用占位符;
- 路径必须相对于项目,绝对路径和
../越界路径会被拒绝。
示例:
src/locales/{lang}.json
src/locales/{lang}/{module}.ts
ios/Localizable.xcstrings输出格式
| format | 行为 |
|---|---|
| json | 标准 JSON 对象 |
| js | 新文件生成 export default |
| ts | 新文件生成 export default ... as const |
| xcstrings | Apple String Catalog,所有语言在同一个文件 |
已有 JS/TS 支持:
export default { /* locale */ };或:
export const languages = { /* locale */ };导入时只替换导出的对象字面量,周边代码和注释会保留。为避免执行项目代码,解析器只接受 JSON5 兼容的静态对象字面量;函数调用、变量引用、展开语法等动态表达式会被拒绝。
Key 结构
keyStyle: "nested":
{
"common": {
"ok": "OK"
}
}keyStyle: "flat":
{
"common.ok": "OK"
}模块拆分
output.module.mode:
none:不拆分;keyPrefix:common.ok的模块是common,模块内 key 是ok;sectionRow:只有 key 单元格有内容的行开启一个模块分节。
分节行示例:
| key | 中文 | English | |---|---|---| | 公共 | | | | title | 公共 | Common | | buy | 购买 | Buy |
配置:
{
"output": {
"pathTemplate": "src/locales/{lang}/{module}.json",
"format": "json",
"module": {
"mode": "sectionRow",
"nameSource": "sectionRow",
"include": ["公共"],
"exclude": [],
"nameReplacements": {
"公共": "common"
},
"removePrefix": false
}
}
}include / exclude 同时识别替换前和替换后的模块名。removePrefix 主要影响多个模块写入同一个语言文件的情况。
合并策略
{
"merge": {
"existing": "overwrite",
"missing": "keep"
}
}| 字段 | 值 | 说明 |
|---|---|---|
| existing | overwrite | Excel 覆盖相同 key 的旧翻译 |
| existing | skip | 保留 locale 中相同 key 的旧翻译 |
| missing | keep | 保留 Excel 本次没有提供的旧 key |
| missing | remove | 删除 Excel 本次没有提供的旧 key |
missing: "remove"会让目标文件与本次输入同步。与模块筛选同时使用时尤其要先运行preview,避免删除未参与本次导入的内容。
格式化选项
{
"quoteObjectProperties": true,
"spaceWrappedLanguages": ["ar", "ur"],
"ensureTrailingNewline": true,
"sourceLanguage": "en-US"
}quoteObjectProperties只影响 JS/TS;spaceWrappedLanguages会给指定语言的翻译前后各加一个空格;- 已有文件继续使用原本的 LF/CRLF;
sourceLanguage只影响 xcstrings,省略时使用第一种语言。
反向导出
{
"export": {
"path": "translations/i18n-export.xlsx",
"format": "xlsx",
"modules": []
}
}路径包含 {module} 且 modules 为空时,CLI 会从第一种语言的目标目录自动发现模块文件。若模板结构无法自动发现,请显式填写模块名。
JSON Schema
精确 Git tag 地址
i18n init 会根据当前 CLI 版本自动写入不可变的 tag 文件地址。例如 CLI 0.1.0:
https://raw.githubusercontent.com/oloshe/pretty-i18n-cli/v0.2.0/schema/config.schema.json只要对应 tag 已推送,这个地址就可以直接供 VS Code 使用;不需要 GitHub Pages,也不要求创建 GitHub Release。尚未推送对应 tag 时,URL 会暂时返回 404。
$schema 服务编辑器补全和诊断,schemaVersion 由 CLI 用于配置兼容性校验。不要使用 main 或 /latest/,避免同一个 URL 的内容发生变化。
CLI 内置 Schema
不发布独立 Schema npm 包。pretty-i18n-cli 自身已包含 schema/config.schema.json,并通过 pretty-i18n-cli/schema 导出;CLI、编辑器和其他工具使用的是同一份 Schema。Schema 的每个字段和枚举值都有中文说明。
发布
仓库包含两条自动化流程:
ci.yml:PR / main 分支执行类型检查、测试、构建和打包检查;publish.yml:推送 SemVer tag 后发布 CLI,并创建 GitHub Release。若该版本已在 npm 存在,则跳过重复发布后继续创建 Release。
配置 npm Token
在 npm 创建具有发布权限的 Granular Access Token:
- 权限:Read and write;
- Packages and scopes:首次发布时选择 All Packages,并设为 Read and write;
- 勾选 Bypass two-factor authentication。
然后在 GitHub 仓库的 Settings → Secrets and variables → Actions 中创建 Repository secret:
- Name:
NPM_TOKEN; - Secret:刚创建的 npm token。
token 只保存在 GitHub Secrets 中,不要写入仓库、配置文件或日志。
发布版本
确认 NPM_TOKEN 已配置后创建并推送 tag:
git tag v0.2.0
git push origin v0.2.0GitHub Actions 会从 secrets.NPM_TOKEN 注入发布凭据,完成校验、打包、npm 发布和 GitHub Release 创建。若对应版本已在 npm 存在,则跳过重复发布后继续创建 Release。tag 对应的 raw GitHub Schema URL 也会立即可用。
开发与本地测试
npm install
npm run check
npm test
npm run build
npm pack --dry-run在 CLI 仓库中建立全局开发链接后,可以在任意测试项目里直接使用最终命令名:
# 在 pretty-i18n-cli 仓库中
npm run build
npm link
# 切到一个测试项目
i18n --help
i18n init
i18n check测试结束后可执行 npm unlink --global pretty-i18n-cli 移除开发链接。若不想建立全局链接,也可以在 CLI 仓库中运行 node dist/cli.js --help。
要测试与用户实际安装完全一致的 tarball:
npm pack
npm install --global ./pretty-i18n-cli-0.2.0.tgz
i18n --version安全说明
- 输出路径不能是绝对路径,也不能通过
../写到项目外; - JS/TS locale 只解析静态对象字面量,不执行项目代码;
- 在线表格会由 CLI 发起网络请求,请只配置可信地址;
- 导入前建议执行
check和preview; .xlsx/.xls使用 SheetJS 官方 CDN 的精确版本0.20.3,避开 npm registry 中过旧且有已知漏洞的0.18.5。
