一个地址,接上资源与译文。
从游戏文件下载、项目介绍到共享译文,在同一平台完成接入。下载保留官方文件与哈希;译文按项目与原文版本查询,未就绪时先显示原文。
Modrinth / CurseForge · 模组 / 资源包 / 光影 / 整合包 · 12 种目标语言,默认简体中文 zh-Hans · 策略 minecraft-v1。标题保留原名;简介和正文翻译。游戏内文本、文件翻译、更新日志和账号计费尚未开放。
游戏下载与地址映射
网页、译文接口和游戏下载共用平台入口。计划使用 https://mirror.bugg.icu;域名与 HTTPS 完成切换前请使用实际部署地址。以下路径加在同一根地址后,下载不需要接入密钥。
| 内容 | 原始来源 | 平台路径前缀 |
|---|---|---|
| 游戏清单 | piston-meta.mojang.com / launchermeta.mojang.com | /mc/game/ |
| 游戏文件与运行时清单 | piston-data.mojang.com / launcher.mojang.com | /v1/objects/、/v1/packages/、/v1/products/java-runtime/ |
| Java 文件 | java-runtime / Mojang | /java/v1/ |
| 依赖库 | libraries.minecraft.net | /maven/ |
| 原版 assets | resources.download.minecraft.net | /assets/{前两位}/{SHA-1} |
| 加载器 | Forge / NeoForge / Fabric / Quilt | /maven/、/neoforge-maven/、/fabric-meta/、/fabric-maven/、/quilt-meta/、/quilt-maven/ |
| 模组 | cdn.modrinth.com / edge.forgecdn.net | /mods/modrinth/、/mods/curseforge/ |
Mojang /mc/game/ 前缀后的内容映射官方同名路径;其他表中前缀保留对应官方 URL 的路径。模组路径移除官方域名后追加完整文件路径,例如 Modrinth 的 /data/…/versions/…/file.jar 追加至 /mods/modrinth/。Java 文件将 piston-data.mojang.com/v1/… 映射为 /java/v1/…。Forge / Mojang Maven 共用路径按已知组名选择上游,不能代理任意网址。
GET /mc/game/version_manifest_v2.json
GET /assets/ab/ab…完整SHA-1
HEAD /maven/org/lwjgl/…/file.jar
Range: bytes=0-1023元数据保留官方内容;启动器需要继续映射清单中的下载 URL,支持 GET、HEAD、Range、307 跳转,下载后验证官方长度与哈希。失败可重试平台地址。请勿将申请密钥或管理 Cookie 转发到跳转目标。
模组默认不保存本地文件并跳转原站,可按后台设置启用缓存、备份或重定向;不批量抓取模组站。游戏下载当前不承诺完整 BMCLAPI API 兼容,特别是 Forge 查询接口。OptiFine、LiteLoader、旧 Oracle Java、第三方整合包文件暂不提供。下方 OpenAPI 描述译文与管理接口;二进制下载以本节路径为准。
多个公开来源,自动生成文件映射
平台内置阿里云、华为云、南京大学和 Maven Central,可在同一后台添加来源、启停或调整国内优先。文件扫描与 SHA-1 核验在后台按批次执行;每个文件保留多个已核验候选,优先国内,同地区按服务端探测耗时选择。下载请求只查询索引,失败候选退出,继续其他候选或官方路径。探测耗时不代表每位用户的实际吞吐。
Maven 源填写仓库根地址;兼容 Minecraft 源填写下载根地址。公开目录可增量遍历并发现独有文件;不提供目录的仓库只匹配已知资源。自建来源也可发布 JSON 文件清单,后台选择「文件清单 JSON」并填写地址。只接受同源 HTTPS 文件目标,目标需提供对应 .sha1。已有官方哈希不能被不同内容替换。
{
"files": [{
"path": "/maven/org/example/unique/1.0/unique-1.0.jar",
"url": "https://downloads.example.org/releases/unique-1.0.jar",
"sha1": "该文件的40位小写SHA1"
}]
}后台按源展示已核验文件、本地副本及下载跳转次数,文件明细每页 50 条。核验覆盖可以重叠;跳转次数不代表客户端下载完成。添加新源匹配成功后,可先预览空间,再移除相应本地副本,或开启默认关闭的自动清理。清理前重新检查远端校验、可达和大小;在用文件与其他共享引用保留。
来源扫描仅读取元数据、目录和校验文件,不抓取整个模组站。Linux 软件包只有与原清单文件实际相同时才能映射,不会把发行版 Java 包替换成 Mojang 运行时。
六类策略,共同的分发入口
游戏核心、加载器、模组、Java、依赖库、assets 分别配置。缓存模式由本机或健康下载节点提供;重定向直接访问官方;备份并重定向让用户直连上游,同时后台保存副本,确认上游故障后后续请求使用已完成备份。已经跳转的请求需要重试,未完成备份不能提供离线保证。
文件映射可让已核验依赖直接从 Maven Central 等公开仓库下载;匹配规则后不缓存。Linux 软件包与 Mojang 运行时文件格式不同,不能直接互换。空间上限可选优先新版本、LRU 或停止新增,保护版本不会强制淘汰;超过空间或出口预算时按健康下载节点、备用来源、官方顺序回退。
译文读取与文件下载按各自能力选路,同一节点可承担两种能力。译文节点通过主站审批与心跳进入目录;资源节点由管理员配置地址、权重与类别,每 20 秒检查健康,直达下载节点不再次跳转其他联邦节点。带宽预算用于请求准入,精确整形需要代理或系统限速。
部署自己的服务,加入平台网络
在 开发者中心 查看当前节点、测速和加入步骤。完整部署见仓库 README;译文缓存节点按 README 的“加入共享网络”配置;资源节点按 docs/资源节点部署.md 与 deploy/resource-node.example.json 配置。下载进程与翻译工作进程隔离,避免大文件任务阻塞翻译,网页和管理入口统一。
管理员在 平台设置 同时管理翻译供应商和下载策略、空间、流量、公开来源、下载节点及 Cloudflare。译文节点审批位于同一管理工作台的“服务节点”。Cloudflare 仅缓存匹配的公开文件;管理接口、Cookie、Authorization、译文生成与 SSE 绕过缓存。307 响应不可缓存,策略切换需要立即生效时清除旧 CDN 对象。
目标语言与无需翻译
选择资源内容语言
网页的“内容语言”控制资源简介与正文,界面导航仍使用中文。默认 zh-Hans,支持繁体中文、英语、日语、韩语、德语、法语、西班牙语、巴西葡萄牙语、俄语、乌克兰语、印度尼西亚语。完整列表以 GET /v1/capabilities 的 languages 为准;其中 code 用于请求,name 用于下拉显示,default_target_language 表示默认值。
resolve / ensure 请求体和 catalog 查询参数都可传 target_language,省略为简体中文。常见别名如 zh-CN、zh_TW、en-US 规范为 zh-Hans、zh-Hant、en;不支持的语言返回 400 unsupported_language_or_profile。语言与原文哈希是两个独立维度:切换目标语言不改变 mc-text-v1 哈希,也不能把目标语言填进原文 source_language。
GET /v1/catalog/search?target_language=ja&limit=20
// resolve / ensure 请求体中的语言:
"target_language": "ja"本地缓存、轮询、任务去重都必须包含规范化后的目标语言。切换语言后停止旧页面轮询,丢弃迟到响应;清空分页游标,从第一页查询。平台仅返回该语言的就绪状态与简介,搜索覆盖原文和当前语言译文。正文仍按需下载不可变 artifact;列表不会加载全部正文。原文更新后仅补译历史上请求过的语言,不会批量生成所有语言。
无需翻译是一种正常完成结果
兼容已有客户端,字段仍返回 state=ready、quality=original、原文 text 或 artifact,并添加 translation_required=false 和 no_translation_reason。当前原文无需翻译时,update.code=not_required、action=none,建议显示“无需翻译,保留原文”,停止轮询和 ensure;不要显示“AI 译文”或失败。
| no_translation_reason | 含义 | 模型调用 |
|---|---|---|
| project_name | 项目标题,或内容仅为项目原名 | 无 |
| empty_content | 空白或空文本 | 无 |
| technical_content | 仅有代码、版本号、网址、结构标记等受保护内容 | 无 |
| already_target_language | 可信来源明确标注原文与目标语言相同 | 无 |
| unchanged | 模型处理后全文未改变 | 首次可能有,后续复用缓存 |
前四类不占用模型 Token,模型日预算暂停期间也可完成本地处理。内容语言未知(und)时不靠字符猜测“已经是中文”;繁简转换、日本汉字等照常处理。首次 ensure 可能需要一次短暂的本地核验任务;结果缓存后不会反复排队。以上结论绑定原文哈希与上下文,原文变化后重新判断;不能把一个项目永久标成无需翻译。接口请求额度仍按申请字段数计算,不能把模型费用与防滥用配额混为一谈。
{
"state": "ready",
"translation": {
"quality": "original", "translation_required": false,
"no_translation_reason": "already_target_language",
"text": "An English description."
},
"update": {"code": "not_required", "action": "none"}
}上例仅列关键字段,完整必填字段与兼容性以 OpenAPI 为准。即使不需要翻译,正文依然按原有 Markdown / HTML 安全渲染,保留布局与原站入口;不要直接作为 HTML 注入。
接入需要申请密钥吗?
公开查询(resolve、source、catalog、artifact)无需申请;个人体验可继续使用一小时匿名会话。正式启动器可以在 开发者中心 提交名称、主页、联系信息及用途,获得待审批密钥。密钥只展示一次,请立即保存。
POST /v1/clients/applications提交 JSON:name、contact、website(HTTP 或 HTTPS)、purpose。返回 application_id、access_token、state=pending。- 携带
Authorization: Bearer bct_…调用GET /v1/clients/application查看审批状态。 - 管理员批准后,原密钥生效;ensure、jobs、events、feedback 和 refresh 可复用此凭据,无需每小时重新创建匿名会话。
待审批、驳回和撤销的密钥不能创建翻译任务,返回 403 client_key_pending / client_key_rejected / client_key_revoked。未知密钥返回 401 invalid_client_key。默认独立额度为每小时 1000 字段、每分钟 600 请求,管理员可调整;IP 防滥用限额与全局模型预算仍然适用。用量按申请字段数统计,重复幂等请求不重复计数。密钥仅以 SHA-256 存储,撤销后下次请求立即失效。
桌面启动器内置的共同密钥可被提取,不能把它当成用户身份凭据。需要保密的应用密钥应保存在开发者自己的后端,或让用户配置个人凭据。申请方密钥与平台上游 OpenAI 模型密钥完全独立。
管理台
平台管理 使用独立管理员令牌。可修改 OpenAI 兼容 Base URL(包含 /v1)、API Key、模型、推理档位和预算。保存后供后续模型调用使用;已在执行的调用不会取消。密钥留空保留原值,读取设置只返回 api_key_configured,不回显密钥。运行配置原子保存到数据库同目录 runtime-config.json(Linux 权限 0600),重启后优先于环境配置;服务需要对该目录有写权限。备份应同时包含数据库与此私密文件。
GET /v1/admin/settings
POST /v1/admin/settings
GET /v1/admin/clients?after=<next_cursor>
POST /v1/admin/clients
Authorization: Bearer <管理员令牌>
// 配置示例:省略 api_key 保留当前密钥
{"base_url":"https://api.example.org/v1","model":"gpt-6.1-sol","reasoning_effort":"medium"}
// 批准并设限额
{"id":"client_…","state":"active","fields_per_hour":1000,"requests_per_minute":600}列表状态与正文状态分别判断
catalog 的 field_states.summary 与 field_states.body 分别表示当前版本的就绪情况。translation_state=ready 表示两者都就绪;只有简介就绪时为 partial。localized_summary 存在不代表正文已经生成。详情页按 resolve 的具体字段显示状态,正文缺失时明确提示“正文正在准备,暂时显示原文”,不能把简介就绪显示成整篇就绪。
快速开始
API 根地址:https://mirror.bugg.icu/v1。读取公开译文无需密钥;申请生成使用短时匿名会话。大模型凭据只存放在平台服务端。
先检查服务能力
curl https://mirror.bugg.icu/v1/capabilities读取 generation_available、目标语言和批量上限;生成关闭时,已有译文仍可查询。示例使用已收录的 Sodium 项目 AANobbMI。
准备一份可核验的原文
curl https://mirror.bugg.icu/v1/projects/modrinth/AANobbMI/source实际启动器通常已经从原站拿到 description / body,可直接计算哈希。此接口主要用于平台 Web 和接入调试;它不会在读取时访问原站。若返回 project_not_indexed,先申请匿名会话,再 POST /projects/{provider}/{project_id}/refresh,等待返回的任务完成。
把翻译与浏览解耦
搜索、滚动、详情和下载先正常完成。在后台读取本地译文缓存,再批量查询平台;任何网络错误都保留原文。以下命令行示例为便于理解会等待翻译,接入 GUI 时放到后台任务中。
稳定身份与原文哈希
项目主键是 provider + project_id。创建时间、作者、标签均为可变元数据,不能拼进项目主键。第一版实体固定为 project,entity_id 必须等于 project_id。
| 字段 | 输入来源 | format |
|---|---|---|
| title | 项目原名 | plain |
| summary | Modrinth description / CurseForge summary | plain |
| body | Modrinth 原始 body | markdown |
| body | CurseForge 原始 description HTML | html |
- 仅把 CRLF、CR 规范成 LF。
- 构造下列五个字符串字段,键按 ASCII 升序排列,不添加空白。
- 输出原生 Unicode 的 UTF-8 JSON 字节,计算 SHA-256,添加
sha256:前缀。
{"field":"summary","format":"plain","schema":"mc-text-v1","source_language":"und","text":"Original summary"}不要先剥除 HTML、裁剪长度、去首尾空白或做 Unicode NFC/NFD 转换。中文和 emoji 不应变成 \uXXXX 后再参与哈希。未知语言固定 und;不能自行换成 en。请跑通全部公开测试向量再接入。
先查译文,缺失时自动排队
3.1 批量查询 · POST /translations:resolve
{
"target_language": "zh-Hans", "profile": "minecraft-v1",
"items": [{
"request_id": "visible-row-1",
"resource": {"provider":"modrinth","project_id":"AANobbMI","entity_type":"project","entity_id":"AANobbMI"},
"fields": [{"field":"summary","source_hash":"sha256:这里替换为实际的64位小写十六进制值"}]
}]
}每批最多 50 个项目、每项最多 3 个字段。服务只读本地数据库,不在此接口调用原站或模型。仅在 state=ready 且 matches_request=true 时使用 translation;还需读取 is_current 和 update 判断版本提示。
3.2 创建短时会话
POST /v1/sessions/anonymous
Content-Type: application/json
{"client_id":"your-launcher"}
// 成功响应(access_token 仅示意)
{"access_token":"…","token_type":"Bearer","expires_in":3600,"scopes":["translations:ensure","jobs:read","feedback:write"]}只在需要生成时创建会话,内存复用到过期前;不要每次轮询申请。会话属于当前调用者,任务票据不能跨会话共享。
3.3 请求生成 · POST /translations:ensure
Authorization: Bearer <access_token>
Idempotency-Key: <本次逻辑请求唯一的 UUID>
Content-Type: application/json
// 在 resolve 请求体基础上添加:
"purpose": "visible_list"请求体仍是完整 JSON 对象;上面只展示新增字段。每批最多 20 项;详情使用 purpose=detail。服务从可信原站核验哈希,只翻译公开资源,不能提交任意文本。HTTP 202 表示接受排队,不表示译文完成。同一个逻辑请求的网络重试复用幂等键;更换请求体必须更换键,否则返回 409。
3.4 完成后替换,不打断操作
用 resolve 每 2–5 秒批量查询当前可见资源,或订阅任务事件。滚动离开的资源停止轮询;详情切换后丢弃旧页面返回的结果。后台生成仍会继续,其他启动器也能复用结果。
正文 artifact
简介直接位于 translation.text。正文通过 translation.artifact.artifact_sha256 下载:
GET /v1/artifacts/{artifact_sha256}用响应的原始字节校验 SHA-256(此处路径里的哈希不带 sha256:),再验证 resource、field、source_hash、target_language 和 profile。artifact 不可变,支持 ETag 与一年缓存;不要在校验前重新序列化 JSON。自己拼接可信服务源下的 artifact 路径,避免跟随不可信 URL。
原文更新时,告诉用户发生了什么
state 描述请求哈希的译文状态;update 描述它与平台当前原文的关系。两者一起使用,不能把“有历史译文”解释成“已经是最新版”。
| update.code | 含义 | 建议界面行为 |
|---|---|---|
| up_to_date | 请求与当前原文一致,译文就绪 | 显示译文 |
| translation_pending | 首次翻译未完成 | 显示原文和“正在准备译文” |
| source_updated | 客户端持有旧原文,新版译文可用 | 刷新原站内容,重算哈希 |
| update_pending | 原文已更新,新译文尚未排队 | 显示原文,自动 ensure |
| update_queued | 新版译文排队或延后重试 | 提示“原文已更新,新版本译文正在排队” |
| update_running | 新版翻译正在执行 | 提示“原文已更新,正在翻译新版本” |
| update_failed | 新版翻译暂时失败 | 保留原文并提示失败 |
{
"field": "summary",
"state": "running", "matches_request": false, "is_current": true,
"requested_source_hash": "sha256:…", "current_source_hash": "sha256:…",
"update": {
"code": "update_running", "source_changed": true,
"previous_translation_available": true,
"current_translation_state": "running",
"notice": "原文已更新,正在翻译新版本", "action": "ensure"
}
}action=refresh_source:刷新客户端原文再查询,不能继续用旧哈希提交新版翻译。action=ensure:按当前请求哈希申请生成,已有任务会去重。action=none:无需操作。可直接显示 notice,或按 code 自行本地化;不要用提示文案当程序判断条件。
旧译文必须明确标识
默认缺失时返回原文,不自动把旧译文放入 translation。只有请求 allow_stale=true 才可能返回 fallback_translation 与 fallback_source_hash;使用时持续显示“旧版译文,新版本翻译中”。即使 state=ready,若 is_current=false,它也只是与请求的历史哈希一致。
发现更新的时效
客户端从原站拿到新原文后,其新哈希会触发 ensure 的版本核验。平台后台默认按五分钟过期时间检查,每轮最多八个项目,拥塞或原站限流会延长实际延迟,不承诺五分钟内全库同步。freshness 只代表最近核验时间,不能作为原站绝未变化的保证。需要时可主动 refresh,受独立限额约束。
内容结构保留,原文与译文一致呈现
正文的 format 可能为 markdown 或 html,以实际响应为准。平台保留作者介绍中的标题层级、段落、列表、表格、链接和图片结构,翻译文字;代码、技术版本和 URL 使用占位符保护。不要直接展示原始标签文本,也不要把整个 HTML 文档当纯文本拼到页面上。
- Markdown 先解析为 HTML;HTML 使用内容片段。
- 原文与译文使用同一套 HTML 清洗规则,移除脚本、事件属性、iframe 和危险 URL。
- 再渲染到相同正文样式中;图片延迟加载,外链使用 noopener/noreferrer。
平台 Web 使用本地打包的 markdown-it 与 DOMPurify,不从第三方 CDN 加载脚本。保留介绍内容结构,不复制原站导航、广告或整站 CSS。客户端必须独立清洗,不能因为内容来自翻译平台就跳过防护。未经审查的原文与模型输出都不能直接注入 WebView。
项目资料、版本和依赖
详情页一次读取
GET /v1/projects/{provider}/{project_id}/detail?target_language=zh-Hans返回当前 source、target_language 和简介、正文两项 fields。字段状态与 resolve 相同;可用译文直接包含 translation.text,正文也无需额外下载。只有两项均为 state=ready 且 is_current=true 才显示“简介与正文已就绪”。请求读取期间显示“正在读取译文”,不要提前判断为“正在翻译”。尚未完成时显示对应字段的 update.notice,并同步修正列表状态。接口只读本地数据,不调用原站或模型;未收录返回 404,频繁更新时返回 503 并附 Retry-After。
列表仍使用轻量批量查询;需要校验正文原始字节或长期缓存的客户端继续使用不可变 artifact。公开详情地址为 /projects/{provider}/{project_id},首次 HTML 已包含可用内容,支持分享与搜索引擎读取。
原文、版本与记录
GET /v1/projects/{provider}/{project_id}/source
GET /v1/projects/{provider}/{project_id}/manifest
GET /v1/projects/{provider}/{project_id}/historysource 返回完整原始字段与 metadata;manifest 返回字段哈希、译文状态、更新时间和项目资料;history 提供原文、元数据变动和译文发布记录。只读接口不请求原站。
| metadata 字段 | 用途 |
|---|---|
| authors / created_at / updated_at | 作者、创建及原站更新时间,时间采用 ISO 8601 |
| tags / game_versions / loaders | 分类、支持的 Minecraft 版本、加载器 |
| icon_url / downloads / license | 图标、下载量和许可证,原站未提供则为空 |
| releases | 最近 12 个原站版本,包含发布时间、渠道、游戏版本与依赖 |
| releases[].dependencies | project_id / version_id / name / relation / url |
| metadata_complete | false 表示部分资料拉取失败,应标为暂缺,不应推断“没有依赖” |
依赖属于具体发布文件,必须按所选版本展示。relation:required 必需、optional 可选、incompatible 不兼容、embedded 内置、tool 工具。列表的 dependency_count 仅对应最近版本;正文、标签和作者变化不会更换项目 ID。
搜索与分页
GET /v1/catalog/search?q=优化&kind=mod&limit=20
GET /v1/catalog/projects?limit=20
// 下一页:原样传回 next_cursor,同时保持 q / kind / limit 一致
GET /v1/catalog/search?q=优化&kind=mod&limit=20&cursor=<URL编码后的next_cursor>响应提供 projects、total_count 和 next_cursor;游标为空表示末页。limit 为 1–50,kind 为 mod / resourcepack / shader / modpack。q 检索已收录的标题、简介和中文译文,不会实时搜索全站资源。
使用索引和 keyset 分页,不执行深层 OFFSET。游标签名绑定目标语言、筛选条件与每页数量,有效期 15 分钟;过期、篡改或筛选不一致时返回 409 cursor_expired,应清空分页栈重载首页。客户端保存访问过的游标实现上一页。资源库会持续新增,总数可能变化;不提供任意深页跳转或固定快照保证。
失败任务与再次访问
客户端自动重试
resolve 只读,不会启动模型或回源。失败且没有可用结果的字段返回 state=missing、last_failure、可重试的 error,以及 update.action=ensure。这使已有启动器再次访问资源时能沿正常未命中流程申请重试;后台的真实任务状态仍为 failed,供管理员筛选和查看。
{
"state": "missing",
"last_failure": {
"code": "model_timeout",
"failed_at": "2026-10-26T00:00:00Z",
"retry_after_seconds": 60
},
"update": {"action": "ensure"}
}上例仅展示关键字段。新访问使用新的幂等键;同一逻辑请求的网络重试继续复用原键,否则无法区分重放与新一轮重试。平台复用原任务和票据,失败后申请的自动重试至少冷却 60 秒;已有客户端的本地提交冷却仍适用。活动任务不会重复创建,已翻译的片段继续复用,成功结果不会被重跑。原文哈希已变化时先按 refresh_source 读取新原文,不重试旧哈希。
管理员手动重试
在翻译任务页按“成功 / 失败”筛选,失败行和详情中均可点击重试。管理员请求跳过失败冷却,仍遵守全局预算与队列上限;额度耗尽时返回 deferred 和恢复等待时间。
POST /v1/admin/tasks/{task_id}/retry
Authorization: Bearer <管理员令牌>
Content-Type: application/json
{}
// 202 示例
{"task_id":"task_…","state":"queued","retry_after_seconds":0}不存在的任务返回 404 task_not_found;成功或当前不可重试的任务返回 409 task_not_retryable;已在排队或执行的任务返回当前状态而不重复创建;队列满时返回 503 queue_full。原票据可能由 failed 回到 queued / deferred,旧 SSE 连接已结束时应重新查询或订阅。
后台会话与调用筛选
GET /v1/admin/session 验证 HttpOnly 管理会话,认证有效返回 authenticated=true。切页先恢复会话,再加载当前模块;数据请求失败不等同于认证失效。未登录返回 401,临时网络异常保留重连入口。
GET /v1/admin/usage?period=day&status=failed 按调用结果筛选明细,status 支持空值、succeeded、failed、pending、unknown。summary 始终统计整个周期,分页游标绑定周期及状态;切换筛选后从第一页开始。调用明细是历史账单,不直接重放某次模型请求;重试以翻译任务为单位,保留去重与片段复用。
轮询与 SSE 事件
GET /v1/jobs/{job_id}
Authorization: Bearer <创建该任务票据的会话令牌>
GET /v1/events?job_ids=<job_id1,job_id2>
Authorization: Bearer <同一会话令牌>任务状态包括 queued → verifying → running / partial → ready;deferred 表示稍后重试;failed 表示本轮失败,可通过新 ensure 或管理操作重试;source_mismatch 需要刷新原文。可读取分段完成量,不能把 partial 当成完整正文。
SSE 最多同时订阅 50 个票据,连接最长约 120 秒,断开后重连并重新读取任务状态。事件仅用于唤醒查询,最终结果以 resolve 为准。浏览器原生 EventSource 无法添加 Authorization,请使用 fetch 流或回退批量轮询,令牌不要放进 URL。
多语言完整示例
五种语言都演示:读取示例原文 → 计算哈希 → resolve → 缺失时创建会话和 ensure → 轮询 → 显示译文。示例可传第二个命令行参数指定目标语言,例如 python client.py AANobbMI ja;省略时为简体中文。五种实现都接受相同顺序的参数。示例只查询简介;正文 artifact 处理见第 03 节。可用环境变量 TRANSLATION_API 指向兼容平台,值应为 HTTPS 地址且包含 /v1。
正在读取示例…本地缓存键至少包含服务源、资源 ID、字段、原文哈希、语言和 profile。网络任务放在后台;401 重建会话、429 服从 Retry-After、5xx 指数退避。不要把模型密钥嵌进桌面程序。服务源切换后隔离缓存。
错误、限额与性能
| HTTP / code | 处理方式 |
|---|---|
| 400 invalid_request | 检查哈希、实体、批量上限和 JSON;不要原样高频重试 |
| 401 unauthorized | 会话过期,重新创建;管理接口使用独立管理员令牌 |
| 404 project_not_indexed | 申请 refresh 并等待任务,不要假设 source 会自动回源 |
| 409 idempotency_conflict | 同一键使用了不同请求体,修复幂等键管理 |
| 409 cursor_expired | 清空旧游标栈,重载首页 |
| 413 request_too_large | 请求 JSON 最大 64 KiB,拆分批次 |
| 429 rate_limited | 按 Retry-After 等待,不要并发重试风暴 |
| source_mismatch | 任务核验的哈希与原站不一致;刷新原文重算哈希 |
| budget_exhausted / deferred | 模型预算耗尽,后台延后,先保留原文 |
当前部署的默认限额
- resolve:每 IP 每分钟最多 1200 次;客户端应以可见区批量查询。
- 匿名会话:每 IP 每小时 10 个,令牌约 1 小时有效。
- ensure:每分钟 60 次;每 IP 和会话每小时最多 200 个字段。
- refresh:每 IP 每小时 10 次;反馈每小时 10 次。
- 模型另有全局日/月 token 和每日调用预算,队列和原站也有并发限制。
限额可能由部署方调整;以 capabilities 和错误响应为准。端到端耗时主要取决于原站、正文长度、队列和模型,不能把缓存查询延迟等同于首次翻译耗时。缓存命中不调用模型;分段缓存复用、WAL、批量 SQL、限量 LRU 和不可变 artifact 分别减少模型成本、锁竞争和网络开销。
接口索引
| 方法与路径(均位于 /v1) | 认证 | 用途 |
|---|---|---|
| GET /capabilities | 无 | 能力与上限 |
| POST /translations:resolve | 无 | 精确哈希查询 |
| POST /sessions/anonymous | 无 | 创建匿名会话 |
| POST /translations:ensure | 会话 + 幂等键 | 异步核验、生成 |
| GET /jobs/{job_id} · GET /events | 票据所属会话 | 进度与状态 |
| GET /artifacts/{artifact_sha256} | 无 | 不可变正文 |
| GET /projects/{provider}/{id}/source · manifest · history | 无 | 原文、资料、版本记录 |
| POST /projects/{provider}/{id}/refresh | 会话 | 核验原站更新 |
| GET /catalog/projects · /catalog/search | 无 | 本地译文库分页与搜索 |
| POST /feedback | 会话 | 提交译文问题 |
| GET /admin/overview | 管理员会话 | 运行状态、额度和反馈 |
| POST /admin/tasks/{task_id}/retry | 管理员会话 | 重新安排失败任务 |
| GET /admin/tasks · GET /admin/usage | 管理员会话 | 分页查看任务、Token 与费用 |
| POST /admin/settings · GET /admin/models | 管理员会话 | 模型、额度、费率配置 |
| GET /admin/session · POST /admin/session · DELETE /admin/session | 管理令牌 / 管理会话 | 建立或退出浏览器会话 |
管理接口只供平台管理员使用。精确请求与响应定义见 OpenAPI 3.1 文件;本页示例中的省略号和注释用于说明,不可直接作为有效 JSON 请求。项目正文和图片版权归原作者所有,界面保留原项目入口与 AI 译文标识。
启动器多节点与多路径
多节点只分担公开译文读取,不复制模型 Key、管理员令牌或私有任务。启动器始终保留一个固定的主服务地址(hub),从主服务获取经过审批且仍在线的镜像列表,再根据启动器到节点的真实往返时间选择路径。
启动器的选路流程
- 启动或网络切换时请求
GET /v1/federation/nodes。只接受固定主服务返回的列表,不接受资源页面、节点自身或用户配置注入的任意地址。 - 最多并行探测 7 个候选节点的
GET /v1/federation/health,确认ready、hub_url、node_id和协议版本都匹配。以启动器所在网络的真实 RTT 排序,区域字段只用于候选顺序。 - 把当前最快节点缓存 5 分钟。单次读取超时或返回 5xx 时立即将该节点冷却 30 秒并重试主服务;主服务不可用时保留原文或使用已验证的旧译文,并显示“正在准备译文”。
- 网络切换、节点冷却结束或定时器到期后在后台重新测速,不阻塞资源列表和详情页。请求使用 2.5 秒读取超时、最多 4 MiB 响应上限,不跟随镜像重定向。
哪些请求走镜像,哪些必须回主服务
镜像只允许公开读取:POST /v1/translations:resolve、GET /v1/catalog/*、GET /v1/capabilities、项目 manifest / source / history 和 GET /v1/artifacts/{sha256}。镜像请求会移除 Authorization、Cookie 和幂等键;公共译文响应仍按原文哈希、目标语言和 profile 精确匹配。
ensure、refresh、任务查询与事件、反馈、申请密钥、管理接口以及任何写请求始终发送到主服务。镜像不能创建翻译任务,也不能把启动器凭据转发给其他节点。译文命中仍应检查 matches_request、is_current 和 update.code;节点返回旧版本不能静默覆盖新原文。
接入示例
仓库中的 Python 多路径客户端 已实现发现、并行健康检查、节点冷却、凭据隔离和主服务回退。启动器可在浏览线程初始化一次:
network = TranslationNetwork("https://mirror.bugg.icu"); network.select(); result = network.call("translations:resolve", payload); job = network.call("translations:ensure", payload) # 自动回 hubJava、C、C++、C# 按相同规则实现即可:把 hub 作为唯一信任根,把节点地址当作短期读取路径;本地缓存键必须包含 hub、节点协议、项目 ID、字段、原文哈希、目标语言和 profile。节点列表的 expires_in 是建议刷新时间,不是授权有效期。
节点生命周期与统计
社区节点通过 POST /v1/federation/nodes 登记,由主服务管理员审批;节点每 30 秒发送心跳,连续 90 秒无心跳或探测失败会从发现列表移除。节点缓存命中、回源和客户端请求分开统计,不能将节点上报量相加当作独立启动器数量。详细部署和安全边界见 联邦节点指南。