-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathi18n.py
More file actions
98 lines (82 loc) · 3.14 KB
/
i18n.py
File metadata and controls
98 lines (82 loc) · 3.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# encoding = utf-8
import json
from pathlib import Path
from typing import Dict, Any, Optional
class I18n:
_instance: Optional["I18n"] = None
def __new__(cls, *args, **kwargs):
# Keep a shared i18n state so repeated I18n() calls use the same language.
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, locale_dir: str = "locales", default_lang: str = "zh_CN"):
if getattr(self, "_initialized", False):
return
self.locale_dir = Path(locale_dir)
self.default_lang = default_lang
self.current_lang = default_lang
self.translations: Dict[str, Any] = {}
self._load_translations()
self._initialized = True
def _load_translations(self):
"""加载所有语言包"""
# 重新扫描并加载所有 json 文件
self.translations = {}
if not self.locale_dir.exists():
return
for lang_file in self.locale_dir.glob("*.json"):
lang = lang_file.stem
try:
with open(lang_file, 'r', encoding='utf-8') as f:
self.translations[lang] = json.load(f)
except Exception:
# 忽略单个语言文件的解析错误
continue
def reload(self):
"""手动重新加载 locales 目录下的语言文件(当文件变化时调用)。"""
self._load_translations()
def available_languages(self):
"""返回当前可用的语言代码列表(按字母排序)。"""
return sorted(list(self.translations.keys()))
def set_language(self, lang: str):
"""切换当前语言"""
if lang in self.translations:
self.current_lang = lang
else:
raise ValueError(f"Language {lang} not supported")
def get(self, key: str, **kwargs) -> str:
"""获取翻译文本"""
# 尝试获取当前语言的翻译
text = self._get_nested(self.translations.get(self.current_lang, {}), key)
# 如果当前语言没有,尝试默认语言
if text is None and self.current_lang != self.default_lang:
text = self._get_nested(self.translations.get(self.default_lang, {}), key)
# 如果都没有,返回key本身
if text is None:
return key
# 格式化字符串
if kwargs:
try:
return text.format(**kwargs)
except KeyError:
return text
return text
def _get_nested(self, data: dict, key: str):
"""支持点号分隔的嵌套key"""
keys = key.split('.')
for k in keys:
if isinstance(data, dict):
data = data.get(k)
else:
return None
return data
def __getitem__(self, key: str, **kwargs) -> str:
"""使实例可以用[]调用"""
return self.get(key, **kwargs)
if __name__ == "__main__":
# 使用示例
i18n = I18n()
# 切换语言
i18n.set_language('en_US')
# 获取翻译
print(i18n['errors.not_found'])