Edit on GitHub

sysmon_pytk.app_locale

Locale management.

 1# SPDX-FileCopyrightText: © 2024 Stacey Adams <stacey.belle.rose@gmail.com>
 2# SPDX-License-Identifier: MIT
 3
 4"""
 5Locale management.
 6"""
 7
 8from __future__ import annotations
 9
10import gettext
11import importlib
12import inspect
13from configparser import ConfigParser, Error
14from pathlib import Path
15from typing import TYPE_CHECKING
16
17from .file_utils import settings_path
18
19if TYPE_CHECKING:
20    from .callables import GettextCallable
21
22LANGUAGES = {
23    "English": "en",
24    "Español": "es",
25    "Deutsch": "de",
26    "Norsk Bokmål": "nb_NO"
27}
28"""The list of language translations available."""
29
30__i18n_domain__ = "app"
31
32TRANSLATED_MODULES: list = []
33"""
34List of modules which have requested translated strings.
35
36When the translation is changed, these modules will be reloaded.
37"""
38
39
40def get_translator(
41    *, forced_lang: str | None = None, domain: str = __i18n_domain__
42) -> GettextCallable:
43    """
44    Load the selected translation.
45
46    Parameters
47    ----------
48    forced_lang : str, optional
49        The language to force-load. If not set, read the language from Settings
50        and load that one.
51    domain : str, optional
52        The gettext domain to use. Default is set by `__i18n_domain__`. Useful
53        for loading translation files for other modules, such as `argparse.py`.
54
55    Returns
56    -------
57    GettextCallable
58        a Callable with the signature: func(message: str) -> str:
59    """
60    current_lang = forced_lang if forced_lang else _get_lang_from_config()
61    frm = inspect.stack()[1]  # get caller
62    mod = inspect.getmodule(frm.frame)
63    if mod not in TRANSLATED_MODULES:
64        TRANSLATED_MODULES.append(mod)
65        TRANSLATED_MODULES.sort(key=lambda x: x.__name__)
66    _localedir = Path.resolve(Path(__file__).parent) / "locale"
67    translation = gettext.translation(
68        domain, _localedir, fallback=True, languages=[current_lang]
69    )
70    return translation.gettext
71
72
73def reload_translated_modules() -> None:
74    """
75    Reload any modules that have requested translations.
76
77    This should be called when the user selects a new translation.
78    """
79    for mod in TRANSLATED_MODULES:
80        importlib.reload(mod)
81
82
83def _get_lang_from_config() -> str:
84    current_lang = "en"
85    try:
86        _filename = settings_path()
87        _config = ConfigParser()
88        _config.read(_filename)
89        if "general" in _config.sections():
90            current_lang = _config["general"].get("language", fallback="en")
91    except Error:
92        pass
93    return current_lang
LANGUAGES = {'English': 'en', 'Español': 'es', 'Deutsch': 'de', 'Norsk Bokmål': 'nb_NO'}

The list of language translations available.

TRANSLATED_MODULES: list = []

List of modules which have requested translated strings.

When the translation is changed, these modules will be reloaded.

def get_translator( *, forced_lang: str | None = None, domain: str = 'app') -> 'GettextCallable':
41def get_translator(
42    *, forced_lang: str | None = None, domain: str = __i18n_domain__
43) -> GettextCallable:
44    """
45    Load the selected translation.
46
47    Parameters
48    ----------
49    forced_lang : str, optional
50        The language to force-load. If not set, read the language from Settings
51        and load that one.
52    domain : str, optional
53        The gettext domain to use. Default is set by `__i18n_domain__`. Useful
54        for loading translation files for other modules, such as `argparse.py`.
55
56    Returns
57    -------
58    GettextCallable
59        a Callable with the signature: func(message: str) -> str:
60    """
61    current_lang = forced_lang if forced_lang else _get_lang_from_config()
62    frm = inspect.stack()[1]  # get caller
63    mod = inspect.getmodule(frm.frame)
64    if mod not in TRANSLATED_MODULES:
65        TRANSLATED_MODULES.append(mod)
66        TRANSLATED_MODULES.sort(key=lambda x: x.__name__)
67    _localedir = Path.resolve(Path(__file__).parent) / "locale"
68    translation = gettext.translation(
69        domain, _localedir, fallback=True, languages=[current_lang]
70    )
71    return translation.gettext

Load the selected translation.

Parameters
  • forced_lang (str, optional): The language to force-load. If not set, read the language from Settings and load that one.
  • domain (str, optional): The gettext domain to use. Default is set by __i18n_domain__. Useful for loading translation files for other modules, such as argparse.py.
Returns
  • GettextCallable: a Callable with the signature: func(message: str) -> str:
def reload_translated_modules() -> None:
74def reload_translated_modules() -> None:
75    """
76    Reload any modules that have requested translations.
77
78    This should be called when the user selects a new translation.
79    """
80    for mod in TRANSLATED_MODULES:
81        importlib.reload(mod)

Reload any modules that have requested translations.

This should be called when the user selects a new translation.