1. 为什么要把 claude-code-guide 文档翻译流程搬到统一通道
claude-code-guide 这个项目本身是一份围绕 Claude 代码工具的使用指南,英文原仓库里塞满了安装命令、环境变量、MCP 配置、子智能体提示词、故障排查这些内容。它的章节结构其实很清晰:入门指南、配置与环境、命令与用法、界面与输入、高级功能、安全与权限、自动化与集成、帮助与故障排除、第三方集成。问题在于,这份文档的更新频率不低,英文原仓库一有改动,中文版就得跟着动。如果每次靠人工逐段翻译,术语会飘、章节会错位、代码块里的注释也容易被顺手翻掉,最后产出的中文版和原仓库结构对不上,读者按目录找内容时就会迷路。
我试过用最原始的方式处理:把英文 Markdown 拉下来,丢进翻译工具,再手工贴回去。结果就是settings.json里的字段名被翻译了,ANTHROPIC_API_KEY变成了「人类学接口密钥」这种离谱东西,代码块里的claude config set -g theme dark也被改得面目全非。更麻烦的是,原仓库的目录层级和锚点链接一旦被破坏,中文版就失去了「结构对齐」这个最重要的价值。
所以这套流程的核心目标不是「把英文变中文」,而是三件事:第一,从原仓库稳定拉取英文文档,保留原始目录结构;第二,建立术语表和替换规则,让MCP、子智能体、环境变量这类词在全文中保持一致;第三,把批量翻译请求的 endpoint 统一改到 TaoToken 的 API 通道,用同一个 Key 完成翻译和校对,避免在多个平台之间来回切换。TaoToken 在这里扮演的是「统一 Key/API 通道」的角色,官网入口是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 地址是 https://taotoken.net/api ,不带 UTM 参数。
适合谁跟做?如果你正在维护一个中文技术文档仓库,或者你负责把某个英文工具指南本地化,又或者你只是想用脚本把一批 Markdown 批量翻译成中文并保持术语一致,这套流程都能直接套用。它不依赖特定的编辑器,核心就是「拉取 → 术语表 → 批量翻译 → 逐段校验 → 回写」这条链路。
这里要提前说清楚一个边界:TaoToken 是 API 通道,不是编辑器,也不是文档托管平台。翻译请求发出去、结果拿回来,最终写回文件、提交 Git 这些动作还是在你本地完成。把 endpoint 改到 TaoToken,只是让翻译请求走一个统一的入口,方便管理 Key 和模型选择。
2. TaoToken 前置准备:Key、模型与 claude-code-guide 翻译场景的对接
在开始写翻译脚本之前,需要先把 TaoToken 这边的准备工作做完。这一步不复杂,但顺序不能乱,否则后面脚本跑起来会一直报 401。
首先是拿 Key。进入 TaoToken 控制台,创建一个 API Key。这个 Key 后面会用在两个地方:一是翻译脚本里的Authorization请求头,二是如果你用 Claude Code 本身来辅助校对,也需要把它写进环境变量。控制台地址是 https://taotoken.net/console ,API Keys 管理页是 https://taotoken.net/api-keys 。创建的时候建议给 Key 起一个能认出来的名字,比如doc-translate,方便以后轮换。
拿到 Key 之后,确认你要用的模型 ID。翻译文档这种任务,对模型的要求是「长文本稳定、术语遵循好、输出格式不乱」。你可以先在模型对话页面里试一段 claude-code-guide 的英文原文,看看输出质量。模型对话入口是 https://taotoken.net/models ,这个页面可以直接粘贴一段英文文档,观察它是否会把代码块原样保留、是否会把MCP翻译成中文。如果试下来满意,就把对应的模型 ID 记下来,后面写进脚本的model字段。
接下来是 Base URL。TaoToken 的 API 地址是 https://taotoken.net/api ,注意这里不加任何 UTM 参数。在脚本里,请求的完整路径通常是https://taotoken.net/api/v1/messages或者兼容 OpenAI 格式的https://taotoken.net/api/v1/chat/completions,具体取决于你用的 SDK。如果你用的是 Anthropic 风格的调用,就把base_url设成https://taotoken.net/api,SDK 会自动拼接后面的路径。
这里有一个容易踩的坑:很多人会把 Key 直接写进脚本文件然后提交到 Git。千万不要这么做。正确的做法是把 Key 放进环境变量,脚本里用os.environ.get("TAOTOKEN_API_KEY")读取。如果你在本地跑,可以写一个.env文件,然后把它加进.gitignore。如果你用 Claude Code 来辅助校对,环境变量的名字建议用ANTHROPIC_API_KEY和ANTHROPIC_BASE_URL,这样 Claude Code 启动时会自动读取。
关于模型选择,翻译和校对可以用同一个模型,也可以分开。翻译阶段用输出稳定的模型,校对阶段用更擅长发现术语不一致的模型。如果你打算长期做这件事,可以考虑 Coding Plan,它更适合持续性的编码和 Agent 类任务,入口是 https://taotoken.net/coding-plan 。不过对于单纯的文档翻译,按量调用 API 就够了,不必一开始就上套餐。
还有一个细节:claude-code-guide 的原文里有大量代码块和配置片段,这些内容在翻译时必须原样保留。所以在准备阶段,最好先确认你的翻译脚本有没有「保护代码块」的逻辑。如果没有,后面术语替换规则里要专门处理。
3. 可复制配置:目录映射、术语表与翻译脚本的 settings 片段
这一节是整套流程的核心,所有配置都可以直接复制修改。先讲目录映射,再讲术语表,最后给出翻译脚本的配置片段。
目录映射的目的是让中文版和英文原仓库的结构一一对应。假设你把英文原仓库克隆到了./claude-code-guide-en,中文版输出到./claude-code-guide-zh。原仓库的目录结构大致是这样的:
claude-code-guide-en/ ├── README.md ├── docs/ │ ├── getting-started.md │ ├── configuration.md │ ├── commands.md │ ├── interface.md │ ├── advanced/ │ │ ├── subagents.md │ │ └── mcp.md │ ├── security.md │ ├── automation.md │ └── troubleshooting.md └── integrations/ └── deepseek.md对应的中文版目录保持同样的层级,只把文件名保留英文,内容翻译成中文。这样做的好处是锚点链接不会断,Git diff 也容易对比。你可以写一个mapping.json来显式声明映射关系:
{ "source_root": "./claude-code-guide-en", "target_root": "./claude-code-guide-zh", "file_map": { "README.md": "README.md", "docs/getting-started.md": "docs/getting-started.md", "docs/configuration.md": "docs/configuration.md", "docs/commands.md": "docs/commands.md", "docs/interface.md": "docs/interface.md", "docs/advanced/subagents.md": "docs/advanced/subagents.md", "docs/advanced/mcp.md": "docs/advanced/mcp.md", "docs/security.md": "docs/security.md", "docs/automation.md": "docs/automation.md", "docs/troubleshooting.md": "docs/troubleshooting.md", "integrations/deepseek.md": "integrations/deepseek.md" }, "skip_patterns": ["*.png", "*.jpg", "*.gif", "*.svg"], "preserve_blocks": ["code", "pre", "table"] }skip_patterns用来跳过图片资源,preserve_blocks声明哪些块在翻译时要原样保留。代码块和表格是最容易出问题的,表格里的英文表头如果被翻译了,列对齐就会乱。
接下来是术语表。术语表的作用是强制统一翻译,避免同一个词在不同章节出现不同译法。把下面这段存成glossary.json:
{ "MCP": "MCP", "Model Context Protocol": "模型上下文协议(MCP)", "subagent": "子智能体", "subagents": "子智能体", "environment variable": "环境变量", "API key": "API 密钥", "settings.json": "settings.json", "CLAUDE.md": "CLAUDE.md", "slash command": "斜杠命令", "keyboard shortcut": "键盘快捷键", "troubleshooting": "故障排除", "getting started": "入门指南", "configuration": "配置与环境", "commands": "命令与用法", "interface": "界面与输入", "advanced": "高级功能", "security": "安全与权限", "automation": "自动化与集成", "permission mode": "权限模式", "thinking keyword": "思考关键词", "token": "令牌", "prompt": "提示词", "agent": "智能体", "workflow": "工作流", "repository": "代码仓库", "pull request": "拉取请求(PR)", "diff": "差异补丁", "scope": "作用域", "stdio": "stdio", "SSE": "SSE", "HTTP": "HTTP" }注意MCP、settings.json、CLAUDE.md、stdio、SSE、HTTP这些词在术语表里是「原文映射到原文」,意思是翻译时不要动它们。Model Context Protocol这种全称第一次出现时给出中文加英文缩写,后面统一用MCP。
然后是翻译脚本的配置片段。下面这段是translate_config.json,它把 TaoToken 的 endpoint、模型、术语表路径、目录映射都串起来:
{ "api": { "base_url": "https://taotoken.net/api", "endpoint": "/v1/messages", "api_key_env": "TAOTOKEN_API_KEY", "model": "claude-sonnet-4-20250514", "max_tokens": 8192, "temperature": 0.2 }, "paths": { "mapping": "./mapping.json", "glossary": "./glossary.json", "cache_dir": "./.translate-cache", "log_dir": "./.translate-logs" }, "translation": { "chunk_size": 3000, "chunk_overlap": 200, "preserve_code_blocks": true, "preserve_tables": true, "preserve_links": true, "glossary_strict": true }, "review": { "enabled": true, "model": "claude-sonnet-4-20250514", "check_terms": true, "check_structure": true, "check_code_blocks": true } }temperature设成 0.2 是为了让输出更稳定,翻译任务不需要创造性。chunk_size设成 3000 字符左右,是因为太长的段落一次翻译容易丢内容,太短又会破坏上下文。chunk_overlap留 200 字符是为了让相邻块之间有重叠,避免句子被切断。
如果你用 Claude Code 本身来跑翻译,可以在项目根目录放一个.claude/settings.json,把环境变量写进去:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-your-taotoken-key", "ANTHROPIC_MODEL": "claude-sonnet-4-20250514" } }注意这里的ANTHROPIC_API_KEY要换成你自己的 Key,而且这个文件不要提交到公开仓库。如果你用 Cline 或者 CC Switch 这类工具,配置逻辑是一样的:Base URL 填https://taotoken.net/api,Key 填 TaoToken 的 Key,Model ID 填你选定的模型。这三件套缺一不可,只填 Base URL 不填 Key 会报 401,只填 Key 不填 Model ID 可能会走到默认模型上。
4. 验证请求:从单文件翻译到全量批处理的成功结果
配置写完之后,不要一上来就跑全量。先用一个文件验证请求能不能通,再逐步放大。
第一步,验证 API 连通性。写一个最小的 Python 脚本,只翻译一句话:
import os import json import urllib.request api_key = os.environ.get("TAOTOKEN_API_KEY") base_url = "https://taotoken.net/api" endpoint = "/v1/messages" payload = { "model": "claude-sonnet-4-20250514", "max_tokens": 256, "messages": [ { "role": "user", "content": "Translate the following into Chinese, keep 'MCP' unchanged: 'MCP extends Claude with external tools.'" } ] } req = urllib.request.Request( base_url + endpoint, data=json.dumps(payload).encode("utf-8"), headers={ "Content-Type": "application/json", "x-api-key": api_key, "anthropic-version": "2023-06-01" }, method="POST" ) with urllib.request.urlopen(req, timeout=60) as resp: result = json.loads(resp.read().decode("utf-8")) print(result["content"][0]["text"])跑通之后,你应该看到类似「MCP 通过外部工具扩展 Claude 的能力。」这样的输出,而且MCP没有被翻译。如果这里报 401,说明 Key 没读到或者 Key 无效;如果报local proxy failed,说明你的网络环境有问题,需要检查本地的网络配置;如果报reading choices之类的错误,通常是响应格式和你的解析代码不匹配,先打印原始响应看看结构。
第二步,单文件翻译。拿docs/getting-started.md做测试。脚本的逻辑是:读取英文原文,按段落切块,对每个块调用翻译接口,把结果拼回去,最后写入中文版对应路径。切块的时候要跳过代码块和表格,这两类内容直接原样复制。
import re def split_markdown(text, chunk_size=3000, overlap=200): lines = text.split("\n") chunks = [] current = [] current_len = 0 in_code = False for line in lines: if line.strip().startswith("```"): in_code = not in_code current.append(line) current_len += len(line) if current_len >= chunk_size and not in_code: chunks.append("\n".join(current)) current = current[-3:] if overlap else [] current_len = sum(len(l) for l in current) if current: chunks.append("\n".join(current)) return chunks这个切块函数会在代码块内部不切分,避免把一段配置命令切成两半。翻译每个块的时候,把术语表作为系统提示的一部分传进去:
def build_prompt(chunk, glossary): terms = "\n".join([f"- {k} => {v}" for k, v in glossary.items()]) return f"""你是一名技术文档翻译。请把下面的英文 Markdown 翻译成中文。 规则: 1. 代码块、行内代码、URL、文件路径原样保留,不要翻译。 2. 表格结构保留,表头可以翻译,但列对齐不能乱。 3. 以下术语必须按映射处理: {terms} 4. 只输出翻译后的 Markdown,不要加任何解释。 原文: {chunk} """第三步,全量批处理。把mapping.json里的每个文件都跑一遍,结果写入claude-code-guide-zh对应路径。跑的时候建议加一个缓存,每个块的翻译结果按内容哈希存到.translate-cache,这样重跑时不会重复调用接口。全量跑完之后,你会得到一份结构对齐的中文版,目录层级和英文原仓库完全一致。
成功的结果是什么样的?打开claude-code-guide-zh/docs/commands.md,你应该看到命令表格里的claude config set -g theme dark原样保留,而表格上方的说明文字已经变成中文。打开docs/advanced/mcp.md,MCP这个词全文统一,没有出现「模型上下文协议」和「MCP」混用的情况。打开docs/configuration.md,环境变量名ANTHROPIC_API_KEY没有被翻译,但旁边的注释变成了中文。
如果这些都对上了,说明翻译链路是通的。接下来就是校对阶段,把机器翻译的痕迹磨掉。
5. 本篇常见错排查:401、local proxy failed、reading choices 与 OAuth
翻译流程跑起来之后,最容易卡住的地方其实不是翻译质量,而是请求层面的报错。下面这几个是我在实际操作中遇到过的,按报错原文对照排查。
第一个,401 Unauthorized。这个报错的意思是 Key 没被正确识别。常见原因有三个:一是环境变量名写错了,比如脚本里读的是TAOTOKEN_API_KEY,但你实际导出的是TAOTOKEN_KEY;二是 Key 前面多了空格或者引号,比如export TAOTOKEN_API_KEY=" sk-xxx",那个空格会被带进请求头;三是请求头字段名不对,Anthropic 风格用x-api-key,OpenAI 风格用Authorization: Bearer,两者不能混。排查方法很简单,在脚本里打印一下api_key[:8]和api_key[-4:],确认 Key 被正确读取,再检查请求头字段名和你的 endpoint 是否匹配。
第二个,local proxy failed。这个报错通常出现在你本地有网络中间层的情况下。它不是说 TaoToken 不可用,而是你的请求在到达 TaoToken 之前就被本地环境拦住了。排查顺序是:先确认你的终端能不能直接访问https://taotoken.net/api,再检查环境变量里有没有HTTP_PROXY、HTTPS_PROXY这类设置。如果你之前为了别的用途设过这些变量,它们会干扰请求。临时清掉再试:
unset HTTP_PROXY unset HTTPS_PROXY unset ALL_PROXY然后重新跑一次单文件翻译。如果清掉之后能通,说明就是本地网络配置的问题,不是 Key 或 endpoint 的问题。
第三个,reading choices 相关报错。这个通常出现在你用的 SDK 期望 OpenAI 格式的响应,但实际拿到的是 Anthropic 格式,或者反过来。比如你用 OpenAI 的 Python SDK,把base_url设成https://taotoken.net/api,但请求路径拼成了/v1/chat/completions,而 TaoToken 在这个路径下返回的结构和 SDK 期望的不一致,解析choices字段时就会报错。解决办法是确认你的 SDK 和 endpoint 匹配:用 Anthropic SDK 就走/v1/messages,用 OpenAI SDK 就走/v1/chat/completions,不要交叉。如果你不确定,先用curl手动发一个请求,看返回的 JSON 顶层字段是content还是choices。
curl -s https://taotoken.net/api/v1/messages \ -H "Content-Type: application/json" \ -H "x-api-key: $TAOTOKEN_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -d '{"model":"claude-sonnet-4-20250514","max_tokens":64,"messages":[{"role":"user","content":"ping"}]}' | head -c 500第四个,OAuth 相关报错。如果你用 Claude Code 的/mcp命令连接远程 MCP 服务,可能会遇到 OAuth 认证失败。这个和翻译流程本身关系不大,但如果你在翻译过程中顺手配置了 MCP,就会碰到。排查方法是先确认 MCP 服务的 URL 和认证头是否正确,再用claude mcp list看服务有没有被正确加载。如果报的是OAuth相关错误,检查你的--header参数里Authorization的值有没有带Bearer前缀,有些服务要求带,有些不要求。
除了请求层面的报错,翻译质量层面也有几个高频问题。一是代码块被翻译,表现为npm install -g @anthropic-ai/claude-code变成了中文注释混排。这个要在切块阶段就跳过代码块,或者在提示词里强调「代码块原样保留」。二是术语不一致,比如同一篇文档里subagent一会儿译成「子智能体」一会儿译成「子代理」。这个靠术语表强制约束,glossary_strict设为true时,脚本会在翻译后做一次术语检查,发现不一致就重新翻译那个块。三是表格错位,表现为中文表头和英文内容对不齐。这个在翻译后要做一次表格结构校验,确认列数没变。
如果你在排查过程中需要对照接口文档,接入文档入口是 https://taotoken.net/doc ,API Keys 管理入口是 https://taotoken.net/api-keys 。这两个页面在排查 401 和 endpoint 问题时最常用。
6. 把翻译请求固定到 TaoToken:长期维护与语义一致的收尾动作
整套流程跑通之后,最后一步是把它固定下来,让后续的文档更新可以重复执行。这里的关键不是「一次性翻译完」,而是「原仓库更新时,中文版能低成本跟进」。
具体做法是写一个sync.sh,把拉取、翻译、校对、提交串起来:
#!/usr/bin/env bash set -euo pipefail EN_DIR="./claude-code-guide-en" ZH_DIR="./claude-code-guide-zh" # 1. 拉取英文原仓库最新内容 if [ -d "$EN_DIR/.git" ]; then git -C "$EN_DIR" pull --ff-only else git clone https://github.com/your-org/claude-code-guide.git "$EN_DIR" fi # 2. 对比文件哈希,只翻译有变化的文件 python3 scripts/diff_files.py --mapping mapping.json --cache .translate-cache # 3. 批量翻译 python3 scripts/translate.py --config translate_config.json # 4. 校对:术语一致性 + 结构对齐 + 代码块完整性 python3 scripts/review.py --config translate_config.json # 5. 输出报告 python3 scripts/report.py --output .translate-logs/report.mddiff_files.py的作用是计算每个英文文件的哈希,和缓存里的哈希对比,只把变化的文件交给翻译脚本。这样原仓库改了一个章节,你只需要重新翻译那一个文件,不用全量重跑。review.py做三件事:扫描中文版全文,检查术语表里的每个词是否按映射出现;对比中英文版的标题层级,确认 H2/H3 数量一致;检查代码块数量是否一致,防止翻译过程中代码块被吞掉。
校对阶段可以用模型对话页面来辅助。把中文版的一个章节贴进去,让模型检查「有没有术语不一致的地方」,入口是 https://taotoken.net/models 。这个页面适合做抽样检查,不适合全量跑,因为全量校对还是脚本更高效。
如果你打算长期维护这个中文版,建议把翻译脚本和术语表都放进版本控制,但 Key 和.env不要提交。术语表可以随着翻译过程不断补充,比如你发现permission mode在原文里有两种译法,就把它加进glossary.json,下次翻译就会自动统一。目录映射也可以扩展,原仓库新增了文件,就在mapping.json里加一条。
最后说一个实际经验:翻译技术文档时,最耗时的不是翻译本身,而是校对。机器翻译出来的内容,术语对了、结构对了,但读起来还是有「翻译腔」。我的做法是,第一遍用脚本全量翻译,第二遍用模型对话页面逐章润色,第三遍人工只读一遍,专门看代码块和配置片段有没有被误伤。这三遍下来,中文版的可读性会明显好于一次性翻译。
如果你在长期维护过程中需要更稳定的调用额度,可以了解一下 Coding Plan,入口是 https://taotoken.net/coding-plan 。它更适合持续性的编码和 Agent 类任务,文档翻译这种周期性任务按量调用 API 也完全够用。关键是,无论你用哪种方式,Base URL、Key、Model ID 这三件套保持一致,翻译请求就始终走同一个通道,不会因为换工具而重新配置一遍。