Opened 9 years ago

Closed 9 years ago

Last modified 5 years ago

#7072 closed (fixed)

i18n gets active language inconsistently

Reported by: Antti Kaihola Owned by: nobody
Component: Internationalization Version: master
Severity: Keywords:
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:


Here is a snippet from the current code for django.core.context_processors.i18n:

    if hasattr(request, 'LANGUAGE_CODE'):
        context_extras['LANGUAGE_CODE'] = request.LANGUAGE_CODE
        context_extras['LANGUAGE_CODE'] = settings.LANGUAGE_CODE
    context_extras['LANGUAGE_BIDI'] = translation.get_language_bidi()

The bi-directionality of the active language is retrieved from the translation.get_language_bidi() function, which in turn calls translation.get_language() to get the active language.

On the other hand, the language code is looked up in the request, where it was copied from a session variable by LocaleMiddleware.process_request:

        language = translation.get_language_from_request(request)
        request.LANGUAGE_CODE = translation.get_language()

Now, if the active language is ever changed after the middleware by calling translation.activate(some_language_code), things get out of sync:

  • the LANGUAGE_CODE context variable indicates the language resolved from the request
  • LANGUAGE_BIDI will reflect the bi-directionality of the newly set language instead
  • calling translation.get_language() will return the new language

This causes no problem if Django's default i18n mechanisms are used: whenever the language is changed, the user is re-directed back to a content page, and request.LANGUAGE_CODE == context.LANGUAGE_CODE.

But if one wants to implement the language code as part of the URL, as suggested e.g. in a article, there's no need to re-direct when changing the language. Language selection is simply done with links pointing to a URL which contains the new language code. No session variable nor request.LANGUAGE_CODE is needed, since translation.activate() and translation.get_language() can be used instead.

A simple change to the i18n context processor would adapt Django to a multi-lingual URL scheme without backwards incompatible side effects. If the LANGUAGE_CODE template context variable is retrieved by calling get_language(), any change to the active language at the URL resolution or even view processing stage is taken into account.

Attachments (1)

7072_i18n_context_processor_fix.diff (729 bytes) - added by Antti Kaihola 9 years ago.
patch for retrieving active language from get_language() instead of request.LANGUAGE_CODE in the i18n context processor

Download all attachments as: .zip

Change History (6)

Changed 9 years ago by Antti Kaihola

patch for retrieving active language from get_language() instead of request.LANGUAGE_CODE in the i18n context processor

comment:1 Changed 9 years ago by Antti Kaihola

A note about the patch:

The request.LANGUAGE_CODE -> settings.LANGUAGE_CODE fallback should work correctly also with the patched code, since [source:django/trunk/django/utils/translation/ translation.get_language()] does the fallback internally.

comment:2 Changed 9 years ago by Simon Greenhill

Has patch: set
Triage Stage: UnreviewedReady for checkin

comment:3 Changed 9 years ago by Marc Fargas

milestone: 1.0
Summary: i18n context processor misses post-middleware changes to active languagei18n gets active language inconsistently

Seems to be a bug, so marking for 1.0

comment:4 Changed 9 years ago by Malcolm Tredinnick

Resolution: fixed
Status: newclosed

(In [7843]) Fixed #7072 -- More logical and robust language settings in the i18n context processor.

Analysis and patch from akaihola.

comment:5 Changed 5 years ago by Jacob

milestone: 1.0

Milestone 1.0 deleted

Note: See TracTickets for help on using tickets.
Back to Top