Coverage for ckanext/udc/solr/config.py: 59%

64 statements  

« prev     ^ index     » next       coverage.py v7.7.1, created at 2026-01-19 23:48 +0000

1from __future__ import annotations 

2import logging 

3from typing import Union 

4 

5from ckan.plugins.toolkit import config 

6from ckan.lib.search.common import SolrSettings 

7import ckan.lib.helpers as h 

8 

9log = logging.getLogger(__name__) 

10 

11 

12def get_udc_langs(): 

13 # read dataset languages, ensure default locale is included 

14 default_lang = config.get("ckan.locale_default", "en") or "en" 

15 raw_langs = config.get("udc.multilingual.languages", default_lang) 

16 

17 # normalize and keep original order 

18 langs = [l.strip() for l in raw_langs.split() if l.strip()] 

19 

20 # deduplicate while preserving order 

21 seen = set() 

22 ordered_langs = [] 

23 for lang in langs: 

24 if lang not in seen: 

25 ordered_langs.append(lang) 

26 seen.add(lang) 

27 

28 # ensure default language is first 

29 remaining_langs = [lang for lang in ordered_langs if lang != default_lang] 

30 return [default_lang] + remaining_langs 

31 

32def get_default_lang(): 

33 """Get the default language from the config, defaulting to 'en'.""" 

34 return config.get("ckan.locale_default", "en") or "en" 

35 

36 

37def get_current_lang(): 

38 """Get the current language from the request context or default to 'en'.""" 

39 lang = h.lang() 

40 if not lang: 

41 lang = config.get("ckan.locale_default", "en") or "en" 

42 return lang 

43 

44 

45def pick_locale(texts: Union[str, dict], lang: str = None) -> str: 

46 """Pick the text in the specified language from a dict of texts. 

47 

48 If texts is a string, return it directly. 

49 If texts is a dict, return the text in the specified language if available, 

50 otherwise return the first text in the dict. 

51 """ 

52 if not lang: 

53 lang = h.lang() or "en" 

54 if isinstance(texts, str): 

55 return texts 

56 elif isinstance(texts, dict): 

57 if lang in texts: 

58 return texts[lang] 

59 elif "en" in texts: 

60 return texts["en"] 

61 elif len(texts) > 0: 

62 return list(texts.values())[0] 

63 return "" 

64 

65 

66def pick_locale_with_fallback(texts: Union[str, dict], lang: str = None) -> tuple: 

67 """Pick the text in the specified language from a dict of texts with fallback chain. 

68 

69 Returns a tuple of (text, actual_lang_used) where actual_lang_used is None if 

70 the requested language was used, or the language code if a fallback was used. 

71 

72 If texts is a string, return (texts, None). 

73 If texts is a dict, try requested language, then follow the precedence order 

74 from get_udc_langs(). Empty strings are treated as missing values. 

75 """ 

76 if not lang: 

77 lang = h.lang() or get_default_lang() 

78 

79 if isinstance(texts, str): 

80 return (texts, None) 

81 

82 if not isinstance(texts, dict): 

83 return ("", None) 

84 

85 # Helper to check if value is non-empty 

86 def is_non_empty(val): 

87 if val is None: 

88 return False 

89 if isinstance(val, str) and not val.strip(): 

90 return False 

91 if isinstance(val, (list, dict)) and not val: 

92 return False 

93 return True 

94 

95 # If requested language exists and is non-empty, return it with None (no fallback) 

96 if lang in texts and is_non_empty(texts[lang]): 

97 return (texts[lang], None) 

98 

99 # Otherwise, try fallback languages in order 

100 lang_order = get_udc_langs() 

101 for fallback_lang in lang_order: 

102 if fallback_lang in texts and is_non_empty(texts[fallback_lang]): 

103 # Return the value and the language code used 

104 return (texts[fallback_lang], fallback_lang) 

105 

106 # Last resort: return any available non-empty value 

107 for k, v in texts.items(): 

108 if is_non_empty(v): 

109 return (v, k) 

110 

111 return ("", None)