Как управлять перенаправлением языков в промежуточном ПО Django с аутентификацией пользователей?

Я разрабатываю промежуточное ПО на Django для управления языковой переадресацией на основе языковых предпочтений пользователя, которые могут храниться в базе данных или указываться в cookie. Промежуточное ПО должно обрабатывать URL-адреса, включающие языковой префикс, обеспечивая их соответствие предпочтительному языку пользователя, особенно после того, как пользователь войдет в систему.

Промежуточное ПО предназначено для перенаправления пользователей на нужную языковую версию страницы. Однако, когда пользователь входит в систему и параметр next используется для указания URL-адреса перенаправления, префикс языка в этом URL-адресе иногда не совпадает с предпочитаемым языком пользователя. В результате пользователи перенаправляются на язык по умолчанию, а не на предпочитаемый язык.

Вот реализация промежуточного ПО:

from django.http import HttpResponseRedirect
from django.utils.http import urlencode
from urllib.parse import urlparse, urlunparse, parse_qs
from django.utils.translation import activate

class UserLanguageMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        excepted_paths = ["/stripe/", "/api/", "/media/", "/static/", "/set-language/"]

        if any(request.path.startswith(path) for path in excepted_paths):
            return response

        preferred_language = None
        if request.user.is_authenticated:
            preferred_language = getattr(request.user, "language", None)
        
        if not preferred_language:
            preferred_language = request.COOKIES.get(settings.LANGUAGE_COOKIE_NAME, "en")

        activate(preferred_language)

        current_cookie_language = request.COOKIES.get(settings.LANGUAGE_COOKIE_NAME)
        if current_cookie_language != preferred_language:
            response.set_cookie(
                settings.LANGUAGE_COOKIE_NAME,
                preferred_language,
                max_age=365 * 24 * 60 * 60,
                path="/",
            )

        current_full_path = request.get_full_path()
        url = urlparse(current_full_path)
        if preferred_language not in url.path:
            query_params = parse_qs(url.query)
            next_path = query_params.get('next', [None])[0]

            if next_path:
                next_url = urlparse(next_path)
                if next_url.path[:3] in ("/en", "/sl", "/hr"):
                    next_path = f'/{preferred_language}{next_url.path[3:]}'
                else:
                    next_path = f'/{preferred_language}{next_url.path}'
                query_params['next'] = [next_path]
                url = url._replace(query=urlencode(query_params, doseq=True))

            modified_path = (
                url.path[3:]
                if url.path[:3] in ("/en", "/sl", "/hr")
                else url.path
            )
            new_path = f"/{preferred_language}{modified_path}"
            new_url = urlunparse(
                (
                    url.scheme,
                    url.netloc,
                    new_path,
                    url.params,
                    urlencode(query_params, doseq=True),
                    url.fragment,
                )
            )
            return HttpResponseRedirect(new_url)

        return response

То, что я ожидал:

Я ожидал, что промежуточное ПО будет последовательно перенаправлять на URL-адреса, соответствующие предпочитаемому языку пользователя после входа в систему, особенно если используется параметр next. Цель состоит в том, чтобы языковой префикс URL и язык, указанный в следующем параметре, всегда соответствовали языковым предпочтениям пользователя.

Вопросы:

Как обеспечить точное отражение и сохранение языковых предпочтений в URL и следующем параметре во всех сценариях перенаправления, особенно после входа в систему? Есть ли лучший подход к изменению следующего параметра в промежуточном ПО для обеспечения согласованности языка?

Вернуться на верх