def _substitute_localizations()

in experimenter/experimenter/experiments/api/v5/serializers.py [0:0]


    def _substitute_localizations(feature_value, substitutions, locale_code):
        ID_RE = re.compile(r"^[A-Za-z0-9\-]+$")
        missing_ids = set()

        def substitute(value):
            if isinstance(value, list):
                return [substitute(item) for item in value]

            if isinstance(value, dict):
                if "$l10n" in value and isinstance(value["$l10n"], dict):
                    l10n = value["$l10n"]

                    if not isinstance(l10n.get("id"), str):
                        raise LocalizationError("$l10n object is missing 'id'")

                    sub_id = value["$l10n"]["id"]

                    if len(sub_id) < NimbusConstants.L10N_MIN_STRING_ID_LEN:
                        raise LocalizationError(
                            f"$l10n id '{sub_id}' must be at least "
                            f"{NimbusConstants.L10N_MIN_STRING_ID_LEN} characters long"
                        )

                    if ID_RE.match(sub_id) is None:
                        raise LocalizationError(
                            f"$l10n id '{sub_id}' contains invalid characters; only "
                            f"alphanumeric characters and dashes are permitted"
                        )

                    if not isinstance(l10n.get("text"), str):
                        raise LocalizationError(
                            f"$l10n object with id '{sub_id}' is missing 'text'"
                        )

                    if not isinstance(l10n.get("comment"), str):
                        raise LocalizationError(
                            f"$l10n object with id '{sub_id}' is missing 'comment'"
                        )

                    if sub_id not in substitutions:
                        missing_ids.add(sub_id)
                        return None

                    return substitutions[sub_id]
                else:
                    return {k: substitute(v) for k, v in value.items()}

            return value

        subbed = substitute(feature_value)

        if missing_ids:
            missing_ids_str = ", ".join(sorted(missing_ids))
            raise serializers.ValidationError(
                {
                    "localizations": [
                        f"Locale {locale_code} is missing substitutions for IDs: "
                        f"{missing_ids_str}"
                    ]
                }
            )

        return subbed