Skip to content

Commit 8ae1a43

Browse files
authored
Update i18n language storage and loading (#1008)
1 parent ee849f0 commit 8ae1a43

File tree

7 files changed

+52
-39
lines changed

7 files changed

+52
-39
lines changed

backend/common/i18n.py

Lines changed: 5 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,15 @@
1-
import glob
2-
import json
3-
4-
from pathlib import Path
51
from typing import Any
62

7-
import yaml
8-
93
from starlette_context.errors import ContextDoesNotExistError
104

115
from backend.common.context import ctx
126
from backend.core.conf import settings
13-
from backend.core.path_conf import LOCALE_DIR
7+
from backend.locale.loader import locale_loader
148

159

1610
class I18n:
1711
"""国际化管理器"""
1812

19-
def __init__(self) -> None:
20-
self.locales: dict[str, dict[str, Any]] = {}
21-
self.load_locales()
22-
2313
@property
2414
def current_language(self) -> str:
2515
"""获取当前请求的语言"""
@@ -33,29 +23,6 @@ def current_language(self, language: str) -> None:
3323
"""设置当前请求的语言"""
3424
ctx.language = language
3525

36-
def load_locales(self) -> None:
37-
"""加载语言文本"""
38-
patterns = [
39-
LOCALE_DIR / '*.json',
40-
LOCALE_DIR / '*.yaml',
41-
LOCALE_DIR / '*.yml',
42-
]
43-
44-
lang_files = []
45-
46-
for pattern in patterns:
47-
lang_files.extend(glob.glob(str(pattern)))
48-
49-
for lang_file in lang_files:
50-
with open(lang_file, encoding='utf-8') as f:
51-
lang = Path(lang_file).stem
52-
file_type = Path(lang_file).suffix[1:]
53-
match file_type:
54-
case 'json':
55-
self.locales[lang] = json.loads(f.read())
56-
case 'yaml' | 'yml':
57-
self.locales[lang] = yaml.full_load(f.read())
58-
5926
def t(self, key: str, default: Any | None = None, **kwargs) -> str:
6027
"""
6128
翻译函数
@@ -68,17 +35,18 @@ def t(self, key: str, default: Any | None = None, **kwargs) -> str:
6835
keys = key.split('.')
6936

7037
try:
71-
translation = self.locales[self.current_language]
38+
translation = locale_loader.locales[self.current_language]
7239
except KeyError:
73-
keys = 'error.language_not_found'
74-
translation = self.locales[settings.I18N_DEFAULT_LANGUAGE]
40+
keys = 'error.language_not_found'.split('.')
41+
translation = locale_loader.locales[settings.I18N_DEFAULT_LANGUAGE]
7542

7643
for k in keys:
7744
if isinstance(translation, dict) and k in list(translation.keys()):
7845
translation = translation[k]
7946
else:
8047
# Pydantic 兼容
8148
translation = None if keys[0] == 'pydantic' else key
49+
break
8250

8351
if translation and kwargs:
8452
translation = translation.format(**kwargs)

backend/core/path_conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
PLUGIN_DIR = BASE_PATH / 'plugin'
2626

2727
# 国际化文件目录
28-
LOCALE_DIR = BASE_PATH / 'locale'
28+
LOCALE_DIR = BASE_PATH / 'locale' / 'langs'
2929

3030
# MySQL 脚本目录
3131
MYSQL_SCRIPT_DIR = BASE_PATH / 'sql' / 'mysql'

backend/locale/__init__.py

Whitespace-only changes.

backend/locale/loader.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import glob
2+
import json
3+
4+
from pathlib import Path
5+
from typing import Any
6+
7+
import yaml
8+
9+
from backend.core.path_conf import LOCALE_DIR
10+
11+
12+
class LocaleLoader:
13+
"""语言文件加载器"""
14+
15+
def __init__(self) -> None:
16+
self.locales: dict[str, dict[str, Any]] = {}
17+
self.load_locales()
18+
19+
def load_locales(self) -> None:
20+
"""加载语言文本"""
21+
patterns = [
22+
LOCALE_DIR / '*.json',
23+
LOCALE_DIR / '*.yaml',
24+
LOCALE_DIR / '*.yml',
25+
]
26+
27+
lang_files = []
28+
29+
for pattern in patterns:
30+
lang_files.extend(glob.glob(str(pattern)))
31+
32+
for lang_file in lang_files:
33+
with open(lang_file, encoding='utf-8') as f:
34+
lang = Path(lang_file).stem
35+
file_type = Path(lang_file).suffix[1:]
36+
match file_type:
37+
case 'json':
38+
self.locales[lang] = json.loads(f.read())
39+
case 'yaml' | 'yml':
40+
self.locales[lang] = yaml.full_load(f.read())
41+
42+
43+
# 创建语言加载器单例
44+
locale_loader = LocaleLoader()

backend/middleware/i18n_middleware.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from starlette.middleware.base import BaseHTTPMiddleware
55

66
from backend.common.i18n import i18n
7+
from backend.core.conf import settings
78

89

910
def get_current_language(request: Request) -> str | None:
@@ -15,7 +16,7 @@ def get_current_language(request: Request) -> str | None:
1516
"""
1617
accept_language = request.headers.get('Accept-Language', '')
1718
if not accept_language:
18-
return None
19+
return settings.I18N_DEFAULT_LANGUAGE
1920

2021
languages = [lang.split(';')[0] for lang in accept_language.split(',')]
2122
lang = languages[0].lower().strip()

0 commit comments

Comments
 (0)