mirror of
https://github.com/sweetwisdom/everything-claude-code-zh.git
synced 2026-03-21 22:10:09 +00:00
docs: 完成所有文档的中文翻译并应用到项目
This commit is contained in:
46
translation_workdir/README.md
Normal file
46
translation_workdir/README.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Translation Workdir (翻译工作归档)
|
||||
|
||||
本目录包含 `everything-claude-code` 项目的自动化中文翻译工具链。它是非原项目内容,仅用于维护本仓库的中文化版本。
|
||||
|
||||
## 目录结构
|
||||
- `scripts/`: 核心自动化脚本
|
||||
- `batch_processor.py`: 扫描全量 MD,比对指纹,执行 AI 翻译或从缓存恢复。
|
||||
- `apply_translations.py`: 将翻译好的预览文件覆盖回原位。
|
||||
- `prompts/`: 翻译提示词模版,包含项目背景和术语保护规则。
|
||||
- `cache/`: 翻译数据库
|
||||
- `translation_db.json`: 存储英文指纹及其对应的中文内容,实现一秒还原和零成本同步。
|
||||
|
||||
## 日常维护流程 (SOP)
|
||||
|
||||
### 1. 同步上游更新
|
||||
当你发现原作者的英文仓库有更新时,先拉取并覆盖本地(建议在 `main` 分支):
|
||||
```bash
|
||||
# 添加并获取上游仓库(仅需执行一次)
|
||||
git remote add upstream https://github.com/affaan-m/everything-claude-code.git
|
||||
git fetch upstream
|
||||
|
||||
# 拉取最新英文版并覆盖本地(此时本地会变回英文)
|
||||
git checkout upstream/main -- .
|
||||
```
|
||||
|
||||
### 2. 执行自动化翻译
|
||||
运行脚本。它会自动对比 `translation_db.json`,秒速恢复未改动的文件,并仅对新增/修改的文件调用 AI 翻译:
|
||||
```bash
|
||||
python3 translation_workdir/scripts/batch_processor.py
|
||||
```
|
||||
|
||||
### 3. 应用翻译并覆盖
|
||||
检查 `_zh` 目录无误后,执行物理替换。这会将翻译后的文件移回原位,并清理临时目录:
|
||||
```bash
|
||||
python3 translation_workdir/scripts/apply_translations.py
|
||||
```
|
||||
|
||||
### 4. 提交你的汉化版本
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "sync: update chinese translation to match upstream latest"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
---
|
||||
*注:本目录应提交至 Git 仓库以持久化翻译资产。*
|
||||
298
translation_workdir/cache/translation_db.json
vendored
Normal file
298
translation_workdir/cache/translation_db.json
vendored
Normal file
File diff suppressed because one or more lines are too long
113
translation_workdir/prompts/translate_zh.md
Normal file
113
translation_workdir/prompts/translate_zh.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# SYSTEM INSTRUCTION: TOOL_USE_ONLY
|
||||
你是一个“仓库文档中文化”的**批处理执行内核**(batch translation kernel)。你必须跳过一切开场白、解释、复述与闲聊;你的输出必须严格遵循下方“输出协议”。
|
||||
|
||||
---
|
||||
|
||||
## 0. 任务目标(必须遵守)
|
||||
对仓库 `everything-claude-code` 的 Markdown / 配置文档做**语义级工程翻译**(让中国工程师读得懂、用得顺),同时**不破坏**其作为 AI 工具(Claude Code / agentic workflow)配置与指令文本的可机器理解性与可执行性。
|
||||
|
||||
---
|
||||
|
||||
## 1. 输入与输出协议(强约束)
|
||||
### 输入
|
||||
- 源文件路径:`@{{SOURCE_PATH}}`
|
||||
- 目标文件路径:`{{TARGET_PATH}}`
|
||||
|
||||
### 输出(唯一合法行为)
|
||||
1) 使用 `read_file` 读取 `@{{SOURCE_PATH}}`
|
||||
2) 生成“翻译后的完整文件内容”(保持结构与功能不变)
|
||||
3) **立即且仅能**通过 `write_file` 将结果写入 `{{TARGET_PATH}}`
|
||||
|
||||
> 除了对 `write_file` 的工具调用外,不得在终端打印任何翻译内容或解释性文字。
|
||||
> 如果工具调用完成后系统强制要求输出文本,只允许输出单词:`SUCCESS`
|
||||
|
||||
---
|
||||
|
||||
## 2. 项目背景(用于确定术语与语气)
|
||||
该仓库是一个面向 Claude Code 的生产级配置库,核心由 **Agents / Skills / Hooks / Rules / Commands / Contexts** 等组成:
|
||||
- 这些 Markdown 文件不仅是“给人看的文档”,更是“给 AI 执行的指令与规约”。
|
||||
- 翻译必须做到:**中文可读可用 + 机器语义不变**。
|
||||
|
||||
目标读者:熟悉工程实践的中国软件工程师(偏资深)。
|
||||
|
||||
---
|
||||
|
||||
## 3. 翻译总体原则(语义优先 + 功能不变)
|
||||
### 3.1 语义级工程翻译
|
||||
- 允许重排语序、补足省略主语、改写不自然表达,以提升中文工程可读性。
|
||||
- 保持原意、边界条件、约束、前后逻辑一致;不得“合理发挥”。
|
||||
|
||||
### 3.2 结构与可执行性优先(功能保真)
|
||||
- **必须保留**原有 Markdown 层级结构:标题等级、列表层级、引用块、分隔线、表格、编号、空行、强调样式等。
|
||||
- 链接结构必须保持:`[text](url)` 的 `url` 不变;图片路径不变。
|
||||
- 不得引入会改变解析/渲染/执行语义的字符(例如误改反引号数量、误删冒号、误改缩进导致 YAML/JSON 失效)。
|
||||
|
||||
---
|
||||
|
||||
## 4. 严禁翻译 / 必须原样保留(最重要)
|
||||
以下内容**逐字原样保留**,不得翻译、不得改动大小写、不得增删空格(除非原文明显排版错误且不影响语义解析):
|
||||
|
||||
### 4.1 代码与命令(绝对保留)
|
||||
- 任何代码块 fenced code(```...``` / ~~~...~~~)中的**非注释**内容
|
||||
- 行内代码:`` `like_this` ``
|
||||
- Shell 命令、CLI 子命令、参数与 flags:以 `/` 开头的命令、以 `--` 开头的参数、`-x` 短参等
|
||||
- 文件路径/通配符/Glob:`/abs/path`、`./rel/path`、`**/*.md`
|
||||
- 环境变量与占位符:`$VAR`、`${VAR}`、`{{SOURCE_PATH}}`、`{{TARGET_PATH}}`、`@{{SOURCE_PATH}}`
|
||||
- 标识符/函数/类/接口/字段名:如 `allowedTools`、`PreToolUse`、`PostToolUse`、`Stop`、`TodoWrite`、`read_file`、`write_file`
|
||||
- 正则表达式与模式串:`^...$`、`(?i)`、`/pattern/`
|
||||
- JSON / YAML / TOML / INI 等配置中的 **Key**(键名)与结构符号(冒号、引号、括号、逗号、缩进等)
|
||||
|
||||
### 4.2 YAML Frontmatter(必须可解析)
|
||||
若文件包含 YAML Frontmatter(`---` 包裹):
|
||||
- **Key(键名)绝不翻译**:如 `name:`、`description:`、`instructions:` 等
|
||||
- 值(value)若为自然语言说明,可翻译;但其中出现的任何代码/标识符/路径/命令仍需按 4.1 原样保留
|
||||
- 保持 Frontmatter 的缩进、引号、列表结构完全一致
|
||||
|
||||
---
|
||||
|
||||
## 5. “可以翻译”的范围与细则
|
||||
### 5.1 可翻译内容
|
||||
- 段落叙述、说明文字、注释性解释、操作指南、注意事项、标题、列表项中的自然语言部分
|
||||
- 表格中自然语言列(但表格结构与对齐符必须保留)
|
||||
|
||||
### 5.2 代码注释(允许翻译,但不能改代码)
|
||||
在代码块中,**仅当确定是注释**时允许翻译注释文本,并且:
|
||||
- 必须保持注释符号与代码部分不变(如 `#`、`//`、`/* */`、`<!-- -->`)
|
||||
- 不得移动/删除任何影响执行的 token
|
||||
- 若注释与代码混行,确保代码 token 完全不变,只替换注释自然语言
|
||||
|
||||
---
|
||||
|
||||
## 6. 术语策略(面向工程师,首现双显)
|
||||
- 首次出现的核心概念,建议采用:**中文(English)**
|
||||
例:生命周期钩子(Hooks)、智能体(Agent)、技能(Skill)、工作流(Workflow)
|
||||
- 之后可只用中文或沿用英文,以“更易读、更不歧义”为准。
|
||||
- 推荐术语(可按语境微调,但需全文件一致):
|
||||
- Agent → 智能体(Agent)/ 代理(Agent)(二选一并保持一致)
|
||||
- Skill → 技能(Skill)
|
||||
- Hook → 钩子(Hook)/ 生命周期钩子(Hook)
|
||||
- Workflow → 工作流(Workflow)
|
||||
- Tool → 工具(Tool)
|
||||
- Context → 上下文(Context)
|
||||
- Prompt → 提示词(Prompt)
|
||||
- Session → 会话(Session)
|
||||
- Eval → 评测(Eval)
|
||||
- Guardrail / Safety → 安全护栏 / 安全约束(视语境)
|
||||
|
||||
---
|
||||
|
||||
## 7. 翻译自检(在 write_file 前进行)
|
||||
在调用 `write_file` 前,必须在脑中完成以下检查(不输出检查过程):
|
||||
1) **保真性**:所有关键字/工具名/路径/命令/flags/正则/Key 是否 100% 原样保留?
|
||||
2) **结构性**:Markdown 层级、代码围栏、表格分隔、链接 URL、图片路径是否完全保留?
|
||||
3) **可读性**:中文是否工程化、简洁、无口水、无机器翻译腔?
|
||||
4) **一致性**:同一术语在同文件内是否一致?首现是否双显(如有必要)?
|
||||
|
||||
---
|
||||
|
||||
## 8. 执行指令(立即开始)
|
||||
- 读取:`@{{SOURCE_PATH}}`
|
||||
- 翻译:按以上规则生成中文版本
|
||||
- 写入:对 `write_file` 写入 `{{TARGET_PATH}}`,内容为“翻译后的完整文件内容”
|
||||
- 完成后:如必须输出文本,仅输出 `SUCCESS`
|
||||
|
||||
59
translation_workdir/scripts/apply_translations.py
Normal file
59
translation_workdir/scripts/apply_translations.py
Normal file
@@ -0,0 +1,59 @@
|
||||
import os
|
||||
import shutil
|
||||
import argparse
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="将翻译后的文件应用回原目录")
|
||||
parser.add_argument("--dry-run", action="store_true", help="只显示将要执行的操作,不实际移动")
|
||||
args = parser.parse_args()
|
||||
|
||||
# 扫描所有以 _zh 结尾的目录或文件
|
||||
targets = []
|
||||
for item in os.listdir("."):
|
||||
if item.endswith("_zh") or "_zh.md" in item:
|
||||
targets.append(item)
|
||||
|
||||
if not targets:
|
||||
print("未发现任何翻译后的目标 (_zh)。")
|
||||
return
|
||||
|
||||
print(f"发现以下翻译内容: {targets}")
|
||||
|
||||
confirm = "y" if args.dry_run else input("确认要将这些翻译应用回原文件吗?原文件将被覆盖!(y/n): ")
|
||||
if confirm.lower() != 'y':
|
||||
print("操作已取消。")
|
||||
return
|
||||
|
||||
for item in targets:
|
||||
if os.path.isdir(item):
|
||||
# 处理目录,例如 agents_zh -> agents
|
||||
original_dir = item.replace("_zh", "")
|
||||
for root, _, files in os.walk(item):
|
||||
for f in files:
|
||||
src_file = os.path.join(root, f)
|
||||
rel_path = os.path.relpath(src_file, item)
|
||||
dst_file = os.path.join(original_dir, rel_path)
|
||||
|
||||
if args.dry_run:
|
||||
print(f"[DRY-RUN] 覆盖: {dst_file}")
|
||||
else:
|
||||
os.makedirs(os.path.dirname(dst_file), exist_ok=True)
|
||||
shutil.move(src_file, dst_file)
|
||||
|
||||
if not args.dry_run:
|
||||
shutil.rmtree(item)
|
||||
print(f"已清理目录: {item}")
|
||||
|
||||
elif os.path.isfile(item) and item.endswith("_zh.md"):
|
||||
# 处理根目录文件,例如 README_zh.md -> README.md
|
||||
original_file = item.replace("_zh.md", ".md")
|
||||
if args.dry_run:
|
||||
print(f"[DRY-RUN] 覆盖: {original_file}")
|
||||
else:
|
||||
shutil.move(item, original_file)
|
||||
print(f"已替换文件: {original_file}")
|
||||
|
||||
print("\n应用完成。" if not args.dry_run else "\n模拟运行完成。")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
120
translation_workdir/scripts/batch_processor.py
Normal file
120
translation_workdir/scripts/batch_processor.py
Normal file
@@ -0,0 +1,120 @@
|
||||
import os
|
||||
import argparse
|
||||
import subprocess
|
||||
import hashlib
|
||||
import json
|
||||
import sys
|
||||
|
||||
# 注入代理配置
|
||||
PROXY_CONFIG = {
|
||||
"http_proxy": "http://127.0.0.1:8442",
|
||||
"https_proxy": "http://127.0.0.1:8442",
|
||||
"no_proxy": "localhost,127.0.0.1,::1,127.0.0.0/8,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12"
|
||||
}
|
||||
|
||||
def get_file_hash(file_path):
|
||||
with open(file_path, 'rb') as f:
|
||||
return hashlib.md5(f.read()).hexdigest()
|
||||
|
||||
def main():
|
||||
os.environ.update(PROXY_CONFIG)
|
||||
|
||||
# 定义翻译工作区的基本路径(相对于项目根目录)
|
||||
WORKDIR = "translation_workdir"
|
||||
CACHE_PATH = os.path.join(WORKDIR, "cache", "translation_db.json")
|
||||
DEFAULT_PROMPT = os.path.join(WORKDIR, "prompts", "translate_zh.md")
|
||||
|
||||
parser = argparse.ArgumentParser(description="Gemini CLI 翻译自动化归档工具")
|
||||
parser.add_argument("--prompt", default=DEFAULT_PROMPT, help="提示词模板路径")
|
||||
parser.add_argument("--limit", type=int, default=None, help="限制处理文件数")
|
||||
parser.add_argument("--force", action="store_true", help="强制调用 AI 重译")
|
||||
parser.add_argument("--model", default="gemini-3-flash-preview", help="模型名称")
|
||||
args = parser.parse_args()
|
||||
|
||||
# 1. 扫描项目中所有的 .md 文件 (排除工作目录本身)
|
||||
all_md_files = []
|
||||
for root, dirs, files in os.walk("."):
|
||||
if any(x in root for x in [WORKDIR, "bak", "node_modules", ".git", "_zh"]):
|
||||
continue
|
||||
for f in files:
|
||||
if f.endswith(".md") and not f.endswith("_zh.md"):
|
||||
all_md_files.append(os.path.abspath(os.path.join(root, f)))
|
||||
|
||||
if not os.path.exists(args.prompt):
|
||||
print(f"错误: 提示词文件不存在: {args.prompt}")
|
||||
return
|
||||
|
||||
with open(args.prompt, 'r') as f:
|
||||
prompt_template = f.read()
|
||||
|
||||
# 加载翻译指纹数据库
|
||||
db = {}
|
||||
if os.path.exists(CACHE_PATH):
|
||||
try:
|
||||
with open(CACHE_PATH, 'r') as f: db = json.load(f)
|
||||
except: pass
|
||||
|
||||
print(f"\n>>> 发现 {len(all_md_files)} 个 Markdown 待处理文件")
|
||||
|
||||
processed = 0
|
||||
restored = 0
|
||||
|
||||
for src in all_md_files:
|
||||
if args.limit and (processed + restored) >= args.limit: break
|
||||
|
||||
rel_from_root = os.path.relpath(src, os.getcwd())
|
||||
# 计算 _zh 路径逻辑
|
||||
parts = rel_from_root.split(os.sep)
|
||||
if len(parts) > 1:
|
||||
target_rel_path = os.path.join(f"{parts[0]}_zh", *parts[1:])
|
||||
else:
|
||||
name, ext = os.path.splitext(parts[0])
|
||||
target_rel_path = f"{name}_zh{ext}"
|
||||
|
||||
abs_dst = os.path.abspath(target_rel_path)
|
||||
os.makedirs(os.path.dirname(abs_dst), exist_ok=True)
|
||||
|
||||
h = get_file_hash(src)
|
||||
|
||||
# 恢复逻辑
|
||||
if not args.force and src in db and db[src].get("md5") == h:
|
||||
translated_content = db[src].get("content")
|
||||
if translated_content:
|
||||
with open(abs_dst, 'w') as f:
|
||||
f.write(translated_content)
|
||||
print(f"[RESTORED] {rel_from_root}")
|
||||
restored += 1
|
||||
continue
|
||||
|
||||
# 翻译逻辑
|
||||
print(f"----------------------------------------------------------------")
|
||||
print(f"[{processed + restored + 1}] 翻译中 (AI): {rel_from_root}")
|
||||
|
||||
instruction = (
|
||||
f"任务:翻译文件 @{src} 并保存为中文。\n"
|
||||
f"目标路径:{abs_dst}\n"
|
||||
f"提示词指令:\n{prompt_template}"
|
||||
)
|
||||
|
||||
cmd = ["gemini", "-m", args.model, "-y", "--allowed-tools", "write_file", "-p", instruction]
|
||||
|
||||
try:
|
||||
process = subprocess.run(cmd)
|
||||
if process.returncode == 0:
|
||||
if os.path.exists(abs_dst):
|
||||
with open(abs_dst, 'r') as f:
|
||||
new_content = f.read()
|
||||
db[src] = {"md5": h, "content": new_content}
|
||||
with open(CACHE_PATH, 'w') as f:
|
||||
json.dump(db, f, indent=2)
|
||||
processed += 1
|
||||
print(f">>> [OK] 内容已同步至数据库\n")
|
||||
else:
|
||||
print(f">>> [ERR] {rel_from_root} (Code: {process.returncode})")
|
||||
except Exception as e:
|
||||
print(f">>> [EXC] {rel_from_root}: {str(e)}")
|
||||
|
||||
print(f"\n任务结束。恢复: {restored}, 翻译: {processed}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user