@ryucode/translate
v1.0.1
Published
提取和翻译 JSON 文件中的文案。通过 locator 机制可自定义提取逻辑,支持任意数据格式。
Readme
@ryucode/translate
提取和翻译 JSON 文件中的文案。通过 locator 机制可自定义提取逻辑,支持任意数据格式。
快速使用
无需安装,直接通过 npx 运行:
npx @ryucode/translate run ./src/locales/id.json --source=id --target=en使用方式
方式一:npx(推荐,免安装)
npx @ryucode/translate <command> [options]方式二:全局安装
npm install -g @ryucode/translate
translate <command> [options]方式三:本地安装
npm install @ryucode/translate
npx translate <command> [options]方式四:从源码直接运行
git clone <repo-url>
npm install
node src/cli.js <command> [options]子命令
run — 完整流水线
按顺序执行 extract → translate → apply,可选 format。
npx @ryucode/translate run <source-file> --source=<语言代码> --target=<语言代码> [options]| 参数 | 说明 |
|------|------|
| source-file | 待处理的 JSON 源文件。可省略,从 stdin 读取 |
| --source | 源语言代码,如 id(印尼语)、zh-CN(中文) |
| --target | 目标语言代码,如 en(英语) |
| --format / -f | 可选,翻译完成后用 prettier 格式化文件 |
| --custom-translate-server / -S=<file> | 可选,使用自定义翻译服务替代内置谷歌翻译 |
| --proxy[=url] | 可选,代理翻译流量:无值时从环境变量读取,有值时使用自定义地址 |
| --locator=<file> | 可选,使用自定义 locator 替代内置提取逻辑。内置名称:json-file |
示例:
npx @ryucode/translate run src/locales/id.json --source=id --target=en
cat src/locales/id.json | npx @ryucode/translate run --source=id --target=enextract — 提取文案
从源文件中提取待翻译文案,输出 key: value 格式到 stdout。
npx @ryucode/translate extract <source-file> [--locator=<file>]示例(JSON):
npx @ryucode/translate extract src/locales/id.json
# 输出:
# greeting: Halo Dunia
# welcome.title: Selamat Datang内置 json-file locator 递归提取所有嵌套字符串值,以点号路径作为 key。
translate — 翻译文本
从 stdin 读取 key: value 格式的文本,翻译后输出 JSON 到 stdout。
npx @ryucode/translate translate --source=<语言代码> --target=<语言代码> [options]通常与 extract 配合使用:
npx @ryucode/translate extract source.json \
| npx @ryucode/translate translate --source=id --target=en \
> result.json支持 --proxy[=url] 和 --custom-translate-server / -S=<file> 参数,用法同 run。
apply — 写回翻译
将翻译结果 JSON 按 key 路径写回源文件。
npx @ryucode/translate apply <result.json> <source-file> [--locator=<file>]示例:
npx @ryucode/translate apply result.json src/locales/id.jsonformat — 格式化文件
用 prettier 格式化指定文件。
npx @ryucode/translate format <file-to-format>自定义 Locator
通过 --locator=<file> 自定义如何从源码中提取和写回翻译内容,替代内置的 locator。
// csv-locator.js
export const ext = ['csv'];
export function match(source) {
const lines = source.trim().split('\n');
const result = {};
for (const line of lines) {
const [key, val] = line.split(',');
result[key.trim()] = val.trim();
}
return result;
}
export function apply(source, translations) {
const lines = source.trim().split('\n');
let changedCount = 0;
const out = lines.map(line => {
const [key, val] = line.split(',');
if (key.trim() in translations && val.trim() !== translations[key.trim()]) {
changedCount++;
return `${key.trim()},${translations[key.trim()]}`;
}
return line;
});
return { code: out.join('\n') + '\n', changedCount };
}| 导出 | 类型 | 必需 | 说明 |
|------|------|------|------|
| ext | string[] | 是 | 支持的文件扩展名,如 ['csv'];['*'] 表示匹配所有 |
| match(source) | 函数 | 是 | 接收源码字符串,返回 { key: text } |
| apply(source, translations) | 函数 | 是 | 接收源码 + 翻译结果,返回 { code, changedCount } |
| source | 'raw' \| 'ast' | 可选,默认 'raw' | 声明 match/apply 的入参类型 |
source='raw'(默认):locator 自行处理解析和生成,框架只调用 match/apply。
source='ast':框架负责 Babel parse/generate,locator 直接操作 AST 节点,apply 返回 number(仅修改数量)。
详情见 locator.md。
npx @ryucode/translate run data.csv --source=en --target=zh-CN --locator=./csv-locator.js内置 locator
| 名称 | ext | source | 说明 |
|------|-------|----------|------|
| json-file(默认) | json | 'raw' | 递归提取 JSON 所有嵌套字符串值,点号路径作为 key |
npx @ryucode/translate run data.json --source=en --target=zh-CN自定义翻译服务
通过 --custom-translate-server=<file> 或 -S=<file> 使用外部翻译服务,替代内置的谷歌翻译。
自定义服务是一个 .js 文件,默认导出一个异步函数 (texts: string[]) => Promise<string[]>:
// ai-translate.js
export default async function translate(texts) {
return texts.map(t => `[AI: ${t}]`);
}npx @ryucode/translate run source.json --source=en --target=zh-CN -S=./ai-translate.js代理
代理会拦截所有翻译服务的 HTTP 流量(谷歌翻译和自定义服务均生效)。
从环境变量读取
export https_proxy=http://127.0.0.1:7890
npx @ryucode/translate run source.json --source=en --target=zh-CN --proxy优先级:https_proxy > http_proxy(均不区分大小写)。
自定义代理地址
npx @ryucode/translate run source.json --source=en --target=zh-CN --proxy=http://127.0.0.1:7890不传 --proxy
不走代理,环境变量中的 http_proxy / https_proxy 不会被读取。
代理拦截机制
工具通过三层方式确保代理对所有 HTTP 库生效:
| 层 | 方式 | 覆盖范围 |
|---|------|---------|
| global-agent | 拦截 http/https/net 原生模块 | axios、got、node-fetch v2 |
| undici setGlobalDispatcher | 设置全局 undici 分发器 | undici、Node 原生 fetch、node-fetch v3 |
| http_proxy env | 设置环境变量 | 主动读取 proxy env 的库 |
批处理
翻译时会按每批 50 条分组,批次之间间隔 1 秒,避免请求频率过高。
开发
npm test # 运行所有测试(node:test)
node src/cli.js ... # 从源码直接运行