README_zh-CN.md
April 30, 2026 · View on GitHub
想读一本外文书,却担心失去原文的语境?EPUB Translator 可以将任何 EPUB 转换成双语版本,AI 翻译与原文并列展示。
无论你是在学习新语言、进行学术研究,还是纯粹享受外国文学,你都能在一本书中同时获得两种版本——保留所有格式、图片和结构。

在线版本
如果你希望在不进行本地安装的情况下体验 EPUB Translator,可以试试 Inkora - EPUB Translator,这是一个基于相同双语 EPUB 翻译流程构建的正式在线应用。你可以直接上传 EPUB 文件,在浏览器中体验主要功能。
安装
pip install epub-translator
系统要求: Python 3.11、3.12 或 3.13
快速开始
使用 OOMOL Studio (推荐)
最简单的使用方式是通过 OOMOL Studio 的可视化界面:
使用 Python API
from epub_translator import LLM, translate, language, SubmitKind
# 使用 API 凭证初始化 LLM
llm = LLM(
key="your-api-key",
url="https://api.openai.com/v1",
model="gpt-4",
token_encoding="o200k_base",
)
# 使用语言常量翻译 EPUB 文件
translate(
source_path="source.epub",
target_path="translated.epub",
target_language=language.CHINESE,
submit=SubmitKind.APPEND_BLOCK,
llm=llm,
)
带进度追踪
from tqdm import tqdm
with tqdm(total=100, desc="翻译中", unit="%") as pbar:
last_progress = 0.0
def on_progress(progress: float):
nonlocal last_progress
increment = (progress - last_progress) * 100
pbar.update(increment)
last_progress = progress
translate(
source_path="source.epub",
target_path="translated.epub",
target_language="Chinese",
submit=SubmitKind.APPEND_BLOCK,
llm=llm,
on_progress=on_progress,
)
API 参考
LLM 类
初始化翻译所需的 LLM 客户端:
LLM(
key: str, # API 密钥
url: str, # API 端点 URL
model: str, # 模型名称 (例如 "gpt-4")
token_encoding: str, # Token 编码方式 (例如 "o200k_base")
cache_path: PathLike | None = None, # 缓存目录路径
timeout: float | None = None, # 请求超时时间(秒)
top_p: float | tuple[float, float] | None = None,
temperature: float | tuple[float, float] | None = None,
retry_times: int = 5, # 失败重试次数
retry_interval_seconds: float = 6.0, # 重试间隔(秒)
log_dir_path: PathLike | None = None, # 日志目录路径
)
translate 函数
翻译 EPUB 文件:
translate(
source_path: PathLike | str, # 源 EPUB 文件路径
target_path: PathLike | str, # 输出 EPUB 文件路径
target_language: str, # 目标语言 (例如 "Chinese", "English")
submit: SubmitKind, # 如何插入译文 (REPLACE, APPEND_TEXT, 或 APPEND_BLOCK)
user_prompt: str | None = None, # 自定义翻译指令
max_retries: int = 5, # 翻译失败的最大重试次数
max_group_tokens: int = 2600, # 每个翻译组的最大 token 数
concurrency: int = 1, # 并发翻译任务数 (默认: 1)
llm: LLM | None = None, # 用于翻译和填充的单个 LLM 实例
translation_llm: LLM | None = None, # 翻译专用 LLM 实例(优先于 llm)
fill_llm: LLM | None = None, # XML 填充专用 LLM 实例(优先于 llm)
on_progress: Callable[[float], None] | None = None, # 进度回调函数 (0.0-1.0)
on_fill_failed: Callable[[FillFailedEvent], None] | None = None, # 错误回调函数
)
注意: 必须提供 llm 或同时提供 translation_llm 和 fill_llm。使用独立的 LLM 可以针对不同任务进行优化。
提交模式
submit 参数控制译文如何插入到文档中。使用 SubmitKind 枚举类型指定插入模式:
from epub_translator import SubmitKind
# 三种可用模式:
# - SubmitKind.REPLACE: 用译文替换原文(单语输出)
# - SubmitKind.APPEND_TEXT: 将译文作为内联文本附加(双语输出)
# - SubmitKind.APPEND_BLOCK: 将译文作为块级元素附加(双语输出,推荐)
模式对比:
-
SubmitKind.REPLACE: 用译文替换原文,创建单语翻译版本。适用于只需要目标语言版本的场景。 -
SubmitKind.APPEND_TEXT: 将译文作为内联文本紧接在原文后附加。两种语言出现在同一段落中,形成连续的阅读流。 -
SubmitKind.APPEND_BLOCK(推荐): 将译文作为独立的块级元素(段落)附加在原文后。这在两种语言之间创建清晰的视觉分隔,最适合双语对照阅读。
示例:
# 创建双语书籍(推荐)
translate(
source_path="source.epub",
target_path="translated.epub",
target_language=language.CHINESE,
submit=SubmitKind.APPEND_BLOCK,
llm=llm,
)
# 创建单语翻译
translate(
source_path="source.epub",
target_path="translated.epub",
target_language=language.CHINESE,
submit=SubmitKind.REPLACE,
llm=llm,
)
语言常量
EPUB Translator 提供了预定义的语言常量供用户使用,您可以使用这些常量而不是直接编写语言名称字符串:
from epub_translator import language
# 使用示例:
translate(
source_path="source.epub",
target_path="translated.epub",
target_language=language.CHINESE,
submit=SubmitKind.APPEND_BLOCK,
llm=llm,
)
# 您也可以使用自定义的语言字符串:
translate(
source_path="source.epub",
target_path="translated.epub",
target_language="Icelandic", # 对于不在常量列表中的语言
submit=SubmitKind.APPEND_BLOCK,
llm=llm,
)
使用 on_fill_failed 处理错误
使用 on_fill_failed 回调监控翻译错误。系统会自动重试失败的翻译,最多重试 max_retries 次(默认:5 次)。大多数错误会在重试过程中恢复,不会影响最终输出。
from epub_translator import FillFailedEvent
def handle_fill_error(event: FillFailedEvent):
# 只记录会影响最终 EPUB 的关键错误
if event.over_maximum_retries:
print(f"关键错误(已尝试 {event.retried_count} 次):")
print(f" {event.error_message}")
print(" 此错误将出现在最终的 EPUB 文件中!")
translate(
source_path="source.epub",
target_path="translated.epub",
target_language=language.CHINESE,
submit=SubmitKind.APPEND_BLOCK,
llm=llm,
on_fill_failed=handle_fill_error,
)
理解错误严重程度:
FillFailedEvent 包含:
error_message: str- 错误描述retried_count: int- 当前重试次数(1 到 max_retries)over_maximum_retries: bool- 错误是否为关键错误
错误分类:
-
可恢复错误(
over_maximum_retries=False):重试过程中发生的错误。系统会继续重试并可能自动解决这些问题。大多数情况下可以安全忽略。 -
关键错误(
over_maximum_retries=True):所有重试尝试后仍然存在的错误。这些错误会出现在最终的 EPUB 文件中,需要进行调查。
进阶用法:
在翻译调试期间进行详细日志记录:
def handle_fill_error(event: FillFailedEvent):
if event.over_maximum_retries:
# 关键错误:影响最终输出
print(f"❌ 关键错误: {event.error_message}")
else:
# 信息提示:系统正在重试
print(f"⚠️ 第 {event.retried_count} 次重试: {event.error_message}")
双 LLM 架构
使用不同优化参数的独立 LLM 实例分别处理翻译和 XML 结构填充:
# 创建两个具有不同温度参数的 LLM 实例
translation_llm = LLM(
key="your-api-key",
url="https://api.openai.com/v1",
model="gpt-4",
token_encoding="o200k_base",
temperature=0.8, # 较高温度用于创造性翻译
)
fill_llm = LLM(
key="your-api-key",
url="https://api.openai.com/v1",
model="gpt-4",
token_encoding="o200k_base",
temperature=0.3, # 较低温度用于结构保持
)
translate(
source_path="source.epub",
target_path="translated.epub",
target_language=language.CHINESE,
submit=SubmitKind.APPEND_BLOCK,
translation_llm=translation_llm,
fill_llm=fill_llm,
)
配置示例
OpenAI
llm = LLM(
key="sk-...",
url="https://api.openai.com/v1",
model="gpt-4",
token_encoding="o200k_base",
)
Azure OpenAI
llm = LLM(
key="your-azure-key",
url="https://your-resource.openai.azure.com/openai/deployments/your-deployment",
model="gpt-4",
token_encoding="o200k_base",
)
其他兼容 OpenAI 的服务
任何提供 OpenAI 兼容 API 的服务都可以使用:
llm = LLM(
key="your-api-key",
url="https://your-service.com/v1",
model="your-model",
token_encoding="o200k_base", # 匹配您模型的编码方式
)
高级功能
自定义翻译提示词
提供特定的翻译指令:
translate(
source_path="source.epub",
target_path="translated.epub",
target_language="Chinese",
submit=SubmitKind.APPEND_BLOCK,
llm=llm,
user_prompt="使用正式语言并保留专业术语",
)
缓存用于进度恢复
启用缓存以在翻译失败后恢复进度:
llm = LLM(
key="your-api-key",
url="https://api.openai.com/v1",
model="gpt-4",
token_encoding="o200k_base",
cache_path="./translation_cache", # 翻译结果缓存在此
)
并发翻译
通过并发处理多个文本段落来加速翻译。使用 concurrency 参数控制并行运行的翻译任务数量:
translate(
source_path="source.epub",
target_path="translated.epub",
target_language="Chinese",
submit=SubmitKind.APPEND_BLOCK,
llm=llm,
concurrency=4, # 同时处理 4 个段落
)
性能建议:
- 建议从
concurrency=4开始,根据 API 速率限制和系统资源进行调整 - 更高的并发值可以显著减少大型书籍的翻译时间
- 无论并发设置如何,翻译顺序都会被保留
- 注意监控 API 提供商的速率限制,避免触发限流
线程安全:
当使用 concurrency > 1 时,请确保任何自定义回调函数(on_progress、on_fill_failed)是线程安全的。内置回调函数默认是线程安全的。
Token 使用量监控
在翻译过程中跟踪 token 消耗,以监控 API 成本和用量:
from epub_translator import LLM, translate, language, SubmitKind
llm = LLM(
key="your-api-key",
url="https://api.openai.com/v1",
model="gpt-4",
token_encoding="o200k_base",
)
translate(
source_path="source.epub",
target_path="translated.epub",
target_language=language.CHINESE,
submit=SubmitKind.APPEND_BLOCK,
llm=llm,
)
# 翻译后访问 token 统计信息
print(f"总 token 数: {llm.total_tokens}")
print(f"输入 token 数: {llm.input_tokens}")
print(f"输入缓存 token 数: {llm.input_cache_tokens}")
print(f"输出 token 数: {llm.output_tokens}")
可用的统计数据:
total_tokens- 使用的 token 总数(输入 + 输出)input_tokens- 提示词/输入的 token 数量input_cache_tokens- 缓存的输入 token 数量(使用 prompt caching 时)output_tokens- 生成/完成的 token 数量
实时监控:
您也可以在翻译过程中实时监控 token 使用量:
from tqdm import tqdm
import time
with tqdm(total=100, desc="翻译中", unit="%") as pbar:
last_progress = 0.0
start_time = time.time()
def on_progress(progress: float):
nonlocal last_progress
increment = (progress - last_progress) * 100
pbar.update(increment)
last_progress = progress
# 在进度条中更新 token 统计
pbar.set_postfix({
'tokens': llm.total_tokens,
'cost_est': f'${llm.total_tokens * 0.00001:.4f}' # 根据您的定价估算成本
})
translate(
source_path="source.epub",
target_path="translated.epub",
target_language=language.CHINESE,
submit=SubmitKind.APPEND_BLOCK,
llm=llm,
on_progress=on_progress,
)
elapsed = time.time() - start_time
print(f"\n翻译完成,耗时 {elapsed:.1f} 秒")
print(f"使用的 token 总数: {llm.total_tokens:,}")
print(f"平均 tokens/秒: {llm.total_tokens/elapsed:.1f}")
双 LLM Token 追踪:
当使用独立的 LLM 进行翻译和填充时,每个 LLM 都会跟踪自己的统计信息:
translation_llm = LLM(key="...", url="...", model="gpt-4", token_encoding="o200k_base")
fill_llm = LLM(key="...", url="...", model="gpt-4", token_encoding="o200k_base")
translate(
source_path="source.epub",
target_path="translated.epub",
target_language=language.CHINESE,
submit=SubmitKind.APPEND_BLOCK,
translation_llm=translation_llm,
fill_llm=fill_llm,
)
print(f"翻译 tokens: {translation_llm.total_tokens}")
print(f"填充 tokens: {fill_llm.total_tokens}")
print(f"总计: {translation_llm.total_tokens + fill_llm.total_tokens}")
注意: Token 统计数据是累积的,包含 LLM 实例发出的所有 API 调用。计数只会增加,并且在使用并发翻译时是线程安全的。
相关项目
- PDF Craft:如果你的源文件是扫描版或图片型 PDF,可以先用 PDF Craft 转成 EPUB,再接入 EPUB Translator 做翻译。完整流程可参考这个演示视频。
- SpineDigest:如果你不只是想翻译,还想进一步获得整本书的结构化提炼,SpineDigest 可以基于 EPUB 生成摘要、章节拓扑和知识图谱。
贡献
欢迎贡献! 请随时提交 Pull Request。
许可证
本项目采用 MIT 许可证 - 详见 LICENSE 文件
支持
- 问题反馈: GitHub Issues
- 在线版本: Inkora - EPUB Translator

