API 参考

本文档对应 api/app.js 中 Express 应用的行为,以及 api/routes/ 下的路由处理程序。

限制和行为

项目
JSON 请求体大小最高 2 MB (express.json({ limit: '2mb' }))
每次请求目标数1–36 语言代码
批量项目数每个批量请求 1–100
模型standard(默认)或 advanced(仅付费层;见下文)

每月令牌额度(免费层): 在调用模型前,API 估算令牌数大致为 ceil(content_length / 4) × (number_of_targets + 1),且仅对 free 层,如果估算超过剩余的月度额度(FREE_TIER_MONTHLY_TOKENS,默认 100000),则拒绝请求,返回 429 / token_limit_reached。付费层不受 enforceTokenCap 中此预检查的限制;使用情况仍会被记录。

速率限制: 当配置了 Upstash Redis(UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKEN,且 URL 不包含占位符 your-instance)时,按层级应用每分钟限制:免费 5,入门 30,成长 60,规模 120,企业无限制。达到限制时,响应为 429,错误为 error: "rate_limit_reached"。如果未配置 Redis,则跳过速率限制(见 rateLimit.js)。

成功的速率限制响应可能包含 X-RateLimit-LimitX-RateLimit-RemainingX-RateLimit-Reset


GET /health

无需认证。

响应 200

{
  "status": "ok",
  "timestamp": "2025-03-23T12:00:00.000Z"
}

GET /languages

无需认证。

返回支持语言的规范列表(代码、显示名称、RTL 标志)。共有 36 条目;代码是翻译端点中 targets 唯一接受的值。

响应 200

{
  "languages": [
    { "code": "en", "name": "English", "rtl": false },
    { "code": "ar", "name": "Arabic", "rtl": true }
  ]
}

来源:api/utils/languages.js


POST /translate

需要 Authorization: Bearer <api_key>

将单个 content 字符串翻译成 targets 中列出的所有语言。模型返回一个 单一 JSON 对象,其键 完全 是请求的语言代码,值是翻译后的字符串(见 formatPrompts.js)。

请求体

字段类型必需描述
contentstring非空待翻译字符串。
targetsstring[]非空有效语言代码数组(最多 36 个)。
formatstringplainmarkdownjsonhtml 之一。若省略,则从 content 自动检测格式。
sourcestring模型的源语言提示;可选。
modelstringstandard(默认)或 advancedadvanced 需付费层(免费层返回 403)。

响应 200

{
  "translations": {
    "es": "...",
    "fr": "..."
  },
  "usage": {
    "input_tokens": 120,
    "output_tokens": 340,
    "total_tokens": 460,
    "model": "standard",
    "detected_format": "markdown",
    "detection_confidence": 0.95
  }
}

仅当省略 format 并执行自动检测时,才会出现 detected_formatdetection_confidence

示例(cURL)

curl -sS -X POST "https://api.usepolylingo.com/v1/translate" \
  -H "Authorization: Bearer $POLYLINGO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "{\"title\":\"Hello\"}",
    "format": "json",
    "targets": ["fr", "de"]
  }'

示例(Python 3)

pip install requests
import os, requests

url = "https://api.usepolylingo.com/v1/translate"
headers = {
    "Authorization": f"Bearer {os.environ['POLYLINGO_API_KEY']}",
    "Content-Type": "application/json",
}
r = requests.post(url, json={
    "content": "<p>Hello <strong>world</strong></p>",
    "format": "html",
    "targets": ["es"],
}, timeout=120)
r.raise_for_status()
print(r.json()["translations"]["es"])

POST /translate/batch

需要 Authorization: Bearer <api_key>

依次处理每个项目(每个项目调用一次模型)。如果任何项目失败,API 返回 500,且不返回该请求的部分结果。

请求体

字段类型必需描述
items数组每个元素:id(字符串)、content(字符串)、可选 format
targetsstring[]/translate 相同规则。
sourcestring可选源语言提示。
modelstringstandardadvanced(与 /translate 规则相同)。

响应 200

{
  "results": [
    { "id": "welcome", "translations": { "fr": "...", "de": "..." } },
    { "id": "goodbye", "translations": { "fr": "...", "de": "..." } }
  ],
  "usage": {
    "total_tokens": 900,
    "input_tokens": 400,
    "output_tokens": 500,
    "model": "standard"
  }
}

示例

curl -sS -X POST "https://api.usepolylingo.com/v1/translate/batch" \
  -H "Authorization: Bearer $POLYLINGO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      { "id": "a", "content": "Hello", "format": "plain" },
      { "id": "b", "content": "## Title", "format": "markdown" }
    ],
    "targets": ["es", "it"]
  }'

POST /jobs

需要 Authorization: Bearer <api_key>

将翻译任务入队,并立即返回 job_id。翻译在后台运行——无论内容大小,均无 HTTP 超时风险。轮询 GET /jobs/:id 获取结果。

当翻译大型文档(长 Markdown、多目标语言)且请求时间可能超过 HTTP 客户端或代理超时时,使用此端点替代 POST /translate

请求体

