mirror of
https://github.com/CodeSeeed/sbackup.git
synced 2026-10-05 02:42:58 +08:00
109 lines
3.4 KiB
Python
109 lines
3.4 KiB
Python
import json
|
|
import os
|
|
import sys
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
_current_locale = "zh_CN"
|
|
_translations = {}
|
|
|
|
|
|
def _get_locales_dir() -> str:
|
|
"""获取 locales 目录路径(兼容正常 Python 和 Nuitka/PyInstaller 打包)"""
|
|
if getattr(sys, "frozen", False):
|
|
# Nuitka/PyInstaller 打包后,资源在可执行文件同级目录
|
|
base_dir = os.path.dirname(sys.executable)
|
|
return os.path.join(base_dir, "sbackup", "locales")
|
|
# 正常 Python 环境
|
|
return os.path.join(os.path.dirname(__file__), "locales")
|
|
|
|
|
|
# 初始化默认语言包
|
|
_default_file = os.path.join(_get_locales_dir(), "zh_CN.json")
|
|
if os.path.exists(_default_file):
|
|
try:
|
|
with open(_default_file, "r", encoding="utf-8") as f:
|
|
_translations = json.load(f)
|
|
except (json.JSONDecodeError, OSError) as e:
|
|
logger.warning("i18n.load.default_failed %s: %s", _default_file, e)
|
|
|
|
|
|
def set_locale(lang: str) -> None:
|
|
"""
|
|
设置当前语言环境并加载对应的翻译文件
|
|
"""
|
|
global _current_locale, _translations
|
|
|
|
# 安全检查:拒绝包含路径遍历字符的语言代码
|
|
if not lang or "/" in lang or "\\" in lang or ".." in lang or ":" in lang:
|
|
logger.warning("i18n.set_locale.invalid_lang: %s", lang)
|
|
return
|
|
|
|
# 白名单校验:只允许已知的语言代码格式
|
|
_KNOWN_LOCALES = {
|
|
"zh_CN",
|
|
"en_US",
|
|
"fr_FR",
|
|
"es_ES",
|
|
"ru_RU",
|
|
"de_DE",
|
|
"ja_JP",
|
|
"pt_BR",
|
|
"ko_KR",
|
|
}
|
|
if lang not in _KNOWN_LOCALES:
|
|
logger.warning("i18n.set_locale.unknown_locale: %s", lang)
|
|
# 仍然设置 _current_locale 以保持向后兼容
|
|
_current_locale = lang
|
|
# 回退到默认中文翻译
|
|
default_file = os.path.join(_get_locales_dir(), "zh_CN.json")
|
|
if os.path.exists(default_file):
|
|
try:
|
|
with open(default_file, "r", encoding="utf-8") as f:
|
|
_translations = json.load(f)
|
|
except (json.JSONDecodeError, OSError) as e:
|
|
logger.warning(
|
|
t("log.i18n.load.fallback_failed", path=default_file, error=e)
|
|
)
|
|
_translations = {}
|
|
return
|
|
|
|
_current_locale = lang
|
|
locale_file = os.path.join(_get_locales_dir(), f"{lang}.json")
|
|
if os.path.exists(locale_file):
|
|
try:
|
|
with open(locale_file, "r", encoding="utf-8") as f:
|
|
_translations = json.load(f)
|
|
return
|
|
except (json.JSONDecodeError, OSError) as e:
|
|
logger.warning(t("log.i18n.load.failed", path=locale_file, error=e))
|
|
|
|
# 回退到默认中文
|
|
default_file = os.path.join(_get_locales_dir(), "zh_CN.json")
|
|
if os.path.exists(default_file):
|
|
try:
|
|
with open(default_file, "r", encoding="utf-8") as f:
|
|
_translations = json.load(f)
|
|
except (json.JSONDecodeError, OSError) as e:
|
|
logger.warning(
|
|
t("log.i18n.load.fallback_failed", path=default_file, error=e)
|
|
)
|
|
_translations = {}
|
|
|
|
|
|
def t(key: str, **kwargs) -> str:
|
|
"""
|
|
获取翻译文本
|
|
:param key: 翻译键名
|
|
:param kwargs: 格式化参数
|
|
:return: 翻译后的字符串
|
|
"""
|
|
text = _translations.get(key, key)
|
|
if kwargs:
|
|
try:
|
|
return text.format(**kwargs)
|
|
except (KeyError, ValueError):
|
|
return text
|
|
return text
|