Bryan Menoscal
Bryan Menoscal

Reputation: 1

Django gettext translation doesnt work on dynamic translations

Question

I am working on a Django application that supports multiple languages. I am using token-based authentication and trying to change the language for authenticated users based on their preference stored in their profile. However, I am encountering a few issues regarding how the translations are being applied, particularly when it comes to dynamic message translations.

What I have:

Problem

Language preference seems to be applied for static content (like templates), but dynamic translations for strings in views (using gettext) are not applying correctly after the user’s preferred language is set.

For example, while the language change works partially (like UI content), messages generated using gettext() (like error or success messages) are still showing in the default language (en), not the user's preferred language (e.g., es for Spanish).

Here are some observations:

What I have tried:

My setup:

MIDDLEWARE configuration (relevant snippet):


MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",  # Ensuring session is set before locale
    "django.middleware.locale.LocaleMiddleware",  # Language activation middleware
    "django.contrib.auth.middleware.AuthenticationMiddleware",  # Authentication for token
    # Other middleware
]
Custom Language Middleware:

from django.utils import translation

def get_user_language(user):
    if user and hasattr(user, 'preferred_language') and user.preferred_language:
        return user.preferred_language
    return None

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

    def __call__(self, request):
        if hasattr(request, 'user') and request.user.is_authenticated:
            language = get_user_language(request.user)
            if language:
                translation.activate(language)  # Activate user preferred language
        response = self.get_response(request)
        return response

Session Cookie: I am also ensuring that the language preference is stored in the session and cookie.

Expected Behavior: I expect the dynamic translations (using gettext() and gettext_lazy()) to change based on the user’s preferred language. However, despite setting the correct language preference, only some parts of the site (like templates) are reflecting the new language, while others (like dynamically generated messages) still show in the default language (en).

Question: Is there something missing in my setup that would allow the dynamic translation strings to respect the preferred language of the authenticated user? How can I ensure that the translations are applied globally, including dynamic messages, after the user’s language is set in the session and cookie? Any guidance or advice on this would be greatly appreciated. Thanks!

Upvotes: 0

Views: 37

Answers (1)

pradeepcep
pradeepcep

Reputation: 932

Depending on where you have defined your error messages, it is likely that the gettext() calls are evaluated before you set the active language in the middleware.

To illustrate, here is a snippet from a Django project with translations set up:

In [2]: from django.utils.translation import gettext, gettext_lazy, activate

In [3]: foo = gettext("Cows")

In [4]: bar = gettext_lazy("Cows")

In [5]: activate('ta')

In [6]: foo2 = gettext("Cows")

In [7]: bar2 = gettext_lazy("Cows")

In [8]: print("foo =", foo, "bar =", bar, "foo2 =", foo2, "bar2 =", bar2)

foo = Cows bar = பசுக்கள் foo2 = பசுக்கள் bar2 = பசுக்கள்

Here you can see how gettext() fetches the text immediately, while gettext_lazy() waits until it is evaluated (i.e. when it is printed).

So if you use gettext_lazy() instead of gettext(), then your strings will be evaluated only at the time of rendering your response, and that should make it use the right translated string. Hope this helps.

Upvotes: 0

Related Questions