zbla
zbla

Reputation: 31

How to manage language redirection in Django middleware with user authentication?

I am developing a middleware in Django to manage language redirection based on the user's language preference, which can be stored in the database or specified in a cookie. The middleware needs to handle URLs that include a language prefix, ensuring they match the user's preferred language, especially after the user logs in.

The middleware is designed to redirect users to the correct language version of a page. However, when a user logs in and a next parameter is used to specify a redirect URL, the language prefix in this URL sometimes does not match the user's preferred language. This results in users being redirected to the default language instead of their preferred language.

Here is the middleware implementation:

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

What I was expecting:

I expected the middleware to consistently redirect to URLs that match the user's preferred language after login, especially when a next parameter is used. The goal is for the URL language prefix and the language specified in the next parameter to always align with the user's language preference.

Questions:

How can I ensure that the language preferences are accurately reflected and preserved in the URL and next parameter during all redirection scenarios, especially after login? Is there a better approach to modify the next parameter in the middleware to ensure language consistency?

Upvotes: 0

Views: 20

Answers (0)

Related Questions