from __future__ import annotations import re from typing import Any, Iterable I18N_SETTINGS_KEY = "i18n" REFERENCE_LANGUAGE_CODE = "de" SOURCE_LANGUAGE_CODE = "en" DEFAULT_LANGUAGE_PACKAGES: tuple[dict[str, str], ...] = ( {"code": "de", "label": "German", "native_label": "Deutsch"}, {"code": "en", "label": "English", "native_label": "English"}, ) def normalize_language_code(value: object) -> str: raw = str(value or "").strip().lower().replace("_", "-") parts = [part for part in re.split(r"[^a-z0-9]+", raw) if part] return "-".join(parts) def language_code_candidates(value: object) -> tuple[str, ...]: code = normalize_language_code(value) if not code: return () primary = code.split("-", 1)[0] return tuple(dict.fromkeys((code, primary))) def resolve_language_code(value: object, allowed_codes: Iterable[str]) -> str: allowed = {normalize_language_code(code) for code in allowed_codes if normalize_language_code(code)} for candidate in language_code_candidates(value): if candidate in allowed: return candidate return "" def i18n_settings(settings: dict[str, Any] | None) -> dict[str, Any]: raw = (settings or {}).get(I18N_SETTINGS_KEY) return dict(raw) if isinstance(raw, dict) else {} def normalize_language_packages(raw_packages: object = None) -> list[dict[str, str]]: packages: dict[str, dict[str, str]] = {} for item in DEFAULT_LANGUAGE_PACKAGES: packages[item["code"]] = dict(item) if isinstance(raw_packages, (list, tuple)): for raw in raw_packages: if not isinstance(raw, dict): continue code = normalize_language_code(raw.get("code")) if not code: continue label = str(raw.get("label") or code.upper()).strip() native_label = str(raw.get("native_label") or raw.get("nativeLabel") or label).strip() packages[code] = {"code": code, "label": label, "native_label": native_label} return list(packages.values()) def system_language_packages(settings: dict[str, Any] | None) -> list[dict[str, str]]: return normalize_language_packages(i18n_settings(settings).get("available_languages")) def normalize_enabled_language_codes( codes: object, available_languages: Iterable[dict[str, Any]], *, default_locale: object = None, fallback_codes: Iterable[str] = (REFERENCE_LANGUAGE_CODE, SOURCE_LANGUAGE_CODE), ) -> list[str]: available_codes = [normalize_language_code(item.get("code")) for item in available_languages if isinstance(item, dict)] available = {code for code in available_codes if code} requested: list[str] = [] if isinstance(codes, (list, tuple, set)): requested = [normalize_language_code(item) for item in codes] if not requested: requested = [normalize_language_code(item) for item in fallback_codes] enabled: list[str] = [] for item in requested: code = resolve_language_code(item, available) if code and code not in enabled: enabled.append(code) default_code = resolve_language_code(default_locale, available) if default_code and default_code not in enabled: enabled.insert(0, default_code) if enabled: return enabled if REFERENCE_LANGUAGE_CODE in available: return [REFERENCE_LANGUAGE_CODE] if SOURCE_LANGUAGE_CODE in available: return [SOURCE_LANGUAGE_CODE] return available_codes[:1] def system_enabled_language_codes(settings: dict[str, Any] | None, *, default_locale: object = None) -> list[str]: i18n = i18n_settings(settings) raw_enabled = i18n.get("enabled_language_codes", i18n.get("enabled_languages")) return normalize_enabled_language_codes(raw_enabled, system_language_packages(settings), default_locale=default_locale) def tenant_enabled_language_codes( tenant_settings: dict[str, Any] | None, system_enabled_codes: Iterable[str], *, default_locale: object = None, ) -> list[str]: enabled = [normalize_language_code(code) for code in system_enabled_codes if normalize_language_code(code)] available = [{"code": code} for code in enabled] raw_enabled = i18n_settings(tenant_settings).get("enabled_language_codes") return normalize_enabled_language_codes(raw_enabled, available, default_locale=default_locale, fallback_codes=enabled) def user_enabled_language_codes(user_settings: dict[str, Any] | None, tenant_enabled_codes: Iterable[str]) -> list[str]: enabled = [normalize_language_code(code) for code in tenant_enabled_codes if normalize_language_code(code)] available = [{"code": code} for code in enabled] raw_enabled = i18n_settings(user_settings).get("enabled_language_codes") return normalize_enabled_language_codes(raw_enabled, available, fallback_codes=enabled) def preferred_language_code(user_settings: dict[str, Any] | None, allowed_codes: Iterable[str], *, default_locale: object = None) -> str: enabled = [normalize_language_code(code) for code in allowed_codes if normalize_language_code(code)] preferred = resolve_language_code(i18n_settings(user_settings).get("preferred_language"), enabled) if preferred: return preferred default = resolve_language_code(default_locale, enabled) if default: return default return enabled[0] if enabled else REFERENCE_LANGUAGE_CODE def update_i18n_settings(settings: dict[str, Any] | None, **values: Any) -> dict[str, Any]: updated = dict(settings or {}) current = i18n_settings(updated) current.update(values) updated[I18N_SETTINGS_KEY] = current return updated def system_i18n_payload(settings_item: Any | None) -> dict[str, object]: settings = getattr(settings_item, "settings", None) packages = system_language_packages(settings) available_codes = [item["code"] for item in packages] default_language = ( resolve_language_code(getattr(settings_item, "default_locale", None), available_codes) or REFERENCE_LANGUAGE_CODE ) enabled = system_enabled_language_codes(settings, default_locale=default_language) if default_language not in enabled: default_language = enabled[0] if enabled else REFERENCE_LANGUAGE_CODE return { "available_languages": packages, "enabled_languages": enabled, "default_language": default_language, }