|
6 | 6 |
|
7 | 7 | from dataclasses import dataclass
|
8 | 8 | import logging
|
9 |
| -from typing import Any, Dict, List |
| 9 | +from typing import Any, Dict, List, Optional |
10 | 10 |
|
11 |
| -from ckan.common import config, request |
| 11 | +from ckan.common import config |
12 | 12 |
|
13 | 13 | # -*- coding: utf-8 -*-
|
14 | 14 | from ckan.plugins import toolkit
|
|
23 | 23 | "dcat_type",
|
24 | 24 | ]
|
25 | 25 | RESOURCE_REPLACE_FIELDS = ["format", "language"]
|
| 26 | +TRANSLATED_SUFFIX = "_translated" |
| 27 | +LANGUAGE_VALUE_FIELDS = { |
| 28 | + "population_coverage", |
| 29 | + "publisher_note", |
| 30 | + "provenance", |
| 31 | + "rights", |
| 32 | +} |
26 | 33 | DEFAULT_FALLBACK_LANG = "en"
|
27 | 34 | SUPPORTED_LANGUAGES = {DEFAULT_FALLBACK_LANG, "nl"}
|
28 | 35 |
|
@@ -121,13 +128,18 @@ def collect_values_to_translate(data: Any) -> List:
|
121 | 128 | return list(set(values_to_translate))
|
122 | 129 |
|
123 | 130 |
|
124 |
| -def replace_package(data, translation_dict): |
| 131 | +def replace_package(data, translation_dict, lang: Optional[str] = None): |
| 132 | + preferred_lang = _get_language(lang) |
| 133 | + |
| 134 | + _apply_translated_properties(data, preferred_lang) |
| 135 | + |
125 | 136 | data = _translate_fields(data, PACKAGE_REPLACE_FIELDS, translation_dict)
|
126 | 137 | resources = data.get("resources", [])
|
127 | 138 | data["resources"] = [
|
128 | 139 | _translate_fields(item, RESOURCE_REPLACE_FIELDS, translation_dict)
|
129 | 140 | for item in resources
|
130 | 141 | ]
|
| 142 | + |
131 | 143 | return data
|
132 | 144 |
|
133 | 145 |
|
@@ -156,11 +168,77 @@ def _change_facet(facet, translation_dict):
|
156 | 168 |
|
157 | 169 |
|
158 | 170 | def replace_search_facets(data, translation_dict, lang):
|
| 171 | + preferred_lang = _get_language(lang) |
159 | 172 | new_facets = {}
|
160 | 173 | for key, facet in data.items():
|
161 | 174 | title = facet["title"]
|
162 |
| - new_facets[key] = {"title": get_translations([title], lang=lang).get(title, title)} |
| 175 | + new_facets[key] = { |
| 176 | + "title": get_translations([title], lang=preferred_lang).get(title, title) |
| 177 | + } |
163 | 178 | new_facets[key]["items"] = [
|
164 | 179 | _change_facet(item, translation_dict) for item in facet["items"]
|
165 | 180 | ]
|
166 | 181 | return new_facets
|
| 182 | + |
| 183 | + |
| 184 | +def _apply_translated_properties(data: Any, preferred_lang: str, fallback_lang: str = DEFAULT_FALLBACK_LANG): |
| 185 | + if not isinstance(data, (dict, list)): |
| 186 | + return data |
| 187 | + |
| 188 | + if isinstance(data, list): |
| 189 | + return [ |
| 190 | + _apply_translated_properties(item, preferred_lang, fallback_lang) |
| 191 | + if isinstance(item, (dict, list)) |
| 192 | + else item |
| 193 | + for item in data |
| 194 | + ] |
| 195 | + |
| 196 | + for key, value in list(data.items()): |
| 197 | + if isinstance(value, dict): |
| 198 | + _apply_translated_properties(value, preferred_lang, fallback_lang) |
| 199 | + elif isinstance(value, list): |
| 200 | + data[key] = [ |
| 201 | + _apply_translated_properties(item, preferred_lang, fallback_lang) |
| 202 | + if isinstance(item, (dict, list)) |
| 203 | + else item |
| 204 | + for item in value |
| 205 | + ] |
| 206 | + |
| 207 | + for key, value in list(data.items()): |
| 208 | + if key.endswith(TRANSLATED_SUFFIX) and isinstance(value, dict): |
| 209 | + base_key = key[:-len(TRANSLATED_SUFFIX)] |
| 210 | + merged_values = value.copy() |
| 211 | + existing_value = data.get(base_key) |
| 212 | + if isinstance(existing_value, dict): |
| 213 | + merged_values.update(existing_value) |
| 214 | + data[base_key] = _select_translated_value( |
| 215 | + merged_values, preferred_lang, fallback_lang |
| 216 | + ) |
| 217 | + elif key in LANGUAGE_VALUE_FIELDS and isinstance(value, dict): |
| 218 | + data[key] = _select_translated_value(value, preferred_lang, fallback_lang) |
| 219 | + |
| 220 | + return data |
| 221 | + |
| 222 | + |
| 223 | +def _select_translated_value(values: Dict[str, Any], preferred_lang: str, fallback_lang: str) -> Any: |
| 224 | + if not isinstance(values, dict): |
| 225 | + return values |
| 226 | + |
| 227 | + for lang in (preferred_lang, fallback_lang): |
| 228 | + translated = values.get(lang) |
| 229 | + if _has_content(translated): |
| 230 | + return translated |
| 231 | + |
| 232 | + for translated in values.values(): |
| 233 | + if _has_content(translated): |
| 234 | + return translated |
| 235 | + |
| 236 | + return next(iter(values.values()), "") |
| 237 | + |
| 238 | + |
| 239 | +def _has_content(value: Any) -> bool: |
| 240 | + if value is None: |
| 241 | + return False |
| 242 | + if isinstance(value, str): |
| 243 | + return bool(value.strip()) |
| 244 | + return bool(value) if isinstance(value, (list, dict)) else True |
0 commit comments