diff --git a/README.md b/README.md index da87bce..1b1b6e2 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ from internationalization import I18N I18N("localization_dir", "en") print(i18n['key']) +print(i18n('key', some=123)) print(i18n.get_phrase('key', some=123)) ``` diff --git a/builtins.i18n.pyi.py b/builtins.i18n.pyi.py index e69de29..8be3dc0 100644 --- a/builtins.i18n.pyi.py +++ b/builtins.i18n.pyi.py @@ -0,0 +1,36 @@ +class i18n: + @staticmethod + def set_lang(lang, encoding=None) -> None: + """ + Set the language and encoding for the locale file. + :param lang: Use the language file with the given language. + :param encoding: Encoding of the language file. + :return: None + """ + @staticmethod + def get_phrase(key: str, **kwargs) -> str: + """ + Get the phrase from the locale file. If the phrase is not found, return the key in uppercase. + + :param key: Key to search in the locale file. + :param kwargs: Arguments to format the phrase. + :return: The phrase from the locale file. + """ + @staticmethod + def __call__(key: str, **kwargs) -> str: + """ + Get the phrase from the locale file. If the phrase is not found, return the key in uppercase. + + :param key: Key to search in the locale file. + :param kwargs: Arguments to format the phrase. + :return: The phrase from the locale file. + """ + @staticmethod + def __getitem__(key: str) -> str: + """ + Get the phrase from the locale file. If the phrase is not found, return the key in uppercase. + + :param key: Key to search in the locale file. + :return: The phrase from the locale file. + """ +class i10n(i18n): ... diff --git a/internationalization/i18n.py b/internationalization/i18n.py index 743abf3..3b1c0dc 100644 --- a/internationalization/i18n.py +++ b/internationalization/i18n.py @@ -1,4 +1,73 @@ +import builtins +from collections import defaultdict + +import json5 +from loguru import logger + +from . import utils + +log = logger.bind(module="i18n", prefix="init") +log_load = logger.bind(module="i18n", prefix="load") class I18N: - def __init__(self, lock_dir, load_lang): - pass + + def __init__(self, locale_dir, load_lang, encoding): + """ + Load the language file and set the locale directory. Use JSON5 format for the language file. + + :param locale_dir: {BASE_DIR}/resources/{locale_dir} + :param load_lang: some.lang + """ + self._locale_dir = utils.get_file(locale_dir) # {BASE_DIR}/resources/{locale_dir} + self._lang = load_lang + self._encoding = encoding + + self._locale = {} + log.debug("Injecting to builtins") + builtins.i18n = self + builtins.i10n = self + log.debug("Ready") + self._load() + + def _load(self): + if not self._locale_dir: + raise FileNotFoundError(f"Locale directory not found: {self._locale_dir}") + if (locale_file:=self._locale_dir / f"{self._lang}.json5").exists(): + log_load.debug(f"Loading locale file: {locale_file}") + with open(locale_file, "r", encoding=self._encoding) as f: + data = json5.load(f) + self._locale = utils.flatten_dict(data) + log_load.debug("Loaded and flattened.") + else: + raise FileNotFoundError(f"Locale file not found: {locale_file}") + + def set_lang(self, lang, encoding=None): + """ + Set the language and encoding for the locale file. + :param lang: Use the language file with the given language. + :param encoding: Encoding of the language file. + :return: None + """ + self._lang = lang + self._encoding = encoding or self._encoding + self._load() + + def get_phrase(self, key: str, **kwargs) -> str: + """ + Get the phrase from the locale file. If the phrase is not found, return the key in uppercase. + + :param key: Key to search in the locale file. + :param kwargs: Arguments to format the phrase. + :return: The phrase from the locale file. + """ + # key: some.key.here + phrase = self._locale.get(key) + if not phrase: + return key.upper() + return phrase.format_map(defaultdict(lambda: '???', kwargs)) + + def __call__(self, key: str, **kwargs): + return self.get_phrase(key, **kwargs) + + def __getitem__(self, key: str): + return self.get_phrase(key) diff --git a/internationalization/utils.py b/internationalization/utils.py index 2e0b737..334fa54 100644 --- a/internationalization/utils.py +++ b/internationalization/utils.py @@ -11,3 +11,13 @@ def base_path(): def get_file(filename): return base_path() / "resources" / filename + +def flatten_dict(d, parent_key='', sep='.'): + items = [] + for k, v in d.items(): + new_key = f"{parent_key}{sep}{k}" if parent_key else k + if isinstance(v, dict): + items.extend(flatten_dict(v, new_key, sep=sep).items()) + else: + items.append((new_key, v)) + return dict(items)