Coverage for src/lektor_ng/i18n.py: 96%

48 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-08-09 00:28 +0000

1import json 

2import os 

3from importlib import resources 

4from pathlib import Path 

5 

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) 

13 

14KNOWN_LANGUAGES = set(translations.keys()) 

15 

16 

17def get_translations(language): 

18 """Looks up the translations for a given language.""" 

19 return translations.get(language) 

20 

21 

22def is_valid_language(lang): 

23 """Verifies a language is known and valid.""" 

24 return lang in KNOWN_LANGUAGES 

25 

26 

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" 

37 

38 

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 

47 

48 

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 

62 

63 

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