面向开发者

将本地化作为 CI/CD 管道的一环。

用 _() 包裹字符串,通过一条命令填充每个语言环境,并在运行的应用中实时编辑任何翻译——.po 文件从头到尾直接写回您的仓库。或者使用真正的 HTTP API 自行驱动整个流程。

开发与构建工具

用于 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
超越 JavaScript

适用于每个平台的构建工具。

提取器和编译器 @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 文件和源码。绝不会发布到生产环境。

HTTP API

或者自己动手连接。

不使用 JavaScript,或者需要从其他技术栈进行自动化?以上所有功能都是简单的 HTTP 调用——一个作用域密钥、一个 POST 请求,并在任务完成后发送已签名的 Webhook。它适用于任何 gettext 项目,无论使用何种语言。

快速入门

预估费用,然后创建任务。

首先使用 /v1/jobs/estimate 预估大小和费用(不收取任何费用),然后使用相同的主体创建运行任务。每个 inputs 条目都是一个 .po 文件,拥有各自的 targetLanguage;sourceLanguage 和 contextMode 是必填项,quality 是 draft、standard 或 pro。

POST /v1/jobs/estimate
curl -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/jobs
curl -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

读取任务状态和计数、列出任务、下载输出。

Webhooks

签名投递,拒绝轮询。

为 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.yml
name: 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。
参考

您真正会用到的端点。

POST/v1/jobstranslate:write创建一个翻译任务。
POST/v1/jobs/estimatetranslate:write演练规模预估 + 成本,不创建任务。
POST/v1/jobs/plantranslate:write演练单条目分类。
GET/v1/jobsjobs:read列出您的任务。
GET/v1/jobs/{id}jobs:read获取单个任务的状态 + 计数。
GET/v1/jobs/{id}/downloadjobs:read下载输出 zip(仓库结构)。
GET/v1/jobs/{id}/reviewjobs:read标记为需审校的条目。
POST/v1/jobs/{id}/retrytranslate:write仅重新运行失败的条目。
POST/v1/jobs/{id}/canceltranslate:write取消正在运行的任务。
POST/v1/translate/texttranslate:write内联翻译一块文本,无任务。
POST/v1/translate/codetranslate:write翻译代码片段中的字符串字面量。
POST/v1/translate/estimatetranslate:write对同步翻译进行定价估算,不收费。
POST/v1/templatestranslate:write生成每种语言的空白 PO 模板。
GET/v1/usagejobs:read当前周期的使用量、成本和限额。

上面的端点是您最先会用到的。 在文档中查看所有端点 →

从您的流水线发布所有语言版本。

创建一个带作用域的密钥,POST 一个任务,并接入 Webhook。首月基础费由我们承担。

获取 API 密钥