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
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env python3
|
||||
import asyncio
|
||||
import sys
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
from loguru import logger
|
||||
from src.translator import EPUBTranslator
|
||||
from src.epub_parser import EPUBParser
|
||||
from src.toc_parser import TOCParser
|
||||
from src.utils import load_config, setup_logging
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(description="EPUB 双语翻译工具")
|
||||
parser.add_argument("epub_path", help="输入 EPUB 文件路径")
|
||||
parser.add_argument("--provider", "-p", default="openrouter", help="LLM 供应商 (config.json 中 providers 的 key)")
|
||||
parser.add_argument("--mode", "-m", default="bilingual", choices=["bilingual", "chinese"],
|
||||
help="输出模式: bilingual (双语对照) 或 chinese (纯中文,保留格式)")
|
||||
parser.add_argument("--test", action="store_true", help="测试模式(仅翻译前几段)")
|
||||
parser.add_argument("--output", "-o", help="输出目录")
|
||||
parser.add_argument("--no-cache", action="store_true", help="禁用缓存(强制重新翻译)")
|
||||
parser.add_argument("--clear-cache", action="store_true", help="清理所有缓存文件")
|
||||
|
||||
# TOC 章节选择
|
||||
parser.add_argument("--show-toc", action="store_true", help="显示书籍目录结构")
|
||||
parser.add_argument("--from", dest="from_chapter", help="起始章节标题")
|
||||
parser.add_argument("--to", dest="to_chapter", help="结束章节标题")
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
def flatten_provider_config(config: dict, provider_name: str) -> dict:
|
||||
"""
|
||||
将选定的 provider 配置扁平化到 config['llm'] 中,
|
||||
以便下游模块统一调用。
|
||||
"""
|
||||
providers = config.get('providers', {})
|
||||
if provider_name not in providers:
|
||||
available = list(providers.keys())
|
||||
logger.error(f"未找到供应商 '{provider_name}'。可用供应商: {available}")
|
||||
sys.exit(1)
|
||||
|
||||
selected_config = providers[provider_name]
|
||||
logger.info(f"使用 LLM 供应商: {provider_name} ({selected_config.get('base_url')})")
|
||||
|
||||
# 注入到 config['llm']
|
||||
config['llm'] = selected_config
|
||||
return config
|
||||
|
||||
async def run_translation(args):
|
||||
try:
|
||||
# 1. 加载配置
|
||||
config = load_config()
|
||||
|
||||
# 2. 处理 Provider 选择
|
||||
config = flatten_provider_config(config, args.provider)
|
||||
|
||||
# 3. 设置日志
|
||||
setup_logging(config)
|
||||
logger.info("程序启动")
|
||||
|
||||
# 4. 初始化翻译器
|
||||
translator = EPUBTranslator(config, use_cache=not args.no_cache)
|
||||
|
||||
# 5. 执行翻译 (传递章节范围参数)
|
||||
await translator.translate_epub(
|
||||
args.epub_path,
|
||||
test_mode=args.test,
|
||||
output_dir=args.output,
|
||||
mode=args.mode,
|
||||
from_chapter=args.from_chapter,
|
||||
to_chapter=args.to_chapter
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
logger.error(f"翻译失败: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
def show_toc(epub_path: str):
|
||||
"""显示 EPUB 的目录结构"""
|
||||
parser = EPUBParser(epub_path)
|
||||
toc_parser = TOCParser(parser.book)
|
||||
|
||||
print(f"\n📖 {parser.metadata.get('title', 'Unknown')} - {parser.metadata.get('author', 'Unknown')}")
|
||||
print(toc_parser.format_toc_table())
|
||||
print("提示: 使用 --from \"章节名\" --to \"章节名\" 指定翻译范围")
|
||||
print()
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
|
||||
if args.clear_cache:
|
||||
import shutil
|
||||
cache_dir = Path("cache")
|
||||
if cache_dir.exists():
|
||||
shutil.rmtree(cache_dir)
|
||||
print("缓存已清理")
|
||||
# sys.exit(0) # 移除退出,允许继续执行
|
||||
|
||||
|
||||
if args.show_toc:
|
||||
show_toc(args.epub_path)
|
||||
sys.exit(0)
|
||||
|
||||
asyncio.run(run_translation(args))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user