Coverage for src/lektor_ng/i18n.py: 96%
48 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-08-31 01:05 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-08-31 01:05 +0000
1import json
2import os
3from importlib import resources
4from pathlib import Path
6translations = {}
7for file in resources.files("lektor_ng").joinpath("translations").iterdir():
8 filename = Path(file.name)
9 if filename.suffix == ".json" and file.is_file():
10 lang = filename.stem
11 with file.open("rb") as f:
12 translations[lang] = json.load(f)
14KNOWN_LANGUAGES = set(translations.keys())
17def get_translations(language):
18 """Looks up the translations for a given language."""
19 return translations.get(language)
22def is_valid_language(lang):
23 """Verifies a language is known and valid."""
24 return lang in KNOWN_LANGUAGES
27def get_default_lang():
28 """Returns the default language the system should use."""
29 for key in "LANGUAGE", "LC_ALL", "LC_CTYPE", "LANG":
30 value = os.environ.get(key)
31 if not value:
32 continue
33 lang = value.split("_")[0].lower()
34 if is_valid_language(lang):
35 return lang
36 return "en"
39def load_i18n_block(key):
40 """Looks up an entire i18n block from a known translation."""
41 rv = {}
42 for lang in KNOWN_LANGUAGES:
43 val = translations.get(lang, {}).get(key)
44 if val is not None:
45 rv[lang] = val
46 return rv
49def get_i18n_block(inifile_or_dict, key, pop=False):
50 """Extracts an i18n block from an ini file or dictionary for a given
51 key. If "pop", delete keys from "inifile_or_dict".
52 """
53 rv = {}
54 for k in list(inifile_or_dict):
55 if k == key:
56 # English is the internal default language with preferred
57 # treatment.
58 rv["en"] = inifile_or_dict.pop(k) if pop else inifile_or_dict[k]
59 elif k.startswith(key + "["):
60 rv[k[len(key) + 1 : -1]] = inifile_or_dict.pop(k) if pop else inifile_or_dict[k]
61 return rv
64def generate_i18n_kvs(**opts):
65 """Generates key-value pairs based on the kwargs passed into this function.
66 For every key ending in "_i18n", its corresponding value will be translated
67 and returned once for every language that has a known translation.
68 """
69 for key, value in opts.items():
70 if key.endswith("_i18n"):
71 base_key = key[:-5]
72 for lang, trans in load_i18n_block(value).items():
73 lang_key = f"{base_key}[{lang}]"
74 yield lang_key, trans
75 else:
76 yield key, value