Opened 7 years ago

Closed 7 years ago

Last modified 4 years ago

#7072 closed (fixed)

i18n gets active language inconsistently

Reported by: akaihola 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 akaihola 7 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 7 years ago by akaihola

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

comment:1 Changed 7 years ago by akaihola

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

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 7 years ago by Simon Greenhill

  • Has patch set
  • Triage Stage changed from Unreviewed to Ready for checkin

comment:3 Changed 7 years ago by telenieko

  • milestone set to 1.0
  • Summary changed from i18n context processor misses post-middleware changes to active language to i18n gets active language inconsistently

Seems to be a bug, so marking for 1.0

comment:4 Changed 7 years ago by mtredinnick

  • Resolution set to fixed
  • Status changed from new to closed

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

Analysis and patch from akaihola.

comment:5 Changed 4 years ago by jacob

  • milestone 1.0 deleted

Milestone 1.0 deleted

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