自建翻译加速节点

Omni AI Translator · 翻译加速服务(Relay)

最后更新:2026-11-11 · 对应服务版本 v0.1.0

加速节点是一个只缓存、不代理的译文缓存服务。插件在翻译前先向它查询缓存, 命中的直接展示;未命中的照常发往翻译接口,翻译完成后再把结果异步写回缓存。
它永远拿不到你的 API Key,也从不代理翻译请求。

项目方官方节点:https://translator.makabonka.com/api。 自 v0.5.0 起,插件设置中的「官方加速节点」即指向该地址;下文的自建配置与它一致, 可以直接照抄。

1. 它做什么,不做什么

会做不会做
按「原文 + 源语言 + 目标语言」缓存译文 不持有、不转发、不存储你的 API Key
被查询时返回命中的译文 不代理翻译请求,不代替翻译接口
接受匿名写入(upsert 覆盖) 不做用户身份认证——任何人都能读写
按真实客户端 IP 做基础限流 不记录原文与译文日志

2. 快速开始

远端部署推荐:从 GHCR 拉取与 release 同 tag 的预构建镜像,不在服务器编译:

curl -fsSL https://raw.githubusercontent.com/Aiden-FE/omni-ai-translator/master/docker-compose.yml -o docker-compose.yml
curl -fsSL https://raw.githubusercontent.com/Aiden-FE/omni-ai-translator/master/.env.example-compose -o .env

# 编辑 .env,锁定与已发布 Release 一致的镜像 tag(示例)
# RELAY_IMAGE=ghcr.io/aiden-fe/omni-relay:v0.5.1
docker compose pull
docker compose up -d

从 v0.5.0 起,GitHub Releases 页面可查看当前版本号;镜像同时提供完整 tag(v0.5.1)、 纯版本 tag(0.5.1)和正式版的 latest。

也可以克隆仓库并从源码构建:

git clone https://github.com/Aiden-FE/omni-ai-translator.git
cd omni-ai-translator
cp .env.example-compose .env
docker compose build relay
docker compose up -d

验证服务与缓存是否都就绪:

curl http://localhost:3000/healthz
# {"status":"ok","version":"0.1.0","redis":"ok"}

redis:"ok" 表示容器和缓存都正常。若返回 "redis":"down" 且 HTTP 503, 说明 relay 起来了但 Redis 没通——检查 docker compose logs redis。

本地开发或调试服务代码时,用 compose 启动真实 Redis,宿主运行 relay:

pnpm install
docker compose -f docker-compose.dev.yml up -d redis
REDIS_URL=redis://127.0.0.1:16379 pnpm --filter @omni/relay dev

Redis 默认映射到宿主 16379,避免与本机 Redis 冲突。停止并清理数据: docker compose -f docker-compose.dev.yml down --volumes。

3. 部署在反向代理之后(务必读)

不配 TRUST_PROXY 会导致限流误伤。 加速节点按真实客户端 IP 计桶限流。如果你把服务放在 nginx / Cloudflare / Caddy 等反向代理后面,而没有开启 TRUST_PROXY,所有请求都会被算作来自 127.0.0.1,于是所有用户共用一个限流桶——用得多的用户会把其他人一起限流掉。

确认自己确实位于反向代理之后(查看访问日志里的来源地址不是客户端真实 IP),然后:

# .env
TRUST_PROXY=true
docker compose up -d

反过来,如果端口直接暴露给客户端、前面没有任何代理,就保持 TRUST_PROXY=false—— 此时客户端可以伪造 X-Forwarded-For 绕过限流。

nginx 参考配置:

location / {
    proxy_pass http://127.0.0.1:3000;
    proxy_set_header Host              $host;
    proxy_set_header X-Real-IP         $remote_addr;
    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

4. 环境变量

变量默认值说明
PORT3000监听端口
REDIS_URLredis://localhost:6379Redis 连接串
CACHE_TTL_SECONDS2592000(30 天)缓存条目过期时间
TRUST_PROXYfalse是否信任反向代理的 X-Forwarded-For;仅在确实位于代理之后时开启
RATE_LIMIT_WINDOW_SECONDS60限流窗口(秒)
RATE_LIMIT_LOOKUP120每窗口每 IP 的查询次数上限(宽松)
RATE_LIMIT_COMMIT30每窗口每 IP 的写入次数上限(严格——写才是成本大头)

限流阈值是防误伤的默认值,不是安全边界。若节点面向公网开放,建议在边缘层(Cloudflare 等) 再加一层规则。

5. 在插件中配置

  1. 打开插件设置页(点击扩展图标 → 右上角设置)。
  2. 在「翻译加速」区域选择自定义域名。
  3. 填入你的节点地址,例如 https://accel.example.com(不带结尾斜杠)。
  4. 点击测试连通,确认返回 redis:"ok"。
  5. 选择加速范围:默认仅免 Key 内置源;若希望自有源也走加速,改为「所有翻译源」。

加速默认关闭。启用是显式选择:原文会发往你所选的节点。

6. 信任模型:务必理解

加速节点能看到你翻译的每一段原文,并且可以返回任意内容作为「译文」。 服务没有任何机制能验证返回的译文是否被篡改——这是开放缓存模型的固有代价。

7. HTTP API

三个端点,路径带 /v1 前缀;契约只增字段不删字段,可向后兼容。

POST /v1/cache/lookup — 批量查缓存

curl -X POST http://localhost:3000/v1/cache/lookup \
  -H 'content-type: application/json' \
  -d '{
    "items": [
      { "id": "a", "text": "Hello World", "targetLang": "zh" }
    ]
  }'

响应只包含命中的条目——未出现在 hits 里的 id 即未命中:

{ "hits": [ { "id": "a", "translatedText": "你好,世界" } ] }

POST /v1/cache/commit — 批量写入(upsert)

curl -X POST http://localhost:3000/v1/cache/commit \
  -H 'content-type: application/json' \
  -d '{
    "items": [
      { "id": "a", "text": "Hello World", "targetLang": "zh",
        "translatedText": "你好,世界" }
    ]
  }'
# { "accepted": 1 }

写入是 upsert:同一条目再次提交会覆盖旧译文并重置 TTL。

GET /healthz — 健康检查

{ "status": "ok", "version": "0.1.0", "redis": "ok" }

限制与容错

项行为
单次请求条数最多 200 条,超出部分被忽略
单条原文长度最多 5000 字符
非法单条跳过该条,同批合法条目照常处理(不整批失败)
错误响应{ "error": "..." },配合 4xx / 5xx 状态码

缓存身份 = 规范化原文(NFKC + 去首尾空白 + 折叠连续空白)+ 源语言 + 目标语言, 再取 sha256。规范化与哈希都在服务端完成,客户端不参与。

8. 运维与排障

现象原因与处理
healthz 返回 redis:"down"Redis 未就绪或连不上。检查 docker compose logs redis 与 REDIS_URL。
多人同时被限流(429)大概率是没设 TRUST_PROXY=true,所有流量共用一个桶。回看第 3 节。
命中率很低缓存按「原文 + 语言」精确匹配。页面内容差异大、或目标语言频繁切换时命中率天然低。
译文不更新该条目已被缓存。用插件的重试功能覆盖,或等待 TTL(默认 30 天)过期。
内存持续增长确认 Redis 使用了 maxmemory + allkeys-lru(compose 已默认配置)。

查看日志:

docker compose logs -f relay

服务只记录条数与命中数,不记录原文和译文。