#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 快速翻译脚本 用于快速翻译 ak_contents 表内容 """ import asyncio import aiohttp import json import logging # 配置日志 logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s') logger = logging.getLogger(__name__) # ========== 配置区域 - 请修改以下参数 ========== SUPABASE_URL = "YOUR_SUPABASE_URL" # 例如: https://abcdefgh.supabase.co SUPABASE_KEY = "YOUR_SUPABASE_KEY" # 您的 Supabase anon key RAGEFLOW_API_KEY = "YOUR_RAGEFLOW_KEY" # 您的 RageFlow API key # 翻译设置 TARGET_LANGUAGES = ["en", "ja"] # 目标语言 CONTENT_LIMIT = 5 # 每次翻译的内容数量 MODEL = "gpt-4" # 使用的模型 # =============================================== class QuickTranslator: def __init__(self): self.session = None async def __aenter__(self): self.session = aiohttp.ClientSession() return self async def __aexit__(self, exc_type, exc_val, exc_tb): if self.session: await self.session.close() async def get_contents(self): """获取待翻译内容""" headers = { "apikey": SUPABASE_KEY, "Authorization": f"Bearer {SUPABASE_KEY}", } url = f"{SUPABASE_URL}/rest/v1/ak_contents?select=id,title,content&limit={CONTENT_LIMIT}&order=created_at.desc" async with self.session.get(url, headers=headers) as response: if response.status == 200: return await response.json() else: logger.error(f"获取内容失败: {response.status}") return [] async def translate_text(self, text, target_lang): """翻译文本""" if not text.strip(): return "" lang_map = {"en": "English", "ja": "Japanese", "fr": "French"} target_name = lang_map.get(target_lang, target_lang) prompt = f"Please translate the following Chinese text to {target_name}:\n\n{text}\n\nTranslation:" payload = { "model": MODEL, "messages": [ {"role": "user", "content": prompt} ], "temperature": 0.3, "max_tokens": 2048 } headers = { "Authorization": f"Bearer {RAGEFLOW_API_KEY}", "Content-Type": "application/json" } try: async with self.session.post( "https://api.rageflow.ai/v1/chat/completions", json=payload, headers=headers ) as response: if response.status == 200: data = await response.json() return data["choices"][0]["message"]["content"].strip() else: logger.error(f"翻译失败: {response.status}") return "" except Exception as e: logger.error(f"翻译异常: {e}") return "" async def save_translation(self, content_id, language, title, content): """保存翻译结果""" headers = { "apikey": SUPABASE_KEY, "Authorization": f"Bearer {SUPABASE_KEY}", "Content-Type": "application/json" } data = { "content_id": content_id, "language": language, "title": title, "content": content, "translation_source": "rageflow_auto" } # 先检查是否已存在 check_url = f"{SUPABASE_URL}/rest/v1/ak_content_translations?content_id=eq.{content_id}&language=eq.{language}&select=id" async with self.session.get(check_url, headers=headers) as response: if response.status == 200: existing = await response.json() if existing: logger.info(f"翻译已存在,跳过: {content_id} -> {language}") return True # 插入新翻译 async with self.session.post( f"{SUPABASE_URL}/rest/v1/ak_content_translations", json=data, headers=headers ) as response: success = response.status in [200, 201] if success: logger.info(f"翻译保存成功: {content_id} -> {language}") else: logger.error(f"保存失败: {response.status}") return success async def run_translation(self): """执行翻译""" logger.info("开始获取内容...") contents = await self.get_contents() if not contents: logger.warning("没有找到内容") return logger.info(f"找到 {len(contents)} 条内容,开始翻译...") total_success = 0 total_failed = 0 for content in contents: content_id = content["id"] title = content.get("title", "") content_text = content.get("content", "") logger.info(f"翻译内容: {title[:30]}...") for target_lang in TARGET_LANGUAGES: try: # 翻译标题和内容 translated_title = await self.translate_text(title, target_lang) await asyncio.sleep(1) # 避免API限制 translated_content = await self.translate_text(content_text, target_lang) await asyncio.sleep(1) if translated_title and translated_content: # 保存翻译 success = await self.save_translation( content_id, target_lang, translated_title, translated_content ) if success: total_success += 1 else: total_failed += 1 else: logger.error(f"翻译失败: {content_id} -> {target_lang}") total_failed += 1 except Exception as e: logger.error(f"处理异常: {content_id} -> {target_lang}: {e}") total_failed += 1 logger.info(f"翻译完成!成功: {total_success}, 失败: {total_failed}") async def main(): """主函数""" print("=" * 50) print("🌍 简化版自动翻译服务") print("=" * 50) print(f"📝 目标语言: {', '.join(TARGET_LANGUAGES)}") print(f"📊 内容限制: {CONTENT_LIMIT} 条") print(f"🤖 使用模型: {MODEL}") print("=" * 50) # 检查配置 if "YOUR_" in SUPABASE_URL or "YOUR_" in SUPABASE_KEY or "YOUR_" in RAGEFLOW_API_KEY: print("❌ 请先在脚本顶部配置正确的 API 参数!") return async with QuickTranslator() as translator: await translator.run_translation() print("✅ 翻译任务完成!") if __name__ == "__main__": asyncio.run(main())