87 lines
1.9 KiB
Python
87 lines
1.9 KiB
Python
|
|
"""
|
||
|
|
Language helpers (local-only).
|
||
|
|
|
||
|
|
We want AI analysis output language to follow the frontend UI language.
|
||
|
|
Frontend sends `X-App-Lang` (and also `Accept-Language`) on each request.
|
||
|
|
"""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from typing import Optional
|
||
|
|
|
||
|
|
|
||
|
|
SUPPORTED_LANGS = {
|
||
|
|
"en-US",
|
||
|
|
"zh-CN",
|
||
|
|
"zh-TW",
|
||
|
|
"ja-JP",
|
||
|
|
"ko-KR",
|
||
|
|
"vi-VN",
|
||
|
|
"th-TH",
|
||
|
|
"ar-SA",
|
||
|
|
"fr-FR",
|
||
|
|
"de-DE",
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
def _normalize_lang(raw: Optional[str]) -> Optional[str]:
|
||
|
|
if not raw:
|
||
|
|
return None
|
||
|
|
s = str(raw).strip()
|
||
|
|
if not s:
|
||
|
|
return None
|
||
|
|
|
||
|
|
# Accept-Language can be like: "en-US,en;q=0.9"
|
||
|
|
if "," in s:
|
||
|
|
s = s.split(",", 1)[0].strip()
|
||
|
|
if ";" in s:
|
||
|
|
s = s.split(";", 1)[0].strip()
|
||
|
|
|
||
|
|
# Normalize short tags
|
||
|
|
lower = s.lower()
|
||
|
|
if lower in ("en", "en-us"):
|
||
|
|
return "en-US"
|
||
|
|
if lower in ("zh", "zh-cn", "zh-hans"):
|
||
|
|
return "zh-CN"
|
||
|
|
if lower in ("zh-tw", "zh-hant"):
|
||
|
|
return "zh-TW"
|
||
|
|
|
||
|
|
# Keep canonical casing if already supported
|
||
|
|
for lang in SUPPORTED_LANGS:
|
||
|
|
if lang.lower() == lower:
|
||
|
|
return lang
|
||
|
|
return None
|
||
|
|
|
||
|
|
|
||
|
|
def detect_request_language(flask_request, body: Optional[dict] = None, default: str = "en-US") -> str:
|
||
|
|
"""
|
||
|
|
Detect language for the current request.
|
||
|
|
|
||
|
|
Priority:
|
||
|
|
1) Header X-App-Lang (frontend UI language)
|
||
|
|
2) body["language"] or query ?language=
|
||
|
|
3) Header Accept-Language
|
||
|
|
"""
|
||
|
|
# 1) Custom header
|
||
|
|
lang = _normalize_lang(flask_request.headers.get("X-App-Lang"))
|
||
|
|
if lang:
|
||
|
|
return lang
|
||
|
|
|
||
|
|
# 2) Explicit parameter
|
||
|
|
if body and isinstance(body, dict):
|
||
|
|
lang = _normalize_lang(body.get("language"))
|
||
|
|
if lang:
|
||
|
|
return lang
|
||
|
|
lang = _normalize_lang(flask_request.args.get("language"))
|
||
|
|
if lang:
|
||
|
|
return lang
|
||
|
|
|
||
|
|
# 3) Browser default
|
||
|
|
lang = _normalize_lang(flask_request.headers.get("Accept-Language"))
|
||
|
|
if lang:
|
||
|
|
return lang
|
||
|
|
|
||
|
|
return default
|
||
|
|
|
||
|
|
|