set language within a django view

DjangoInternationalization

Django Problem Overview


background: The view is called when a payment service pings back a payment outcome behind the scenes - afterwhich I need to send an email in the right language to confirm payment and so on. I can get the language code back in the request from the payment server and would like to use that along with Django's i18n systems to determine which language to send my email out in.

So I need to set the language of my django app from within a view. And then do my template rendering and emailing all in one go.

setting request.session['django_language'] = lang only effects the next view when I'm testing.

Is there any other way to do it?

Cheers,

Guy

Django Solutions


Solution 1 - Django

To quote parts from Django's Locale Middleware (django.middleware.locale.LocaleMiddleware):

from django.utils import translation

class LocaleMiddleware(object):
    """
    This is a very simple middleware that parses a request
    and decides what translation object to install in the current
    thread context. This allows pages to be dynamically
    translated to the language the user desires (if the language
    is available, of course).
    """

    def process_request(self, request):
        language = translation.get_language_from_request(request)
        translation.activate(language)
        request.LANGUAGE_CODE = translation.get_language()

The translation.activate(language) is the important bit.

Solution 2 - Django

Be sure to also add deactivate in process_response, otherwise you will have problems with different threads.

from django.utils import translation

class LocaleMiddleware(object):
    """
    This is a very simple middleware that parses a request
    and decides what translation object to install in the current
    thread context. This allows pages to be dynamically
    translated to the language the user desires (if the language
    is available, of course).
    """

    def process_request(self, request):
        language = translation.get_language_from_request(request)
        translation.activate(language)
        request.LANGUAGE_CODE = translation.get_language()

    def process_response(self, request, response):
        translation.deactivate()
        return response

Solution 3 - Django

If just want to get the translated strings for a language for whatever reason, you can use override as a decorator like this:

from django.utils import translation
from django.utils.translation import ugettext as _

with translation.override(language):
    welcome = _('welcome')

Solution 4 - Django

You can consider storing the language in the user model and use this custom middleware django-user-language-middleware.

This allows easy translation of your Django app by looking at the selected language in the user.language field and you can always know the language preference of any user.

Usage:

  1. Add a language field to your user model:

     class User(auth_base.AbstractBaseUser, auth.PermissionsMixin):
         # ...
         language = models.CharField(max_length=10,
                                     choices=settings.LANGUAGES,
                                     default=settings.LANGUAGE_CODE)
    
  2. Install the middleware from pip:

    pip install django-user-language-middleware

  3. Add it to your middleware class list in settings to listen to requests:

     MIDDLEWARE = [  # Or MIDDLEWARE_CLASSES on Django < 1.10
         ...
         'user_language_middleware.UserLanguageMiddleware',
         ...
     ]
    

I hope this may help people landing on this question in the future.

Solution 5 - Django

Sometimes you want to enforce a certain language for a given view but let the browser language settings choice the language for the rest of the views. I haven't figured out how to change the language in the view code but you can do this by implementing a simple Middleware

lang_based_on_url_middleware.py:

from django.utils import translation

# Dictionary of urls that should use special language regardless of language set in browser
#   key = url
#   val = language code
special_cases = {
    '/this/is/some/url/' : 'dk',
    '/his/is/another/special/case' : 'de',
                 }

class LangBasedOnUrlMiddleware(object):
    def process_request(self, request):
        if request.path_info in special_cases:
            lang = special_cases[request.path_info]
            translation.activate(lang)
            request.LANGUAGE_CODE = lang

In settings.py:

MIDDLEWARE_CLASSES = (
    ...
    'django.middleware.locale.LocaleMiddleware',
    'inner.lang_based_on_url_middleware.LangBasedOnUrlMiddleware', # remember that the order of LocaleMiddleware and LangBasedOnUrlMiddleware matters
    ...
)

Not an elegant solution but it works.

Solution 6 - Django

request.LANGUAGE_CODE if LocaleMiddleware activated.

Solution 7 - Django

If you are using django 1.10 or higher, there's a new syntax for custom middleware:

from django.utils import translation

class LocaleMiddleware(object):

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

	def __call__(self, request):

		language_code = 'en' #TODO, your logic

		translation.activate(language_code)

		response = self.get_response(request)

		translation.deactivate()

		return response

Solution 8 - Django

With class based views, this should work:

class YourView(SomeBuiltInView):
def get(self, request, *args, **kwargs):
    setattr(request, 'LANGUAGE_CODE', 'YOUR_LANGUAGE_CODE')
    return super().get(self, request, *args, **kwargs)

Basically all you do is make the view renderer think that the request came from YOUR_LANGUAGE_CODE rather than what was originally true.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGuy BowdenView Question on Stackoverflow
Solution 1 - DjangostefanwView Answer on Stackoverflow
Solution 2 - DjangowebjunkieView Answer on Stackoverflow
Solution 3 - DjangoFlimmView Answer on Stackoverflow
Solution 4 - DjangoLaura BarluzziView Answer on Stackoverflow
Solution 5 - DjangoHelgi BorgView Answer on Stackoverflow
Solution 6 - DjangoDenisKolodinView Answer on Stackoverflow
Solution 7 - DjangoPatrik BeckView Answer on Stackoverflow
Solution 8 - Djangoemihir0View Answer on Stackoverflow