ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Easy-Lang 配 TaoToken:中文即 key 的前端国际化在 VSCode 中的落地骨架

Easy-Lang 配 TaoToken:中文即 key 的前端国际化在 VSCode 中的落地骨架 1. 为什么我在 React TS 项目里放弃了传统 i18n先说结论传统 i18n 的核心痛点不是翻译而是命名。每次写一个中文文案你得先想一个英文变量名再把它塞进t(login.title)然后去locales/zh-CN/translation.json里补一条再去en-US里补一条。一个登录页十几个文案光命名就能耗掉半小时。更难受的是可检索性。产品经理说登录按钮文案改一下你在 VSCode 里搜登录搜到的全是t(login.submit.text)这种变量名根本定位不到组件。你只能靠记忆或者翻目录效率极低。Easy-Lang 的思路很直接中文即 key。你写$t(用户登录)翻译文件里就以用户登录作为 key代码里看到什么中文翻译文件里就是什么中文。所见即所得不需要命名不需要跨文件查找。这篇文章聚焦 React TypeScript 项目在 VSCode 里把 Easy-Lang 的工程化骨架搭起来。我会给出可复制的settings.json、config.toml、Easy-Lang 配置片段以及验证中文 key 提取、编译、回退的逐步动作。适合已经在用 React TS、被 i18n 命名折磨过的前端开发者。TaoToken 在这里的角色是当你要用大模型批量翻译untranslatedList里的中文 key 时需要一个稳定的 API 入口。TaoToken 提供兼容 OpenAI 格式的接口直接填 endpoint 和 key 就能用不需要额外适配层。2. TaoToken 前置拿 Key、配环境、装依赖2.1 注册与获取 API Key打开 TaoToken 官网https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content注册后在控制台创建 API Key。这个 Key 后面会填到 VSCode 插件的model.apiKey字段里用于批量翻译。API 基础地址是https://taotoken.net/api兼容 OpenAI 的/v1/chat/completions格式。如果你习惯用 curl 测试可以先跑一条curl https://taotoken.net/api/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -d { model: gpt-4o-mini, messages: [{role: user, content: 把「用户登录」翻译成英文只返回译文}] }返回正常说明 Key 可用。模型名按你账号里可用的填这里只是示例。2.2 项目依赖安装在 React TS 项目根目录执行pnpm add easy-lang easy-lang/react pnpm add -D zustandeasy-lang/react的 peerDependency 是 zustand必须显式安装。如果你用 npmnpm install easy-lang easy-lang/react npm install -D zustand2.3 VSCode 插件安装Easy-Lang 的 VSCode 插件包在 GitHub 仓库的packages/easy-lang-vscode/下文件名类似easy-lang-vscode-0.0.5.vsix.zip。下载后解压得到.vsix文件然后在 VSCode 里按CmdShiftPWindows 是CtrlShiftP打开命令面板输入Extensions: Install from VSIX...选择解压出的.vsix文件安装完成后侧边栏会出现 Easy-Lang 图标。第一次打开项目会自动扫描代码里的$t(...)调用列出已翻译和未翻译的 key。3. 可复制配置settings.json、config.toml、Easy-Lang 骨架3.1 VSCode settings.json在项目根目录的.vscode/settings.json里加入以下配置让 VSCode 对 Easy-Lang 的翻译文件有更好的编辑体验{ files.associations: { translation.json: jsonc }, editor.quickSuggestions: { strings: true }, typescript.tsdk: node_modules/typescript/lib, typescript.enablePromptUseWorkspaceTsdk: true, easy-lang.translationPath: locales/translation.json, easy-lang.targetLangs: [en-US, zh-TW], easy-lang.autoScan: true }files.associations把translation.json关联为jsonc这样你可以在翻译文件里写注释比如标注某个 key 的使用场景不会报错。easy-lang.translationPath告诉插件翻译文件在哪autoScan开启自动扫描。3.2 插件配置文件 .vscode/easy-lang.json这是 Easy-Lang VSCode 插件自己的配置文件放在.vscode/easy-lang.json{ translationPath: locales/translation.json, translateMode: model, targetLangs: [en-US, zh-TW], model: { endpoint: https://taotoken.net/api/v1/chat/completions, model: gpt-4o-mini, apiKey: sk-your-taotoken-key } }translateMode设为model表示用大模型翻译而不是 Google 翻译。endpoint填 TaoToken 的 API 地址apiKey填你在控制台创建的 Key。注意不要把真实 Key 提交到 Git建议用环境变量或者.gitignore排除这个文件。3.3 Easy-Lang 核心配置 locales/index.ts在locales/index.ts里创建 i18n 实例import { createI18nTool } from easy-lang; import { createReactI18nTool } from easy-lang/react; import translations from ./translation.json; export const langOptions [ { label: 简体中文, value: zh-CN }, { label: English, value: en-US }, { label: 繁體中文, value: zh-TW }, ] as const; const i18nTool createI18nTool typeof translations, (typeof langOptions)[number][value] ({ defaultLang: zh-CN, langs: langOptions.map((l) l.value), translations, autoReload: false, }); export const reactI18nTool createReactI18nTool(i18nTool); export const useTranslate reactI18nTool.useTranslate(); export const $t i18nTool.$t;autoReload: false表示切换语言时不刷新页面走 React 响应式更新。如果你不介意刷新可以设为true那样更简单但用户体验差一些。3.4 翻译文件骨架 locales/translation.json初始文件可以只放一条示例{ 用户登录: { zh-CN: 用户登录, en-US: User Login, zh-TW: 用戶登錄 }, 请输入用户名或邮箱: { zh-CN: 请输入用户名或邮箱, en-US: Enter username or email, zh-TW: 請輸入用戶名或郵箱 } }结构是中文原文作为顶层 key下面按语言代码分。同一个 key 的所有语言翻译集中在一处不需要切换文件。3.5 如果你用 Codex 或类似工具config.toml 参考有些团队用 Codex 做代码生成可以在项目根目录放一个config.toml来统一管理翻译相关的配置[translation] provider taotoken endpoint https://taotoken.net/api/v1/chat/completions model gpt-4o-mini target_langs [en-US, zh-TW] translation_file locales/translation.json batch_size 20 [translation.prompt] system 你是一个前端国际化翻译助手。用户会给你一个 JSON 对象key 是中文原文value 是目标语言代码。请返回翻译后的 JSON保持结构不变。这个文件不是 Easy-Lang 必需的但如果你要写脚本批量调用 TaoToken 翻译把配置抽出来会方便很多。4. 验证请求中文 key 提取、编译、回退的逐步动作4.1 在组件里写中文 key打开一个 React 组件比如src/components/LoginForm.tsximport { useTranslate } from /locales; export function LoginForm() { const { $t, changeLang, currentLang } useTranslate(); return ( div classNamelogin-container h1{$t(用户登录)}/h1 label{$t(用户名)}/label input placeholder{$t(请输入用户名或邮箱)} / button{$t(登录)}/button div当前语言{currentLang}/div button onClick{() changeLang(en-US)}English/button button onClick{() changeLang(zh-CN)}中文/button /div ); }保存后VSCode 侧边栏的 Easy-Lang 面板应该会自动扫描到这些中文 key。如果没出现点一下面板上的刷新按钮。4.2 验证 TypeScript 类型检测Easy-Lang 会根据translation.json的类型推断$t的合法参数。如果你写了一个翻译文件里没有的中文 keyTypeScript 会标红$t(这个key不存在) // TS 报错Argument of type 这个key不存在 is not assignable...这个特性很实用你不需要等到运行时才发现漏翻译编译阶段就能看到。4.3 验证未翻译列表在组件里加一个未翻译的中文div{$t(暂无数据)}/div然后在浏览器控制台或者一个临时按钮里打印console.log(i18nTool.untranslatedList); // 输出[暂无数据]untranslatedList会收集所有在代码里用了$t()但翻译文件里还没有的 key。你可以把这个列表复制出来丢给 TaoToken 批量翻译。4.4 用 TaoToken 批量翻译写一个简单的 Node 脚本scripts/translate.mjsimport fs from node:fs; const API_KEY process.env.TAOTOKEN_API_KEY; const ENDPOINT https://taotoken.net/api/v1/chat/completions; const untranslated [暂无数据, 更新时间]; const targetLangs [en-US, zh-TW]; async function translate(texts, lang) { const res await fetch(ENDPOINT, { method: POST, headers: { Content-Type: application/json, Authorization: Bearer ${API_KEY}, }, body: JSON.stringify({ model: gpt-4o-mini, messages: [ { role: system, content: 把以下中文翻译成${lang}返回 JSON 数组顺序不变${JSON.stringify(texts)}, }, ], }), }); const data await res.json(); return JSON.parse(data.choices[0].message.content); } const translationFile JSON.parse( fs.readFileSync(locales/translation.json, utf-8) ); for (const lang of targetLangs) { const results await translate(untranslated, lang); untranslated.forEach((key, i) { if (!translationFile[key]) translationFile[key] { zh-CN: key }; translationFile[key][lang] results[i]; }); } fs.writeFileSync( locales/translation.json, JSON.stringify(translationFile, null, 2) ); console.log(翻译完成);运行TAOTOKEN_API_KEYsk-xxx node scripts/translate.mjs执行后translation.json里会多出对应的翻译条目。4.5 验证语言切换与回退在浏览器里点击English按钮changeLang(en-US)会触发 React 重新渲染所有$t()的返回值变成英文。如果某个 key 在en-US下没有翻译Easy-Lang 会回退到defaultLang这里是zh-CN不会显示空白或报错。你可以故意删掉某条en-US翻译来验证回退行为{ 暂无数据: { zh-CN: 暂无数据 } }切换到英文后这条仍然显示暂无数据说明回退生效。5. 本篇常见错排查5.1 插件扫描不到中文 key检查.vscode/easy-lang.json里的translationPath是否指向正确的文件。如果项目用了 monorepo路径要相对于工作区根目录。另外确认autoScan没有被关掉。5.2 TypeScript 报错 Property does not exist通常是translation.json的类型没有被正确推断。确认locales/index.ts里createI18nTool的泛型参数传了typeof translations并且translation.json在tsconfig.json的resolveJsonModule开启状态下被引入。{ compilerOptions: { resolveJsonModule: true, esModuleInterop: true } }5.3 切换语言后页面没更新如果你设了autoReload: false但组件里用的是$t而不是useTranslate返回的$t就不会触发重新渲染。确保在 React 组件里用 hookconst { $t } useTranslate(); // 正确 // import { $t } from /locales; // 这种不会响应式更新5.4 TaoToken 返回 401检查apiKey是否填了完整的sk-开头字符串以及endpoint是否写成了https://taotoken.net/api/v1/chat/completions。如果用的是环境变量确认 shell 里echo $TAOTOKEN_API_KEY有值。5.5 翻译文件里出现重复 keyJSON 不允许重复 key但如果你手动编辑时不小心写了两遍同一个中文后面的会覆盖前面的。建议用 VSCode 的 JSON 校验或者装一个 JSON 格式化插件保存时自动检测。6. 把翻译流程接进日常开发到这一步你的 React TS 项目应该已经能跑通写中文 → 自动扫描 → 批量翻译 → 切换语言的完整链路了。我自己的习惯是开发阶段只管写$t(中文)不关心翻译文件一个模块做完后打开 Easy-Lang 侧边栏把untranslatedList复制出来用 TaoToken 批量翻译一次提交。如果你还在用传统的t(login.title)方案迁移成本其实不高先把translation.json的 key 从英文变量改成中文原文然后把代码里的t(xxx)全局替换成$t(中文)。VSCode 的查找替换配合正则半小时能搞定一个中等项目。TaoToken 的 API Key 在控制台可以随时创建和吊销建议给翻译脚本单独建一个 Key方便管理和轮换。接入文档在 https://taotoken.net/api 有详细的参数说明模型对话功能可以直接在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 体验确认翻译质量后再写进脚本。最后提醒一点translation.json里的中文 key 尽量保持和代码里完全一致包括标点符号。Easy-Lang 是精确匹配的$t(登录)和$t(登录 )末尾多一个空格会被当成两个不同的 key。
返回列表