mcp-feedback-enhanced/tests/unit/test_i18n_core.py
2025-06-10 08:40:47 +08:00

257 lines
9.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
I18N 核心功能測試
"""
import pytest
import os
from pathlib import Path
from tests.fixtures.test_data import TestData
class TestI18NManager:
"""I18N 管理器測試"""
def test_i18n_manager_creation(self, i18n_manager):
"""測試 I18N 管理器創建"""
assert i18n_manager is not None
assert hasattr(i18n_manager, '_current_language')
assert hasattr(i18n_manager, '_translations')
assert i18n_manager.get_current_language() is not None
def test_supported_languages(self, i18n_manager):
"""測試支援的語言"""
supported_languages = i18n_manager.get_supported_languages()
# 驗證包含預期的語言
for lang in TestData.SUPPORTED_LANGUAGES:
assert lang in supported_languages
# 驗證至少有基本語言支援
assert len(supported_languages) >= 2
def test_language_switching(self, i18n_manager):
"""測試語言切換"""
original_language = i18n_manager.get_current_language()
# 測試切換到不同語言
for lang in TestData.SUPPORTED_LANGUAGES:
if lang != original_language:
success = i18n_manager.set_language(lang)
assert success == True
assert i18n_manager.get_current_language() == lang
break
# 恢復原始語言
i18n_manager.set_language(original_language)
def test_invalid_language_switching(self, i18n_manager):
"""測試無效語言切換"""
original_language = i18n_manager.get_current_language()
# 嘗試切換到不存在的語言
success = i18n_manager.set_language("invalid-lang")
assert success == False
assert i18n_manager.get_current_language() == original_language
def test_translation_function(self, i18n_manager):
"""測試翻譯函數"""
# 測試基本翻譯
for key in TestData.I18N_TEST_KEYS:
translation = i18n_manager.t(key)
assert isinstance(translation, str)
assert len(translation) > 0
# 翻譯結果不應該等於 key除非是回退情況
if key in i18n_manager._translations.get(i18n_manager.get_current_language(), {}):
assert translation != key
def test_translation_with_parameters(self, i18n_manager):
"""測試帶參數的翻譯"""
# 假設有帶參數的翻譯 key
test_key = "test.message.withParam"
test_params = {"name": "測試用戶", "count": 5}
# 即使 key 不存在,也應該返回合理的結果
translation = i18n_manager.t(test_key, **test_params)
assert isinstance(translation, str)
assert len(translation) > 0
def test_fallback_mechanism(self, i18n_manager):
"""測試回退機制"""
original_language = i18n_manager.get_current_language()
try:
# 切換到可能翻譯不完整的語言
i18n_manager.set_language("en")
# 測試不存在的 key
non_existent_key = "non.existent.key.for.testing"
translation = i18n_manager.t(non_existent_key)
# 應該返回 key 本身或合理的回退值
assert isinstance(translation, str)
assert len(translation) > 0
finally:
# 恢復原始語言
i18n_manager.set_language(original_language)
class TestI18NTranslationCompleteness:
"""I18N 翻譯完整性測試"""
def test_all_languages_have_translations(self, i18n_manager):
"""測試所有語言都有翻譯文件"""
supported_languages = i18n_manager.get_supported_languages()
for lang in supported_languages:
translations = i18n_manager._translations.get(lang, {})
assert len(translations) > 0, f"語言 {lang} 沒有翻譯內容"
def test_key_consistency_across_languages(self, i18n_manager):
"""測試所有語言的 key 一致性"""
supported_languages = i18n_manager.get_supported_languages()
if len(supported_languages) < 2:
pytest.skip("需要至少兩種語言來測試一致性")
# 獲取所有語言的翻譯
all_translations = {}
for lang in supported_languages:
all_translations[lang] = i18n_manager._translations.get(lang, {})
# 獲取所有 key 的聯集
all_keys = set()
for translations in all_translations.values():
all_keys.update(self._get_all_keys(translations))
# 檢查每種語言是否有所有 key
missing_keys_report = {}
for lang in supported_languages:
missing_keys = []
lang_translations = all_translations[lang]
for key in all_keys:
if not self._has_key(lang_translations, key):
missing_keys.append(key)
if missing_keys:
missing_keys_report[lang] = missing_keys
# 如果有缺失的 key生成詳細報告
if missing_keys_report:
report_lines = ["翻譯 key 缺失報告:"]
for lang, missing_keys in missing_keys_report.items():
report_lines.append(f" {lang}: 缺失 {len(missing_keys)} 個 key")
for key in missing_keys[:5]: # 只顯示前5個
report_lines.append(f" - {key}")
if len(missing_keys) > 5:
report_lines.append(f" ... 還有 {len(missing_keys) - 5}")
# 這裡我們記錄警告而不是失敗測試,因為某些 key 可能是特定語言的
print("\n".join(report_lines))
def test_common_keys_exist(self, i18n_manager):
"""測試常用 key 存在"""
common_keys = [
"common.submit",
"common.cancel",
"common.loading"
]
supported_languages = i18n_manager.get_supported_languages()
for lang in supported_languages:
i18n_manager.set_language(lang)
for key in common_keys:
translation = i18n_manager.t(key)
# 翻譯應該存在且不為空
assert isinstance(translation, str)
assert len(translation.strip()) > 0
def _get_all_keys(self, translations: dict, prefix: str = "") -> set:
"""遞歸獲取所有翻譯 key"""
keys = set()
for key, value in translations.items():
full_key = f"{prefix}.{key}" if prefix else key
if isinstance(value, dict):
# 遞歸處理嵌套字典
keys.update(self._get_all_keys(value, full_key))
else:
# 葉子節點
keys.add(full_key)
return keys
def _has_key(self, translations: dict, key: str) -> bool:
"""檢查翻譯字典是否包含指定 key"""
keys = key.split('.')
current = translations
for k in keys:
if not isinstance(current, dict) or k not in current:
return False
current = current[k]
return True
class TestI18NEnvironmentDetection:
"""I18N 環境檢測測試"""
def test_language_detection_from_env(self, i18n_manager):
"""測試從環境變數檢測語言"""
original_lang = os.environ.get('LANG')
original_language = os.environ.get('LANGUAGE')
try:
# 測試設置環境變數
os.environ['LANG'] = 'zh_TW.UTF-8'
# 重新創建 I18N 管理器來測試環境檢測
from src.mcp_feedback_enhanced.i18n import I18nManager
test_manager = I18nManager()
# 應該檢測到繁體中文
detected_lang = test_manager._detect_language()
assert detected_lang in ['zh-TW', 'zh-CN', 'en'] # 應該是支援的語言之一
finally:
# 恢復環境變數
if original_lang is not None:
os.environ['LANG'] = original_lang
else:
os.environ.pop('LANG', None)
if original_language is not None:
os.environ['LANGUAGE'] = original_language
else:
os.environ.pop('LANGUAGE', None)
def test_fallback_to_default_language(self, i18n_manager):
"""測試回退到默認語言"""
# 測試當系統語言不支援時的回退行為
original_lang = os.environ.get('LANG')
try:
# 設置不支援的語言
os.environ['LANG'] = 'fr_FR.UTF-8' # 法語
from src.mcp_feedback_enhanced.i18n import I18nManager
test_manager = I18nManager()
detected_lang = test_manager._detect_language()
# 應該回退到支援的語言
assert detected_lang in TestData.SUPPORTED_LANGUAGES
finally:
if original_lang is not None:
os.environ['LANG'] = original_lang
else:
os.environ.pop('LANG', None)