import json from pathlib import Path from functools import lru_cache from typing import Any, Dict FALLBACK_LANG = "ru" @lru_cache(maxsize=16) def _load_lang(lang: str) -> Dict[str, Any]: base_dir = Path(__file__).resolve().parents[1] / "locales" file_path = base_dir / f"{lang}.json" if not file_path.exists(): # fallback to default if lang != FALLBACK_LANG: return _load_lang(FALLBACK_LANG) return {} try: return json.loads(file_path.read_text(encoding="utf-8")) except Exception: return {} def _resolve_key(data: Dict[str, Any], dotted_key: str) -> Any: cur: Any = data for part in dotted_key.split("."): if not isinstance(cur, dict) or part not in cur: return None cur = cur[part] return cur def get_user_lang(user) -> str: """Унифицированное получение языка интерфейса пользователя.""" return (getattr(user, 'language_interface', None) if user else None) or 'ru' def t(lang: str, key: str, **kwargs) -> str: """Translate key for given lang; fallback to ru and to key itself. Supports dotted keys and str.format(**kwargs) placeholders. """ data = _load_lang(lang or FALLBACK_LANG) value = _resolve_key(data, key) if value is None and lang != FALLBACK_LANG: value = _resolve_key(_load_lang(FALLBACK_LANG), key) if value is None: value = key # last resort: return the key try: if isinstance(value, str) and kwargs: return value.format(**kwargs) except Exception: pass return value if isinstance(value, str) else str(value)