lektor_ng.i18n

src/lektor_ng/i18n.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import json
import os
from importlib import resources
from pathlib import Path

translations = {}
for file in resources.files("lektor_ng").joinpath("translations").iterdir():
    filename = Path(file.name)
    if filename.suffix == ".json" and file.is_file():
        lang = filename.stem
        with file.open("rb") as f:
            translations[lang] = json.load(f)

KNOWN_LANGUAGES = set(translations.keys())


def get_translations(language):
    """Looks up the translations for a given language."""
    return translations.get(language)


def is_valid_language(lang):
    """Verifies a language is known and valid."""
    return lang in KNOWN_LANGUAGES


def get_default_lang():
    """Returns the default language the system should use."""
    for key in "LANGUAGE", "LC_ALL", "LC_CTYPE", "LANG":
        value = os.environ.get(key)
        if not value:
            continue
        lang = value.split("_")[0].lower()
        if is_valid_language(lang):
            return lang
    return "en"


def load_i18n_block(key):
    """Looks up an entire i18n block from a known translation."""
    rv = {}
    for lang in KNOWN_LANGUAGES:
        val = translations.get(lang, {}).get(key)
        if val is not None:
            rv[lang] = val
    return rv


def get_i18n_block(inifile_or_dict, key, pop=False):
    """Extracts an i18n block from an ini file or dictionary for a given
    key. If "pop", delete keys from "inifile_or_dict".
    """
    rv = {}
    for k in list(inifile_or_dict):
        if k == key:
            # English is the internal default language with preferred
            # treatment.
            rv["en"] = inifile_or_dict.pop(k) if pop else inifile_or_dict[k]
        elif k.startswith(key + "["):
            rv[k[len(key) + 1 : -1]] = inifile_or_dict.pop(k) if pop else inifile_or_dict[k]
    return rv


def generate_i18n_kvs(**opts):
    """Generates key-value pairs based on the kwargs passed into this function.
    For every key ending in "_i18n", its corresponding value will be translated
    and returned once for every language that has a known translation.
    """
    for key, value in opts.items():
        if key.endswith("_i18n"):
            base_key = key[:-5]
            for lang, trans in load_i18n_block(value).items():
                lang_key = f"{base_key}[{lang}]"
                yield lang_key, trans
        else:
            yield key, value