ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Logto 翻译 CLI(@logto/translate)全解析:基于 GPT 的 i18n 短语自动化翻译与键同步实战指南

2026/9/15 12:34:06 拓冰建站 浏览量
Logto 翻译 CLI(@logto/translate)全解析:基于 GPT 的 i18n 短语自动化翻译与键同步实战指南 Logto 翻译 CLIlogto/translate全解析基于 GPT 的 i18n 短语自动化翻译与键同步实战指南【免费下载链接】logto‍ Authentication and authorization infrastructure for SaaS and AI apps, built on OIDC and OAuth 2.1 with multi-tenancy, SSO, and RBAC.项目地址: https://gitcode.com/GitHub_Trending/lo/logto本文以 packages/translate/CHANGELOG.md 为脉络结合logto/translate包的全部源码入口文件、openai.ts、prompts.ts、sync-keys 等完整讲解 Logto 开源仓库中这套 AI 驱动的 i18n 翻译工作流它如何用 GPT 为phrases/phrases-experience两个语言包自动生成与增量翻译短语、如何基于 TypeScript AST 同步不同语言间的键与文件结构以及 CLI 各子命令的参数、环境变量与底层实现原理。读完本文你将掌握logto-translate的安装配置、四条核心命令的实战用法以及其从logto/cli拆分独立的演进背景。一、包定位与演进背景为什么需要一个独立的翻译 CLIlogto/translate的定位在 package.json 中写得很明确A CLI tool that helps translate phrases and experience-phrases to i18n resources.——它专门服务于 Logto 的两套 i18n 资源包logto/phrases管理端admin console等场景的文案短语logto/phrases-experience登录体验sign-in experience界面的文案短语。两者各自维护大量按语言目录组织的 TypeScript locale 文件packages/phrases/src/locales 与 packages/phrases-experience/src/locales新增语言或新增短语时人工翻译与键对齐成本极高于是这套 CLI 被设计出来。从 CHANGELOG 的0.1.0版本可以看出它诞生的直接原因将translate命令从logto/cli中拆分出来创建独立的包。该命令涉及 TypeScript 代码操作必须把typescript作为依赖导致logto/cli包体积大增而实际上只有少数想为 Logto 贡献代码的开发者会用到它因此把它分离出去以保持 cli 包的轻量与简洁。这解释了三个关键事实该工具主要面向Logto 贡献者/翻译维护者而非终端用户它依赖typescript做源码级代码操作这正是sync-keys命令的核心它随 Logto 开源发行版打包发布二进制名称为logto-translate见 package.json 的bin字段。二、环境准备Node 版本与 API 密钥运行时要求package.json 中engines字段要求 Node^22.14.0这一要求对应 CHANGELOG0.2.0的变更 bump node version to ^22.14.0。必需环境变量create与sync两个命令都依赖 OpenAI APIcreate.ts 与 sync.ts 的命令描述中明确提示Note the environment variableOPENAI_API_KEYis required to work.完整的可配置环境变量如下依据 openai.ts 与 utils.ts 源码环境变量默认值作用OPENAI_API_KEY无必填OpenAI 请求的 Bearer 认证令牌OPENAI_MODEL_NAMEgpt-4.1使用的模型名通过getModel()读取OPENAI_API_PROXY_ENDPOINThttps://api.openai.com/v1API 前缀地址可替换为兼容网关HTTPS_PROXY/HTTP_PROXY/https_proxy/http_proxy无HTTP(S) 代理按优先级HTTPS_PROXY→https_proxy→HTTP_PROXY→http_proxy取值其中默认模型gpt-4.1正是 CHANGELOG0.2.1的变更usegpt-4.1as the default model, as its newer and cheaper thangpt-4o-2024-08-06而OPENAI_MODEL_NAME的读取能力对应0.2.0的 should correctly read modal name from env。代理场景下源码使用hpagent的HttpsProxyAgent构造 HTTPS 代理客户端并将请求超时统一设置为 300 秒timeout: { request: 300_000 }适合大文件翻译的长时间推理。CLI 全局参数入口文件基于 yargs 构建提供了三个全局参数参数别名说明--env path-e,--env-file.env文件路径通过dotenv.config({ path: env })加载--path path-pLogto 实例目录路径见下--skip-core-check-sc跳过 core 包存在性校验入口同时启用了demandCommand(1)与strict()即必须指定一个子命令未知参数会直接报错。实例路径解析与校验所有命令都要定位一个Logto 实例目录逻辑封装在inquireInstancePath()utils.ts默认路径为~/logtoos.homedir() /logto见 constants.ts校验规则目标目录下必须存在packages/core/package.json且其中name字段必须等于logto/core否则提示The path … does not contain a Logto instance当前目录满足校验时直接使用当前目录无需交互非 TTY 环境下必须显式传入--path否则报错 Path is missing传入--skip-core-check可跳过上述校验例如针对尚未拉取 core 的目录。三、命令总览四条子命令logto/translate共提供四个子命令其中create与sync需要 OpenAI APIsync-keys与list-tags为纯本地操作命令别名功能需要 API Keylist-tagslist列出所有可用语言标签否create language-tagc为指定语言创建完整翻译是sync无增量翻译所有未翻译短语是sync-keyssk将 baseline 语言的键与文件结构同步到目标语言否四、list-tags查看可用语言标签logto-translate list-tags该命令list-tags.ts遍历logto/language-kit导出的languages对象逐行打印每个语言标签并用蓝色标注其归属标注phrases该标签是logto/phrases的内置标签标注phrases-experience该标签是logto/phrases-experience的内置标签。它也是create命令校验参数合法性的依据create中若传入的语言标签不满足isLanguageTag()会直接提示Invalid language tag. Runlogto translate list-tagsto see available list.。值得注意的一个细节CHANGELOG0.1.3isLanguageTag被修复为大小写不敏感。原因是phrases与phrases-experience中语言标签一律小写而language-kit中使用混合大小写如pt-BR、zh-CN导致部分 i18n 短语此前无法被识别翻译。修复后大小写不匹配的标签也能被正确检测并翻译。五、create一键生成某语言的全量翻译# 例如为南非荷兰语创建翻译 logto-translate create af-ZA执行流程create.ts校验language-tag合法性isLanguageTag解析 Logto 实例路径inquireInstancePath若该标签是phrases内置标签提示正在更新未翻译短语随后对phrases包执行createFullTranslation若该标签是phrases-experience内置标签同样提示并执行createFullTranslation。底层createFullTranslationopenai.ts的逻辑是读取enbaseLanguage见 utils.ts目录下所有.tslocale 文件递归readLocaleFiles为每个基准文件计算目标路径packages/pkg/src/locales/tag/相对路径目标标签统一转为小写若目标文件已存在则跳过保证幂等不覆盖人工翻译不存在的文件加入并发队列PQueue默认并发 10交给 GPT 生成生成前自动mkdir -p父目录成功后写入文件。因此create适合首次引入一种新语言的场景一次调用即可为phrases和phrases-experience补全全部文件。六、sync增量翻译所有未翻译短语# 翻译 phrases 包默认 logto-translate sync # 翻译 phrases-experience 包 logto-translate sync --package phrases-experiencesyncsync.ts面向持续维护场景读取目标包src/locales下的所有语言目录跳过en与非法语言标签对每种语言调用syncTranslation并打印当前使用的模型Translating files using model ${getModel()}全部完成后执行eslint --fix统一 locale 文件风格lintLocaleFiles对phrases与phrases-experience的src/locales运行。syncTranslation对每个目标文件采取三态决策openai.ts目标文件状态处理方式不存在走createLocaleFile全量生成存在但内容包含未翻译标记将整个文件交给 GPT 翻译随后unlink旧文件并写入新内容存在且无未翻译标记跳过已完整翻译这里的未翻译标记是 prompt 体系的关键约定/** UNTRANSLATED */定义于 prompts.ts。凡是sync-keys生成时发现目标语言缺失的键都会用 baseline 语言的值占位并在上方标注该标记sync则专门寻找这些标记做增量翻译翻译完成后由模型负责移除标记。由此形成sync-keys 打标 → sync 补译的闭环工作流。七、sync-keys基于 TypeScript AST 的键与文件结构同步# 将 en 的键与文件结构同步到 zh-CN logto-translate sync-keys --baseline en --target zh-CN # 同步到所有语言 logto-translate sync-keys -b en -t all # 指定包并跳过 lint logto-translate sync-keys -b en -t all --package phrases-experience --skip-lintsync-keyssync-keys/index.ts不调用任何 AI 服务是纯本地、纯代码级的同步工具其语义在命令描述中定义得非常精确若目标缺少某键用 baseline 的值补齐并加注释标记该短语未翻译便于后续sync补译若 baseline 已删除某键从目标中移除若键在两侧都存在保留目标语言的值绝不覆盖已有翻译。参数一览参数别名默认值说明--baseline-ben基准语言标签必须与 target 不同--target-t无必填目标语言标签或all同步全部语言--package-pkgphrases短语包名如phrases或phrases-experience--skip-lint-slfalse同步后跳过eslint --fix参数校验规则baseline 与 target 必须是合法语言标签isLanguageTagall除外且两者不能相同Baseline and target cannot be the same。底层实现parseLocaleFiles 的 AST 解析核心函数parseLocaleFilessync-keys/utils.ts利用TypeScript Compiler APIts.createSourceFile把 locale 入口index.ts解析为两部分数据结构嵌套短语对象{ key: [短语文本, 是否已翻译] | 嵌套对象 }文件结构{ key: { filePath?: ./xxx.js, structure: {...} } }其中带filePath的键代表跨文件 import。解析规则源码注释中明确简写属性{ errors }视为 import沿importIdentifierPath递归解析被导入文件.js后缀会被替换为.ts再解析普通属性按 initializer 分类对象字面量 → 嵌套对象递归解析字符串字面量 / 无替换模板字面量 → 短语值数组字面量 → 按索引映射为数组元素常用于复数形式的短语数组其他类型 → 直接fatal报错退出。函数返回[短语对象, 文件结构]二元组若入口文件不存在或 stat 失败则返回[{}, {}]——这正是 CHANGELOG0.2.1的变更 allow empty file when syncing keys 的实现基础此前任何一个import文件为空都会抛错中断导致删除文件后无法重新同步键现在缺失/空文件按空对象处理同步流程可无缝继续。目标目录重建traverseNodetraverseNode以 baseline 的嵌套对象与文件结构为模板重建目标语言的完整目录与文件递归mkdir 以追加方式逐行写文件.ts根文件写入固定头import { type DeepPartial } from silverhand/essentials;与import type { LocalePhrase } from ../../types.js;并以export default Object.freeze(identifier)结尾标识符由文件名推导index使用父目录名连字符转下划线import 声明按键名排序后集中写入文件头部路径.ts→.js数组按0 in baselineObject判定输出[ ... ]语法字符串键判定是否已翻译若目标对象中存在该键且已翻译输出目标值否则输出 baseline 值并冠以/** UNTRANSLATED */注释。备份与恢复同步过程先把目标目录整体重命名为目录.bak再重建若重建中途失败控制台会打印Failed to sync keys for , the backup is at 目录.bak for recovery并退出保留备份供人工恢复成功后才删除备份目录。八、AI 翻译核心机制prompt 设计与响应解析请求构造translate()openai.ts向POST {prefixUrl}/chat/completions发送请求请求体为{ model: getModel(), messages: getTranslationPromptMessages({ sourceFileContent, targetLanguage, extraPrompt }) }。Prompt 设计要点prompts.ts系统级assistant roleprompt 对模型的约束极其精细是保证翻译质量的关键只翻译带/** UNTRANSLATED */标记的值输出时移除该标记转义翻译结果中的单引号前置反斜杠保留插值双花括号及其内部内容如{{count}}CJK 与非 CJK 字符之间保留空格中文翻译优先使用你而非您复数形式后缀处理CHANGELOG0.1.3的改进点英文复数后缀为_one、_other但其他语言可能还有_two、_few、_many。这些带后缀的短语总是包含{{count}}变量翻译时需想象变量被后缀对应的数字替换使用目标语言正确的复数形式。prompt 内置了俄语示例const password_requirement { length_one: Требуется минимум {{count}} символ, length_two: Требуется минимум {{count}} символа, length_few: Требуется минимум {{count}} символа, length_many: Требуется минимум {{count}} символов, length_other: Требуется минимум {{count}} символов, };附带完整的输入→输出示例含 import 语句、嵌套对象、UNTRANSLATED标记的保留与移除确保模型输出结构与输入完全一致。源码注释还提醒GPT-3.5 时代的输入 token 上限为 2048prompt 加源文件内容约为 1600 token扩增 prompt 前需注意 token 预算。响应解析与容错用 zod 的gptResponseGuard校验响应结构choices[].message.content、finish_reasonfinish_reason ! stop时打印警告优先用正则/(?:ts)?\n(.*)/s提取代码块内容若未匹配到代码块但内容以const或import开头视为纯代码直接使用翻译失败HTTP 错误、结构校验失败、无 choice均只warn不中断但单文件翻译结果为空时会fatal退出避免写入损坏文件。并发与收尾两个翻译流程均使用PQueue并发 10 控制请求速率queue.onIdle()等待全部完成后统一执行eslint --fix保证生成文件符合仓库代码风格utils.ts 的lintLocaleFiles。九、版本演进时间线从 CHANGELOG 看核心变更结合 CHANGELOG.md该工具的关键演进如下版本类型核心变更0.1.0Minor从logto/cli拆分出独立包涉及 TypeScript 代码操作为保持 cli 轻量而拆分对既有 translate 命令使用者属破坏性变更但因随发行版捆绑发布仅做 minor 升级0.1.1Patch依赖安全升级0.1.2Patch更新 translate CLI 以提升语言与包兼容性0.1.3Patch改进 OpenAI prompt 以更好支持 i18n 复数形式后缀isLanguageTag大小写不敏感0.2.0MinorNode 版本提升至^22.14.0正确从环境变量读取模型名0.2.1Patch允许同步键时空文件缺失/空 import 文件按空处理默认模型切换为gpt-4.1更新更便宜0.2.2 – 0.2.17Patch逐版本跟随logto/phrases、logto/phrases-experience、logto/core-kit、logto/language-kit、logto/shared的依赖升级当前版本为0.2.17见 package.json其依赖树与五个 workspace 包保持同仓同步logto/phrases-experience1.15.0、logto/core-kit2.13.0、logto/language-kit1.4.0、logto/phrases1.31.0、logto/shared3.4.3。十、源码速览关键文件导航若要深入该工具的实现建议按以下顺序阅读packages/translate/src/index.ts — CLI 入口yargs 配置与全局参数packages/translate/src/constants.ts — 默认实例路径与 core 目录常量packages/translate/src/utils.ts — 实例路径校验、代理读取、locale 文件扫描、lint 与共享类型packages/translate/src/openai.ts — OpenAI 客户端、createFullTranslation与syncTranslation的完整翻译流程packages/translate/src/prompts.ts — 翻译 prompt 模板与UNTRANSLATED标记定义packages/translate/src/sync-keys/index.ts —sync-keys命令的参数与流程packages/translate/src/sync-keys/utils.ts — TypeScript AST 解析、文件结构同步与备份恢复实现。配合阅读 packages/phrases/src/locales、packages/phrases-experience/src/locales 下的真实 locale 文件每个语言目录含index.ts入口与按模块拆分的子文件可以直观看到同步 → 打标 → AI 补译三个环节在产物上的对应关系。总结logto/translate是一套设计精巧的 i18n 维护工具链sync-keys用 TypeScript AST 保证多语言间键与文件结构严格对齐不覆盖已有翻译、只补缺失键并打上UNTRANSLATED标记sync与create则借助 OpenAI 完成增量补译与全量生成配合gpt-4.1默认模型、300 秒超时、并发 10 的请求队列以及eslint --fix收尾构成人工保底 AI 提效的完整闭环。理解其从logto/cli拆分、Node 版本约束、环境变量语义到 prompt 复数规则处理的每一处细节既能让你直接上手维护 Logto 的多语言资源也能为自建 AI 翻译工作流提供一份可复用的工程范式。【免费下载链接】logto‍ Authentication and authorization infrastructure for SaaS and AI apps, built on OIDC and OAuth 2.1 with multi-tenancy, SSO, and RBAC.项目地址: https://gitcode.com/GitHub_Trending/lo/logto创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考