Initial commit

This commit is contained in:
谭凯
2026-01-19 09:51:07 +08:00
commit 9ef82393be
174 changed files with 22285 additions and 0 deletions
+51
View File
@@ -0,0 +1,51 @@
# 开发者避坑指南 (Developer's Survival Guide)
这份文档总结了 EPUB 翻译器开发过程中的血泪教训。在修改代码前,**务必阅读此文档**。
## 🔴 核心原则 (Core Principles)
### 1. 奥卡姆剃刀原则 (KISS)
**不要自作聪明。**
* **错误案例**:为了“美观”或“规范”,给 ID 加上方括号 `[p_001]`,甚至试图让 LLM 返回 JSON 结构。
* **后果**:LLM 经常搞错括号的全角/半角,或者漏掉闭合括号,导致正则解析极其痛苦,甚至产生 `SyntaxError`
* **最佳实践****ID 就用纯文本 `p_xxxxx`。** 解析就用 `find()` 和字符串切片。越简单越不容易出错。
### 2. 单一真理源 (Single Source of Truth)
**不要在模块间传递散乱的数据。**
* **最佳实践****Manifest (清单) 是唯一的真理。** Profile, Glossary, Winner Model 都应该直接存储在 Manifest 的 metadata 中,而不是依赖外部临时文件。
---
## 🚫 常见陷阱 (Pitfalls)
### 1. Python 语法陷阱
* **f-string 中的正则**
* *Bad*: `rf'\[{id}\]'``rf"[{id}]"`。在 f-string 中使用反斜杠转义非常容易出错,尤其是涉及引号嵌套时。
* *Good*: 使用字符串拼接 `r'\[' + id + r'\]'`。虽然丑一点,但绝对安全。
* **Unhashable Dict**:
* *Bad*: `glossary = profile.get('glossary', {{}})`。双花括号 `{{}}` 在 Python 中会被解释为集合 `{dict()}`,而 dict 是不可哈希的,导致 `TypeError`
* *Good*: `glossary = profile.get('glossary', {})`
### 2. Prompt Engineering
* **不要让 LLM "解释" 它的翻译。**
* 它一旦开始解释,解析器就很难把正文抠出来。必须在 System Prompt 中严令禁止。
* **Context Injection**:
* 注入 Glossary 时,格式越简单越好(如 `Term -> Translation`),不要用复杂的 JSON 结构,这会消耗 Token 且容易被模型忽略。
### 3. EPUB 结构处理
* **不要随意丢弃 Item。**
* 默认复制所有非 Document 资源。对于 Document,要么替换为双语版,要么原样保留。
* **不要重建 Spine 顺序。**
* 不要试图自己去猜页面顺序。严格按照 `original_book.spine` 的顺序来构建新书。
---
## ✅ 推荐工作流 (Workflow)
1. **修改提取逻辑时** -> 必须同时检查 `get_valid_text_elements` 是否被 `Builder` 复用。
2. **修改 Prompt 时** -> 必须同步更新 `LLMClient` 的解析逻辑。
3. **调试 LLM 输出时** -> 使用 `raw_chat_completion` 接口进行单元测试。
---
*Last Updated: v0.05*