字段类型必需描述
contentstring非空待翻译字符串。
targetsstring[]非空有效语言代码数组(最多 36 个)。
formatstringplainmarkdownjsonhtml 之一。省略时自动检测。
sourcestring源语言提示;可选。
modelstringstandard(默认)或 advanced

响应 202

{
  "job_id": "a1b2c3d4-...",
  "status": "pending",
  "created_at": "2025-03-23T12:00:00.000Z"
}

GET /jobs/:id

需要 Authorization: Bearer <api_key>

轮询通过 POST /jobs 提交的任务状态。每 5–10 秒轮询一次。任务归提交用户所有——其他用户返回 404

响应(待处理 / 处理中)

{
  "job_id": "a1b2c3d4-...",
  "status": "pending",
  "created_at": "2025-03-23T12:00:00.000Z",
  "updated_at": "2025-03-23T12:00:00.000Z",
  "completed_at": null,
  "queue_position": 3
}

statuspending(等待工作者)或 processing(工作者已领取)。queue_position(从 1 开始)表示在此任务之前严格创建的待处理或处理中任务数——用于进度 UI。计数查询失败时省略。

响应(已完成)

{
  "job_id": "a1b2c3d4-...",
  "status": "completed",
  "created_at": "2025-03-23T12:00:00.000Z",
  "updated_at": "2025-03-23T12:00:02.000Z",
  "completed_at": "2025-03-23T12:00:02.000Z",
  "translations": {
    "es": "...",
    "fr": "..."
  },
  "usage": {
    "input_tokens": 120,
    "output_tokens": 340,
    "total_tokens": 460,
    "model": "standard"
  }
}

响应(失败)

{
  "job_id": "a1b2c3d4-...",
  "status": "failed",
  "error": "Model returned invalid JSON"
}

示例(JavaScript)

const API = 'https://api.usepolylingo.com/v1'
const headers = {
  'Authorization': `Bearer ${process.env.POLYLINGO_API_KEY}`,
  'Content-Type': 'application/json',
}

// 1. 提交
const submit = await fetch(`${API}/jobs`, {
  method: 'POST',
  headers,
  body: JSON.stringify({ content: longMarkdown, format: 'markdown', targets: ['de', 'fr'] }),
})
const { job_id } = await submit.json()

// 2. 轮询
while (true) {
  await new Promise(r => setTimeout(r, 10_000))
  const poll = await fetch(`${API}/jobs/${job_id}`, { headers })
  const job = await poll.json()
  if (job.status === 'completed') { console.log(job.translations); break }
  if (job.status === 'failed')    { throw new Error(job.error) }
  // 可选:显示进度(queue_position 从 1 开始,未排队时省略)
  if (job.queue_position != null) console.log(`队列位置: ${job.queue_position}`)
}

GET /usage

需要 Authorization: Bearer <api_key>(标准密钥查找——内部绕过路径)。

返回已认证用户的当前日历月令牌使用情况。

响应 200

{
  "period_start": "2025-03-01T00:00:00.000Z",
  "period_end": "2025-03-31T23:59:59.000Z",
  "tokens_used": 12000,
  "tokens_included": 100000,
  "tokens_remaining": 88000,
  "overage_tokens": 0,
  "tier": "free"
}

tokens_includedtokens_remaining 对于 enterprisenull(报告中无限额度)。


内容格式

支持的 format 值:plainmarkdownjsonhtml

格式保留翻译
plain换行 / 段落所有可见文本
markdown语法、链接(URL 不变)、代码块(逐字)散文和链接文本
json键、结构、非字符串类型仅字符串值
html标签和属性文本节点和适当属性(见提示)

应用中的 RTL 和方向

对于 plainmarkdown 输出,API 仅返回翻译文本——不添加 dir="rtl" 或包装元素。显示阿拉伯语、希伯来语或波斯语时,请在 UI 中设置文本方向(CSS direction、父元素的 dir 属性或框架的国际化布局)。

对于 html 格式,翻译后的标记可能在适合 RTL 的目标语言中包含 dir="rtl";见 formatPrompts.jsscripts/test-translation.js 中的 HTML 测试。


错误响应

错误尽可能以 JSON 格式返回:

{
  "error": "invalid_request",
  "message": "人类可读的详细信息"
}
HTTPerror何时
400invalid_request缺失/无效的请求体字段(如空 content、错误的 targets
400invalid_formatformat 不在支持集合中
400invalid_languagetargets 中未知代码
401invalid_api_key缺失/格式错误的 Authorization,未知密钥,被撤销密钥
403advanced_not_available免费层使用 model: "advanced"
429token_limit_reached免费层月度上限超出(预检查)
429rate_limit_reached每分钟 RPM 限制(启用 Redis 时)
500translation_error模型/网络失败;可安全重试
404not_foundGET /jobs/:id — 任务不存在或属于其他用户
500server_errorPOST /jobs — 入队失败;可安全重试

GET /usage 如果 Supabase 查询失败,可能返回带通用消息的 500


底层模型(仅供参考)

API 仅暴露 standardadvanced。实际的 OpenAI 模型 ID 配置在 api/utils/modelRouter.js 中,且不会在 API 响应中返回。

API 参考 | PolyLingo | PolyLingo