feat: 阶段2 Python后端、用户管理、统计、单词收藏与响应式适配
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import json
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
|
||||
|
||||
def translate_mymemory(text, source="zh-CN", target="es"):
|
||||
url = (
|
||||
"https://api.mymemory.translated.net/get?"
|
||||
+ urllib.parse.urlencode({"q": text, "langpair": source + "|" + target})
|
||||
)
|
||||
try:
|
||||
with urllib.request.urlopen(url, timeout=15) as resp:
|
||||
data = json.loads(resp.read().decode("utf-8"))
|
||||
translated = data.get("responseData", {}).get("translatedText", "")
|
||||
if not translated or data.get("quotaFinished"):
|
||||
return {"ok": False, "error": "MyMemory 配额已用完或未返回结果"}
|
||||
return {"ok": True, "translatedText": translated, "provider": "mymemory"}
|
||||
except Exception as exc:
|
||||
return {"ok": False, "error": str(exc)}
|
||||
|
||||
|
||||
def translate_custom(text, settings, source="zh", target="es"):
|
||||
api_url = (settings.get("api_url") or "").strip()
|
||||
if not api_url:
|
||||
return {"ok": False, "error": "未配置自定义翻译接口地址"}
|
||||
|
||||
extra = {}
|
||||
try:
|
||||
extra = json.loads(settings.get("extra_config") or "{}")
|
||||
except Exception:
|
||||
extra = {}
|
||||
|
||||
payload = extra.get("payload", {})
|
||||
payload["q"] = text
|
||||
payload["source"] = source
|
||||
payload["target"] = target
|
||||
|
||||
headers = {"Content-Type": "application/json"}
|
||||
api_key = settings.get("api_key") or ""
|
||||
header_key = extra.get("api_key_header", "Authorization")
|
||||
if api_key:
|
||||
headers[header_key] = api_key
|
||||
headers.update(extra.get("headers", {}) or {})
|
||||
|
||||
request = urllib.request.Request(
|
||||
api_url,
|
||||
data=json.dumps(payload).encode("utf-8"),
|
||||
headers=headers,
|
||||
method="POST",
|
||||
)
|
||||
try:
|
||||
with urllib.request.urlopen(request, timeout=20) as resp:
|
||||
data = json.loads(resp.read().decode("utf-8"))
|
||||
text_key = extra.get("result_key", "translatedText")
|
||||
translated = data
|
||||
for part in text_key.split("."):
|
||||
if isinstance(translated, dict):
|
||||
translated = translated.get(part, "")
|
||||
else:
|
||||
translated = ""
|
||||
if not translated:
|
||||
return {"ok": False, "error": "自定义接口未返回可识别的翻译字段"}
|
||||
return {"ok": True, "translatedText": translated, "provider": "custom"}
|
||||
except Exception as exc:
|
||||
return {"ok": False, "error": str(exc)}
|
||||
|
||||
|
||||
def perform_translate(text, settings, source="zh", target="es"):
|
||||
provider = (settings.get("translator") or "local").lower()
|
||||
if provider == "mymemory":
|
||||
lang_map = {
|
||||
("zh", "es"): ("zh-CN", "es"),
|
||||
("es", "zh"): ("es", "zh-CN"),
|
||||
("zh", "en"): ("zh-CN", "en"),
|
||||
("en", "zh"): ("en", "zh-CN"),
|
||||
("es", "en"): ("es", "en"),
|
||||
("en", "es"): ("en", "es"),
|
||||
}
|
||||
src, dst = lang_map.get((source, target), (source, target))
|
||||
return translate_mymemory(text, src, dst)
|
||||
if provider == "custom":
|
||||
return translate_custom(text, settings, source, target)
|
||||
return {"ok": False, "error": "本地词典翻译请在前端完成"}
|
||||
Reference in New Issue
Block a user