npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pretty-i18n-cli

v0.2.0

Published

由配置驱动的 Excel/Google Sheets 与多语言 locale 文件双向转换 CLI

Downloads

28

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 --help

5 分钟开始

在需要管理多语言的项目根目录运行:

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

识别当前安装来源并请求确认;只有输入 yyes 才会使用原包管理器全局卸载:

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"
    }
  }
}

加载在线来源时,checkpreviewimport 都会显示逐 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:不拆分;
  • keyPrefixcommon.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 仓库的 SettingsSecrets and variablesActions 中创建 Repository secret:

  • Name:NPM_TOKEN
  • Secret:刚创建的 npm token。

token 只保存在 GitHub Secrets 中,不要写入仓库、配置文件或日志。

发布版本

确认 NPM_TOKEN 已配置后创建并推送 tag:

git tag v0.2.0
git push origin v0.2.0

GitHub 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 发起网络请求,请只配置可信地址;
  • 导入前建议执行 checkpreview
  • .xlsx/.xls 使用 SheetJS 官方 CDN 的精确版本 0.20.3,避开 npm registry 中过旧且有已知漏洞的 0.18.5

License

MIT