用于 JavaScript 和 TypeScript 的构建工具。
四个 npm 包将 Echo Lingua 从标记字符串转化为已交付的翻译,无需离开你的代码库:@echo-lingua/i18n 运行时,使用 @echo-lingua/i18n-cli 提取和编译,用 @echo-lingua/sdk 填充每个区域设置,并使用 @echo-lingua/inline-editor 在浏览器中实时编辑。相同的 @echo-lingua/i18n-cli 也处理 PHP 和 Laravel;见下文 适用于每个平台的构建工具。
包裹字符串。发布轻量级运行时。
用 @echo-lingua/i18n 运行时中的 _() 包装 UI 文本;@echo-lingua/i18n-cli 工具扫描你的源代码,为每个区域设置填充 .po,并将翻译后的内容编译成带有占位符、复数和富文本的紧凑运行时。在调用点直接为模型添加上下文、标志或注释。运行时是可选的且仅限 JS;CLI 是项目无关的另一半。
标记字符串,在需要时添加标志import { _, EL } from '@echo-lingua/i18n'; _('Save changes'); _('Hello {name}', { name }); _('You have {count} item', 'You have {count} items', { count }); // 选项尾部:标志、msgctxt 和给模型的注释。 _('Order', {}, { context: 'verb' }); _('Save', {}, { flags: [EL.CONTEXT_UI_LABEL] }); _('There is a file', 'There are {count} files', { count }, { flags: [EL.QUALITY_PRO, EL.CONTEXT_LEGAL], comment: 'Shown under the section title', });
提取 → 编译# 用于应用程序的运行时,用于构建的工具链 npm i @echo-lingua/i18n npm i -D @echo-lingua/i18n-cli # 扫描代码,为每个语言环境填充一个 .po 文件 npx echo-lingua-i18n extract # 将翻译目录编译进运行时 npx echo-lingua-i18n compile
适用于每个平台的构建工具。
提取器和编译器 @echo-lingua/i18n-cli 是项目无关的。它扫描 JavaScript、TypeScript 和 PHP(包括 .phtml 模板),填充相同的 .po 文件,并将它们编译为您运行时原生读取的任何格式:JS 目录、用于 PHP gettext() 的二进制 .mo,或用于 Laravel __() 的扁平 JSON。除了 JS 之外,没有其他 Echo Lingua 运行时需要采用;你保留你自己的。任何其他 gettext 堆栈(Python、Go、C)都通过下方的 HTTP API 驱动同一个平台。
在 PHP 或 .phtml 中标记字符串<?php // 使用你已在使用的 gettext / Laravel 函数标记字符串 _('Account settings'); ngettext('one invoice', '{count} invoices', $n); pgettext('nav', 'Home'); __('Welcome back'); // Laravel 字符串键
编译原生目标// i18n.config.mjs — 整个工具链只需一个配置 export default { locales: ['de', 'fr'], include: ['src/**/*.{php,phtml}'], compileTargets: ['mo'], // 或 'laravel'(扁平 JSON),或 'js' }; # 为每个区域设置写入一个原生的 .mo 文件供 PHP gettext() 使用 npx echo-lingua-i18n sync
从 CLI 或您自己的代码进行翻译。
API 客户端和翻译 CLI。echo-lingua translate 读取您的配置,通过 API 填充每个语言环境的 .po,并将它们写回。或者从您自己的代码中调用类型化客户端——创建任务、等待任务完成并下载仓库格式的输出。
翻译 CLI# 通过 API 就地填充每种语言环境的 .po 文件 npm i @echo-lingua/sdk # 读取您的配置,并将翻译写回 npx echo-lingua translate
或使用类型化客户端import { EchoLingua } from '@echo-lingua/sdk'; const el = new EchoLingua({ apiKey: process.env.ECHO_LINGUA_KEY }); // 创建任务,等待任务完成,然后拉取仓库格式的 zip 包。 const job = await el.createJob({ sourceLanguage: 'en', contextMode: 'ui-label', quality: 'standard', inputs: [{ filename: 'de/messages.po', targetLanguage: 'de', content }], }); const done = await el.waitForJob(job.id, { onProgress: (j) => log(j.status) }); const zip = await el.downloadJob(done.id);
在运行中的应用中编辑翻译。
一个仅供开发使用的工具栏会嵌入到您的应用中。按住 Alt 并点击任何已翻译的字符串即可实时编辑翻译、修复英文原文、添加上下文或标志,或者让 AI 进行智能修复、缩短文本或重新翻译。管理复数形式、覆盖显示的英文原文,并运行整个提取 → 翻译 → 编译流程——所有更改都会直接写回到您的仓库中。
添加 Vite 插件(仅限开发环境)// vite.config.ts — dev only import { echoLinguaBabel, echoLinguaInlineEditor } from '@echo-lingua/inline-editor'; export default defineConfig(({ command }) => ({ plugins: [ react(command === 'serve' ? { babel: { plugins: [echoLinguaBabel()] } } : {}), echoLinguaInlineEditor(), ], }));
@echo-lingua/inline-editor
浏览器内编辑器。与 @echo-lingua/i18n 配对使用——Babel 转换会将每次点击映射到具体的 _() 调用,开发服务器会读取并写入您的 .po 文件和源码。绝不会发布到生产环境。
或者自己动手连接。
不使用 JavaScript,或者需要从其他技术栈进行自动化?以上所有功能都是简单的 HTTP 调用——一个作用域密钥、一个 POST 请求,并在任务完成后发送已签名的 Webhook。它适用于任何 gettext 项目,无论使用何种语言。
预估费用,然后创建任务。
首先使用 /v1/jobs/estimate 预估大小和费用(不收取任何费用),然后使用相同的主体创建运行任务。每个 inputs 条目都是一个 .po 文件,拥有各自的 targetLanguage;sourceLanguage 和 contextMode 是必填项,quality 是 draft、standard 或 pro。
POST /v1/jobs/estimatecurl -X POST https://api.echo-lingua.com/v1/jobs/estimate \ -H "Authorization: Bearer $ECHO_LINGUA_KEY" \ -H "Content-Type: application/json" \ -d @job.json # same body as the create call — nothing is charged
200 · 大小 + 费用,不收取任何费用{
"entries": 550,
"chunks": 10,
"words": 7400,
"chargedMicros": 2386500,
"creditRequiredMicros": 2505825
}POST /v1/jobscurl -X POST https://api.echo-lingua.com/v1/jobs \ -H "Authorization: Bearer $ECHO_LINGUA_KEY" \ -H "Content-Type: application/json" \ -d '{ "sourceLanguage": "en", "contextMode": "ui-label", "quality": "standard", "inputs": [ { "filename": "de/messages.po", "targetLanguage": "de", "content": "…" }, { "filename": "ar/messages.po", "targetLanguage": "ar", "content": "…" } ] }'
201 · 创建成功的任务{
"id": "job_8f2c41",
"status": "QUEUED",
"sourceLanguage": "en",
"contextMode": "ui-label",
"quality": "standard",
"createdAt": 1726669120000
}一个 Bearer 令牌。您授予它的作用域。
在应用中创建密钥,每个密钥都会显示 once、带有过期时间且可撤销。使用量按密钥归属。使用单个标头进行身份验证:
每个请求Authorization: Bearer elk_live_2b7f…
# elk_-prefixed. 仅在创建时显示一次,请将其存放在机密存储中。translate:write
创建任务、重试失败条目、取消运行。
jobs:read
读取任务状态和计数、列出任务、下载输出。
签名投递,拒绝轮询。
为 job.completed 和 job.failed 注册一个端点。每次投递都经过针对原始主体的 HMAC-SHA256 签名,请在信任前进行验证。重试使用有界指数退避算法。
投递 · 标头 + 请求体POST https://your-app.example/hooks/echo-lingua X-EchoLingua-Signature: 9f86d0818… (原始正文的十六进制 HMAC-SHA256) X-EchoLingua-Timestamp: 1726669123456 X-EchoLingua-Delivery: whd_3f9c8a { "id": "whd_3f9c8a", "type": "job.completed", "createdAt": 1726669123456, "data": { "jobId": "job_8f2c41", "status": "COMPLETE", "downloadUrl": "/v1/jobs/job_8f2c41/download" } }
verify.ts,针对原始请求体import { createHmac, timingSafeEqual } from 'node:crypto'; // 对原始请求正文进行验证,在 JSON 解析之前。 export function verify(rawBody, signature, secret) { const expected = createHmac('sha256', secret).update(rawBody).digest('hex'); const a = Buffer.from(signature); const b = Buffer.from(expected); return a.length === b.length && timingSafeEqual(a, b); }
发布时自动翻译,开启 PR。
从 CI 触发任务,让签名的 Webhook 告诉你它已完成,然后拉取仓库结构的输出并开启 Pull Request,无需浏览器介入。
.github/workflows/translate.ymlname: Translate on release
on:
release:
types: [published]
jobs:
translate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Kick off a translation job
run: |
curl -sS -X POST https://api.echo-lingua.com/v1/jobs \
-H "Authorization: Bearer ${{ secrets.ECHO_LINGUA_KEY }}" \
-H "Content-Type: application/json" \
-d @job.json
# 已签名的 job.completed Webhook 会打开包含翻译目录的 PR。您真正会用到的端点。
上面的端点是您最先会用到的。 在文档中查看所有端点 →