Files
谭凯 7a93c52b42 feat: Release v0.10 - Modular Architecture & External Config
- Refactor codebase into src/ (preprocessing, translation, assembly)
- Add pipeline/ scripts for individual stages
- Externalize configuration to config/config.yaml
- Fix Cover Image preservation
- Update documentation and manuals
2026-01-31 22:49:44 +08:00

181 lines
7.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 预处理与回填层技术文档
本文档详细描述 EPUB 双语翻译器的预处理(Preprocessing)和回填(Backfill)层的技术方案、数据结构、问题解决方案,用于指导代码开发、调试和维护。
---
## 1. 架构概览
```
┌─────────────┐ ┌────────────────┐ ┌───────────────────┐
│ EPUB 文件 │ ──► │ EpubCleaner │ ──► │ book_structure.json│
└─────────────┘ └────────────────┘ └───────────────────┘
┌────────────────┐ ┌───────────────────┐
│FineGrainedExt. │ ──► │ manifest.json │
└────────────────┘ └───────────────────┘
┌────────────────┐ │
│ BackfillEngine │ ◄───────────┘
└────────────────┘
┌────────────────┐ ┌───────────────────┐
│BilingualBuilder│ ──► │ 输出 EPUB │
└────────────────┘ └───────────────────┘
```
---
## 2. 目录结构
```
work/
├── {book_name}/ # 每本书独立的工作目录
│ ├── book_structure.json # 书籍结构(会被复用)
│ ├── manifest.json # 翻译清单(持久化,Source of Truth
│ └── assets/ # 解压出的 EPUB 资源文件
│ └── OEBPS/images/... # 保留原始路径结构
└── translations/ # (可选) 翻译记忆或其他中间文件
```
**关键设计**`book_structure.json` **默认复用**。为避免 UUID 不一致导致回填失败,除非显式指定强制清理,否则程序优先读取现有的结构文件。
---
## 3. 数据结构定义
### 3.1 BookStructure (book_structure.json)
记录书籍的“骨架”,确保翻译后的章节能按正确顺序和层级重组。
```json
{
"metadata": {
"title": "书名",
"author": "作者",
"language": "en",
"identifier": "ISBN或UUID"
},
"spine": ["item_id_1", "item_id_2", ...], // 阅读顺序
"resources": {
"item_id_1": {
"href": "OEBPS/chapter1.xhtml",
"media_type": "application/xhtml+xml",
"content": "<html>...</html>", // 清理并注入ID后的HTML内容
"properties": "nav"
},
...
}
}
```
### 3.2 ManifestEntry (manifest.json)
翻译清单是全生命周期的核心,记录了所有待翻译段落的状态。
```json
[
{
"entry_id": "OEBPS/c3Z.xhtml#uuid-603ff3fb",
"file_path": "OEBPS/c3Z.xhtml",
"element_id": "uuid-603ff3fb",
"original_text": "φ1φHelloφ/1φ world.",
"placeholders": {
"1": "<b>",
"/1": "</b>",
"_prefix": "<p>",
"_suffix": "</p>"
},
"translated_text": "φ1φ你好φ/1φ 世界。",
"context": "body"
}
]
```
| 字段 | 类型 | 说明 |
|------|------|------|
| `entry_id` | str | **全局唯一ID** (`file_path#element_id`),用于精准追踪。 |
| `file_path` | str | 标识该段落属于哪一章,用于按章分组批处理。 |
| `element_id` | str | HTML DOM 元素的 ID,回填时的锚点。 |
| `original_text` | str | 经过智能抽提和占位符化后的文本,发送给 LLM。 |
| `placeholders` | Dict | 格式映射表,用于还原 HTML 结构。 |
| `translated_text`| str | 翻译结果(含占位符),初始为 null。 |
---
## 4. 预处理与抽提流程 (Extraction)
流程由 `FormatExtractor` 驱动,分为三个阶段:
### Step 1: 结构索引 (Structure Indexing)
* **动作**: 解析 OPF 文件,提取 Spine 和 Metadata。
* **目的**: 建立骨架,确定处理顺序。
### Step 2: 语义识别 (Semantic Detection)
* **动作**: 使用 `HeadingDetector` 分析 DOM 节点。
* **逻辑**:
* 匹配 `h1`-`h6` 正则,区分 `Chapter`(章)与 `Section`(节)。
* 识别 `blockquote` 或特定 class 判定 `Epigraph`(引言)。
* **目的**: 为 LLM 提供差异化的 Prompt(例如翻译标题时不要加句号)。
### Step 3: 智能抽提 (Smart Extraction - `_smart_extract_v3`)
这是核心算法,将 HTML 转换为“纯文本+占位符”。
1. **首尾分离 (Prefix/Suffix Separation)**:
* 将包裹文本的外层标签(如 `<p>`, `div`)剥离到 `_prefix``_suffix`
* **目的**: 极大减少 LLM 输入 Token,且防止 LLM 随意修改外层布局。
2. **首字下沉处理 (Drop Cap Handling)**:
* 检测并合并被 `<span>` 单独包裹的首字母(如 `<span class="drop">O</span>` + `nce``Once`)。
* **目的**: 修复语意割裂,让 LLM 看到完整的单词。
3. **占位符化 (Placeholder Mapping)**:
* 将内联标签(`<a>`, `<em>`)或公式替换为短码 `φIDφ`
* **目的**: 保护 HTML 属性不被“翻译”,降低噪声干扰。
4. **完整性校验 (Integrity Check)**:
* **逻辑**: 抽提后的文本(去占位符)与原始纯文本进行归一化比对,要求覆盖率 **100%**
* **兜底**: 若校验失败(如误删内容),回退到简单模式(只剥离首尾标签)。
---
## 5. 构建与回填流程 (Backfill & Build)
### 5.1 翻译回填
* 根据 `entry_id` 找到对应的 DOM 节点。
* 使用 `FormatRestorer``translated_text` 中的占位符(`φ1φ`)还原为原始 HTML 标签(`<b>`)。
* 根据模式(双语/单语)决定将新节点插入到原文后还是替换原文。
### 5.2 链接修复 (Link Repair)
`BilingualBuilder` 中执行:
1. **ID 补全**: 为缺失 ID 的 TOC 节点自动生成 UUID。
2. **死链检测**: 检查 TOC/Nav 指向的文件是否存在。
3. **模糊修复**: 尝试通过文件名后缀匹配(解决路径前缀变更问题)或特定重定向(如 `c0.xhtml` -> `cover.xhtml`)。
4. **坏死剔除**: 无法修复的死链将从目录中移除。
### 5.3 CSS 样式恢复
`EbookLib` 默认可能会重写 `<head>` 导致样式丢失。
* **逻辑**:
* 收集所有 CSS 资源。
* 在构建每个 HTML Item 时,显式计算 HTML 到 CSS 的**相对路径**。
* 强制调用 `item.add_link(..., rel='stylesheet', type='text/css')` 注入引用。
---
## 6. 常见问题排查
### 6.1 UUID 不匹配
**现象**: `WARNING - Element uuid-xxx not found`.
**原因**: 手动删除了 `book_structure.json` 但保留了 `manifest.json`,导致重新生成的 HTML ID 与清单记录不一致。
**解决**: 清空 `work/BookName` 目录重新运行,或确保两个 JSON 文件版本一致。
### 6.2 样式丢失
**现象**: 打开书面目全非,只有黑白文字。
**检查**: 解压 EPUB,查看 HTML `<head>` 是否有 `<link rel="stylesheet">`。如果没有,检查 `BilingualBuilder` 的 Step 4 逻辑。
### 6.3 翻译错位
**现象**: 译文出现在了错误的位置。
**检查**: 确认 `entry_id` 生成逻辑是否包含文件名,且文件名在处理过程中未被意外修改。