38 lines
1.1 KiB
Python
38 lines
1.1 KiB
Python
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, ""))
|