Opened 3 years ago

Closed 2 years ago

#20125 closed Cleanup/optimization (fixed)

get_language_from_request() - inconsistent use of fallback language

Reported by: lwarx Owned by: nobody
Component: Internationalization Version: 1.5
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


To set language code django.utils.translation.trans_real.get_language_from_request() consults four places in the following order:

  1. url - get_language_from_path()
  2. session - request.session.get('django_language', None)
  3. cookie - request.COOKIES.get(settings.LANGUAGE_COOKIE_NAME)
  4. accept-language header - request.META.get('HTTP_ACCEPT_LANGUAGE', )

Its docsting says:

Analyzes the request to find what language the user wants the system to
show. Only languages listed in settings.LANGUAGES are taken into account.
If the user requests a sublanguage where we have a main language, we send
out the main language.

(1) and (2) do not use get_supported_language_variant() function (which uses available main language when there is no sublanguage), making it impossible to always have full locale in url or session. Consider this use-case:

I want to build a site which will be available in several countries, and some of them have more than one official language. To do that, I allocate several url prefixes (locales) to always contain both language and country:

  • /fr-ca/
  • /en-ca/
  • /en-us/
  • /en-gb/

Using this scheme there is no need to have separate country selector in the url, and I can have only generic translations like 'en' and 'fr' with the possibility to add specific ones like 'en-gb'.

Is it worth to unify fallback language handling to allow full locale in url and session? There is also two recently closed related tickets: #19811 and #19763

Also this logic is not very easy to override - I can subclass LocaleMiddleware.process_request(), but get_language_from_request() is still monolithic. I think it is better to move accept-language normalization to separate function.

Attachments (1) (4.0 KB) - added by lwarx 2 years ago.
rough concept of how locale selector might look like

Download all attachments as: .zip

Change History (5)

comment:1 Changed 2 years ago by akaariai

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Accepted

At the least the docstring is false.

Changed 2 years ago by lwarx

rough concept of how locale selector might look like

comment:2 Changed 2 years ago by lwarx

I do not have free time to work on this right now, but I have rough concept (not tested at all) of how locale selector could be implemented. It allows subclassing and some steps can be easily disabled. The missing part is the way to inject custom class into LocaleMiddleware.

comment:3 Changed 2 years ago by bouke

In get_language_from_path:453 there is already a call to get_supported_language_variant and the session will only contain languages that were previously available. Is there still a problem with this? Apart from that, I like the locale selector you're working on. The locale selection could do with some cleaning up.

comment:4 Changed 2 years ago by lwarx

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

I haven't switched my projects to 1.6 yet, but after looking at the code (#11915 #19763 #19811 #19919) I think it will do the trick.
Regarding locale selection class, I still do not have much time to work on this, but hope to do it in the future.

If you do not have any objections, I'm closing this ticket for now (refactoring can be moved to separate ticket).

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