#!/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.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("--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="清理所有缓存文件") 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 ) except Exception as e: import traceback traceback.print_exc() logger.error(f"翻译失败: {e}") sys.exit(1) 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) asyncio.run(run_translation(args)) if __name__ == "__main__": main()