"""Traduccion de claves con dot-path notation e interpolacion de variables.""" import threading _locale_local = threading.local() _translations: dict = {} _default_locale: str = "en" def _set_translations(translations: dict, default_locale: str = "en") -> None: """Configura el diccionario global de traducciones y el locale default. Llamar desde load_translations o al inicio de la aplicacion. """ global _translations, _default_locale _translations = translations _default_locale = default_locale def _set_locale(locale: str) -> None: """Establece el locale para el thread actual.""" _locale_local.locale = locale def _get_locale() -> str: """Retorna el locale del thread actual, o el default si no esta configurado.""" return getattr(_locale_local, "locale", _default_locale) def _resolve_key(translations: dict, locale: str, key: str) -> str | None: """Navega dot-path en el diccionario de traducciones para un locale. Returns: El string de traduccion si existe, None si no. """ locale_dict = translations.get(locale) if not locale_dict: return None parts = key.split(".") node = locale_dict for part in parts: if not isinstance(node, dict): return None node = node.get(part) if node is None: return None return node if isinstance(node, str) else None def t(key: str, locale: str | None = None, **kwargs) -> str: """Traduce una clave con dot-path notation al idioma actual. Determina el locale en orden de prioridad: parametro > thread-local > default. Soporta interpolacion de variables con {nombre} en el valor traducido. Si la clave no existe en el locale solicitado, intenta el locale default. Si tampoco existe, retorna la clave tal cual. Args: key: Clave de traduccion en dot-path notation (ej: "report.taskStarted"). locale: Locale a usar. Si es None usa el locale del thread actual. **kwargs: Variables para interpolar en el string traducido. Returns: String traducido con variables interpoladas, o la key si no se encontro. Example: >>> # translations = {"en": {"report": {"sectionStart": "Section: {title}"}}} >>> t("report.sectionStart", locale="en", title="Introduction") 'Section: Introduction' >>> t("nonexistent.key", locale="en") 'nonexistent.key' """ resolved_locale = locale if locale is not None else _get_locale() value = _resolve_key(_translations, resolved_locale, key) if value is None and resolved_locale != _default_locale: value = _resolve_key(_translations, _default_locale, key) if value is None: return key if kwargs: try: value = value.format(**kwargs) except (KeyError, ValueError): pass return value