Source code for aiogram_i18n.cores.fluent_runtime_core

from collections.abc import Callable
from pathlib import Path
from typing import Any, cast

from aiogram_i18n.exceptions import FluentMessageError, KeyNotFoundError, NoModuleError
from aiogram_i18n.utils.text_decorator import td

try:
    from fluent.runtime import FluentBundle, FluentResource
except ImportError as e:
    raise NoModuleError(name="FluentRuntimeCore", module_name="fluent.runtime") from e

from aiogram_i18n.cores.base import BaseCore


[docs] class FluentRuntimeCore(BaseCore[FluentBundle]): def __init__( self, path: str | Path, default_locale: str | None = None, use_isolating: bool = False, functions: dict[str, Callable[..., Any]] | None = None, pre_compile: bool = True, raise_key_error: bool = True, use_td: bool = True, locales_map: dict[str, str] | None = None, ) -> None: super().__init__(path=path, default_locale=default_locale, locales_map=locales_map) self.use_isolating = use_isolating self.functions = functions or {} if use_td: self.functions.update(td.functions) self.pre_compile = pre_compile self.raise_key_error = raise_key_error
[docs] def get(self, message_id: str, locale: str | None = None, /, **kwargs: Any) -> str: locale = self.get_locale(locale=locale) translator: FluentBundle = self.get_translator(locale=locale) try: message = translator.get_message(message_id=message_id) if message.value is None: raise KeyError(message) # noqa: TRY301 except KeyError: locale: str | None = self.locales_map.get(locale) if locale is not None: return self.get(message_id, locale, **kwargs) if self.raise_key_error: raise KeyNotFoundError(message_id) from None return message_id text, errors = translator.format_pattern(pattern=message.value, args=kwargs) if errors: raise FluentMessageError(message_id=message_id, errors=errors) return cast(str, text)
[docs] def find_locales(self) -> dict[str, FluentBundle]: translations: dict[str, FluentBundle] = {} locales = self._extract_locales(self.path) for locale, paths in self._find_locales(self.path, locales, ".ftl").items(): translations[locale] = FluentBundle( locales=[locale], use_isolating=self.use_isolating, functions=self.functions ) for path in paths: with path.open("r", encoding="utf8") as fp: translations[locale].add_resource(FluentResource(fp.read())) if self.pre_compile: self.__compile_runtime(translations[locale]) return translations
@staticmethod def __compile_runtime(fb: FluentBundle) -> None: for key, value in fb._messages.items(): # noqa: SLF001 if key not in fb._compiled: # noqa: SLF001 fb._compiled[key] = fb._compiler(value) # noqa: SLF001 for key, value in fb._terms.items(): # noqa: SLF001 key = f"-{key}" if key not in fb._compiled: # noqa: SLF001 fb._compiled[key] = fb._compiler(value) # noqa: SLF001