from __future__ import annotations import re from urllib.parse import urlsplit, urlunsplit from django.conf import settings def normalize_set_language_next(value: str | None) -> str: """ Normalize the `next` path used by Django's set_language view. Removes any leading language prefix from the path so switching from one locale to another cannot produce duplicated prefixes like `/de/en/...`. """ if not value: return "/" parsed = urlsplit(str(value)) path = parsed.path or "/" if not path.startswith("/"): path = f"/{path}" configured_codes = { str(code).lower().replace("_", "-") for code, _ in settings.LANGUAGES } first_segment, _, remainder = path.lstrip("/").partition("/") normalized_segment = first_segment.lower().replace("_", "-") looks_like_language_code = bool( re.fullmatch(r"[a-z]{2}(?:-[a-z]{2})?", normalized_segment) ) should_strip = normalized_segment in configured_codes or looks_like_language_code if should_strip: path = f"/{remainder}" if remainder else "/" return urlunsplit(("", "", path, parsed.query, ""))