Files
Nexus/server/utils/http_errors_zh.py
T

117 lines
4.6 KiB
Python
Raw Normal View History

"""Translate HTTPException detail strings to Chinese for admin-facing API responses."""
from __future__ import annotations
import re
from typing import Any
# Exact English literals from server/api (and shared services)
_DETAIL_EXACT: dict[str, str] = {
"Not found": "不存在",
"Server not found": "服务器不存在",
"Platform not found": "平台不存在",
"Node not found": "节点不存在",
"Admin not found": "管理员不存在",
"Setting not found": "设置项不存在",
"API_KEY not found": "API_KEY 不存在",
"Schedule not found": "调度任务不存在",
"Preset not found": "凭据预设不存在",
"SSH key preset not found": "SSH 密钥预设不存在",
"telegram_bot_token not found": "telegram_bot_token 不存在",
"Retry job not found": "重试任务不存在",
"Credential not found": "凭据不存在",
"Execution not found": "执行记录不存在",
"Script not found": "脚本不存在",
"Login failed": "登录失败",
"Missing refresh token": "缺少刷新令牌",
"Invalid refresh token": "刷新令牌无效",
"Missing Authorization header": "缺少 Authorization 请求头",
"Invalid or expired token": "令牌无效或已过期",
"Can only setup TOTP for yourself": "只能为自己设置 TOTP",
"Can only enable TOTP for yourself": "只能为自己启用 TOTP",
"Can only disable TOTP for yourself": "只能为自己禁用 TOTP",
"Setup failed": "设置失败",
"Enable failed": "启用失败",
"Disable failed": "禁用失败",
"Server has no domain configured": "服务器未配置域名",
"Missing API key": "缺少 API Key",
"Invalid API key for this server": "该服务器的 API Key 无效",
"Invalid or expired job": "任务无效或已过期",
"new_path required for rename": "重命名需要指定 new_path",
"Invalid operation": "无效操作",
"server_id required": "server_id 必填",
"Too many script callback requests": "脚本回调请求过于频繁",
}
# AuthService ``reason`` codes → user-facing Chinese (when ``message`` absent)
_AUTH_REASON_ZH: dict[str, str] = {
"admin_not_found": "管理员不存在",
"no_secret": "请先完成 TOTP 设置",
"invalid_totp": "TOTP 验证码错误",
"invalid_password": "当前密码错误",
"totp_required": "需要 TOTP 验证码",
"invalid_token": "令牌无效或已过期",
"invalid_credentials": "用户名或密码错误",
"account_locked": "登录尝试过多,请 15 分钟后重试",
"account_disabled": "账户已被禁用",
"ip_blocked": "拒绝访问",
"service_unavailable": "认证服务暂不可用,请稍后重试",
}
_DETAIL_PATTERNS: list[tuple[re.Pattern[str], str]] = [
(
re.compile(r"^Command failed \(exit (\d+)\)$"),
r"命令失败(退出码 \1",
),
(
re.compile(
r"^Setting '([^']+)' is immutable and cannot be modified via API$"
),
r"设置项「\1」不可通过 API 修改",
),
]
def _looks_chinese(text: str) -> bool:
return any("\u4e00" <= ch <= "\u9fff" for ch in text)
def translate_http_detail_str(msg: str) -> str:
"""Return Chinese detail when a known translation exists."""
if not msg or _looks_chinese(msg):
return msg
if msg in _DETAIL_EXACT:
return _DETAIL_EXACT[msg]
for pattern, repl in _DETAIL_PATTERNS:
if pattern.fullmatch(msg):
return pattern.sub(repl, msg)
return msg
def auth_failure_detail(result: dict[str, Any], *, fallback: str = "操作失败") -> str:
"""Map AuthService failure dict to Chinese ``HTTPException.detail``."""
msg = result.get("message")
if isinstance(msg, str) and msg.strip():
return translate_http_detail_str(msg)
reason = str(result.get("reason") or "")
if reason in _AUTH_REASON_ZH:
return _AUTH_REASON_ZH[reason]
return fallback if _looks_chinese(fallback) else translate_http_detail_str(fallback)
def translate_http_detail(detail: Any) -> Any:
"""Translate ``HTTPException.detail`` (str | list | dict) for JSON responses."""
if isinstance(detail, str):
return translate_http_detail_str(detail)
if isinstance(detail, list):
return [translate_http_detail(item) for item in detail]
if isinstance(detail, dict):
out: dict[Any, Any] = {}
for key, value in detail.items():
if key in ("msg", "message") and isinstance(value, str):
out[key] = translate_http_detail_str(value)
else:
out[key] = value
return out
return detail