harry0703--moneyprinterturbo
132 行
4.0 KiB
Python
132 行
4.0 KiB
Python
import ast
|
|
import json
|
|
from pathlib import Path
|
|
import unittest
|
|
|
|
from app.utils import utils
|
|
|
|
|
|
ROOT_DIR = Path(__file__).parent.parent.parent
|
|
WEBUI_MAIN = ROOT_DIR / "webui" / "Main.py"
|
|
I18N_DIR = ROOT_DIR / "webui" / "i18n"
|
|
LLM_PROVIDER_TIPS_PREFIX = "llm_provider_tips."
|
|
TTS_PROVIDER_TIPS_PREFIX = "tts_provider_tips."
|
|
|
|
|
|
class _TrKeyVisitor(ast.NodeVisitor):
|
|
def __init__(self):
|
|
self.keys = set()
|
|
|
|
def visit_Call(self, node):
|
|
if (
|
|
isinstance(node.func, ast.Name)
|
|
and node.func.id == "tr"
|
|
and node.args
|
|
and isinstance(node.args[0], ast.Constant)
|
|
and isinstance(node.args[0].value, str)
|
|
):
|
|
self.keys.add(node.args[0].value)
|
|
self.generic_visit(node)
|
|
|
|
|
|
def _load_translation(locale):
|
|
data = json.loads((I18N_DIR / f"{locale}.json").read_text(encoding="utf-8"))
|
|
return data.get("Translation", {})
|
|
|
|
|
|
class TestWebuiI18n(unittest.TestCase):
|
|
def test_saved_ui_language_takes_priority_over_browser_locale(self):
|
|
language = utils.resolve_ui_language(
|
|
saved_language="de",
|
|
browser_locale="zh-CN",
|
|
supported_languages=["zh", "en", "de"],
|
|
)
|
|
|
|
self.assertEqual(language, "de")
|
|
|
|
def test_browser_locale_is_normalized_to_supported_base_language(self):
|
|
self.assertEqual(
|
|
utils.resolve_ui_language("", "zh-CN", ["zh", "en"]),
|
|
"zh",
|
|
)
|
|
self.assertEqual(
|
|
utils.resolve_ui_language(None, "pt_BR", ["en", "pt"]),
|
|
"pt",
|
|
)
|
|
|
|
def test_unsupported_browser_locale_falls_back_to_english(self):
|
|
language = utils.resolve_ui_language(
|
|
saved_language="",
|
|
browser_locale="fr-FR",
|
|
supported_languages=["zh", "en"],
|
|
)
|
|
|
|
self.assertEqual(language, "en")
|
|
|
|
def test_english_locale_covers_static_webui_labels(self):
|
|
tree = ast.parse(WEBUI_MAIN.read_text(encoding="utf-8"))
|
|
visitor = _TrKeyVisitor()
|
|
visitor.visit(tree)
|
|
|
|
en_keys = set(_load_translation("en"))
|
|
|
|
self.assertEqual(sorted(visitor.keys - en_keys), [])
|
|
|
|
def test_russian_locale_covers_english_locale(self):
|
|
en_keys = set(_load_translation("en"))
|
|
ru_keys = set(_load_translation("ru"))
|
|
# Provider 配置说明只维护中英文,俄语及其它 locale 运行时统一回退英文。
|
|
# 这里排除动态 tips key,避免继续复制一整套不会被读取的英文文案。
|
|
required_en_keys = {
|
|
key
|
|
for key in en_keys
|
|
if not key.startswith(
|
|
(LLM_PROVIDER_TIPS_PREFIX, TTS_PROVIDER_TIPS_PREFIX)
|
|
)
|
|
}
|
|
|
|
self.assertEqual(sorted(required_en_keys - ru_keys), [])
|
|
|
|
def test_russian_locale_does_not_duplicate_provider_tips(self):
|
|
ru_keys = set(_load_translation("ru"))
|
|
|
|
self.assertEqual(
|
|
sorted(
|
|
key for key in ru_keys if key.startswith(LLM_PROVIDER_TIPS_PREFIX)
|
|
),
|
|
[],
|
|
)
|
|
|
|
self.assertEqual(
|
|
sorted(
|
|
key for key in ru_keys if key.startswith(TTS_PROVIDER_TIPS_PREFIX)
|
|
),
|
|
[],
|
|
)
|
|
|
|
def test_russian_locale_covers_static_webui_labels(self):
|
|
tree = ast.parse(WEBUI_MAIN.read_text(encoding="utf-8"))
|
|
visitor = _TrKeyVisitor()
|
|
visitor.visit(tree)
|
|
|
|
ru_keys = set(_load_translation("ru"))
|
|
|
|
self.assertEqual(sorted(visitor.keys - ru_keys), [])
|
|
|
|
def test_script_language_options_include_russian(self):
|
|
tree = ast.parse(WEBUI_MAIN.read_text(encoding="utf-8"))
|
|
support_locales = None
|
|
|
|
for node in tree.body:
|
|
if not isinstance(node, ast.Assign):
|
|
continue
|
|
if any(
|
|
isinstance(target, ast.Name) and target.id == "support_locales"
|
|
for target in node.targets
|
|
):
|
|
support_locales = ast.literal_eval(node.value)
|
|
break
|
|
|
|
self.assertIsNotNone(support_locales)
|
|
self.assertIn("ru-RU", support_locales)
|