import logging import os from pathlib import Path from typing import Dict, NoReturn, Any, Tuple, Union from babel.messages.pofile import read_po from tuxbot.core import Config from tuxbot.core.config import search_for from tuxbot.core.utils.functions.extra import ContextPlus log = logging.getLogger("tuxbot.core.i18n") _translators = [] available_locales: Dict[str, Tuple] = { "en-US": ("english", "anglais", "en", "us", "en-us"), "fr-FR": ("français", "francais", "french", "fr", "be", "fr-fr"), } def find_locale(locale: str) -> Union[str, NoReturn]: """We suppose `locale` is in `_available_locales.values()`""" for key, val in available_locales.items(): if locale in val: return key raise NotImplementedError("This locale isn't implemented") def list_locales() -> str: description = "" for key, value in available_locales.items(): description += f":flag_{key[-2:].lower()}: {value[0]}\n" return description def get_locale_name(locale: str) -> str: """Return the name of this `locale`""" return available_locales[find_locale(locale)][0] class Translator: """Class to load texts at init.""" def __init__( self, name: str, file_location: Union[Path, os.PathLike, str] ): """Initializes the Translator object. Parameters ---------- name : str The cog name. file_location:Path|os.PathLike|str File path for the required extension. """ self.cog_folder = Path(file_location).resolve().parent self.cog_name = name self.translations: Dict[str, Any] = {} _translators.append(self) self.load_translations() def __call__( self, untranslated: str, ctx: ContextPlus, config: Config ) -> str: try: user_locale = search_for( config.Users, ctx.author.id, "locale", None ) if user_locale: return self.translations[user_locale][untranslated] guild_locale = ( search_for(config.Servers, ctx.guild.id, "locale", None) if ctx.guild else None ) if guild_locale: return self.translations[guild_locale][untranslated] return self.translations[config.Core.locale][untranslated] except KeyError: return untranslated def __repr__(self): return "" % ( self.cog_name, self.cog_folder, ) def load_translations(self): """Loads the current translations.""" for locale in available_locales: locale_path = self.cog_folder / "locales" / f"{locale}.po" with locale_path.open("r") as f: catalog = read_po(f) for message in catalog: if message.id: self._add_translation(locale, message.id, message.string) def _add_translation( self, locale: str, untranslated: str, translated: str ): if translated: if not self.translations.get(locale, False): self.translations[locale] = {} self.translations[locale][untranslated] = translated