56 lines
2.1 KiB
Python
56 lines
2.1 KiB
Python
from __future__ import annotations
|
|
|
|
from django.conf import settings
|
|
from django.http import HttpRequest, HttpResponse, HttpResponseRedirect
|
|
from django.urls import translate_url
|
|
from django.utils.http import url_has_allowed_host_and_scheme
|
|
from django.utils.translation import check_for_language
|
|
from django.utils.translation import get_language as _get_language
|
|
from django.views.decorators.csrf import csrf_exempt
|
|
from django.views.i18n import LANGUAGE_QUERY_PARAMETER
|
|
|
|
from .i18n_utils import normalize_set_language_next
|
|
|
|
|
|
@csrf_exempt
|
|
def set_language_normalized(request: HttpRequest) -> HttpResponse:
|
|
"""
|
|
Set language while normalizing `next` to avoid duplicated locale prefixes.
|
|
|
|
Mirrors Django's set_language behavior closely, but enforces `next`
|
|
normalization before translating redirects.
|
|
"""
|
|
next_url = request.POST.get("next", request.GET.get("next"))
|
|
if next_url:
|
|
next_url = normalize_set_language_next(next_url)
|
|
if next_url and not url_has_allowed_host_and_scheme(
|
|
url=next_url,
|
|
allowed_hosts={request.get_host()},
|
|
require_https=request.is_secure(),
|
|
):
|
|
next_url = request.META.get("HTTP_REFERER")
|
|
if not next_url:
|
|
next_url = "/"
|
|
|
|
response: HttpResponse = HttpResponseRedirect(next_url)
|
|
|
|
if request.method == "POST":
|
|
lang_code = request.POST.get(LANGUAGE_QUERY_PARAMETER)
|
|
if lang_code and check_for_language(lang_code):
|
|
translated = translate_url(next_url, lang_code)
|
|
if translated != next_url:
|
|
response = HttpResponseRedirect(translated)
|
|
response.set_cookie(
|
|
settings.LANGUAGE_COOKIE_NAME,
|
|
lang_code,
|
|
max_age=settings.LANGUAGE_COOKIE_AGE,
|
|
path=settings.LANGUAGE_COOKIE_PATH,
|
|
domain=settings.LANGUAGE_COOKIE_DOMAIN,
|
|
secure=settings.LANGUAGE_COOKIE_SECURE,
|
|
httponly=settings.LANGUAGE_COOKIE_HTTPONLY,
|
|
samesite=settings.LANGUAGE_COOKIE_SAMESITE,
|
|
)
|
|
|
|
response.headers.setdefault("Content-Language", _get_language())
|
|
return response
|