#28567: Unclear documentation for 'next' parameter of set_language view
-------------------------------------+-------------------------------------
     Reporter:  George Tantiras      |                    Owner:  George
                                     |  Tantiras
         Type:  Bug                  |                   Status:  assigned
    Component:                       |                  Version:  master
  Internationalization               |
     Severity:  Normal               |               Resolution:
     Keywords:                       |             Triage Stage:  Accepted
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Changes (by Carlton Gibson):

 * cc: Claude Paroz (added)
 * has_patch:  1 => 0
 * component:  Documentation => Internationalization


Comment:

 This looks like a bug to me, rather than a documentation issue.

 You shouldn't have to set the `next` parameter, manually calling
 `translate_url()` to get the value, since
 
[https://github.com/django/django/blob/8ba20d9071e9e1b8f2c81d4df977db4278342085/django/views/i18n.py#L45-L48
 the `set_language()` view does that itself]:


 {{{
                 next_trans = translate_url(next, lang_code)
                 if next_trans != next:
                     response = HttpResponseRedirect(next_trans)
 }}}

 A breakpoint inserted here, in the failing test case George provided
 ([https://github.com/django/django/pull/9058 Original PR]), shows the
 `translate_url()` call failing.

 Furthermore, as per the report, the `translate_url()` call works when
 `prefix_default_language=True`.

 The issue lies in the relation between the `set_language()` view,
 LocaleMiddleware, and `i18n_patterns()` when
 `prefix_default_language=False`.

 If you disable `LocaleMiddleware` and set the the request language using
 `translation.override()` (to, e.g. `'el'` here) the test passes.

 The issue is in
 
[https://github.com/django/django/blob/8ba20d9071e9e1b8f2c81d4df977db4278342085/django/middleware/locale.py#L18-L26
 `LocaleMiddle.process_request()`]:


 {{{
     def process_request(self, request):
         urlconf = getattr(request, 'urlconf', settings.ROOT_URLCONF)
         i18n_patterns_used, prefixed_default_language =
 is_language_prefix_patterns_used(urlconf)
         language = translation.get_language_from_request(request,
 check_path=i18n_patterns_used)
         language_from_path =
 translation.get_language_from_path(request.path_info)
         if not language_from_path and i18n_patterns_used and not
 prefixed_default_language:
             language = settings.LANGUAGE_CODE
         translation.activate(language)
         request.LANGUAGE_CODE = translation.get_language()
 }}}

 Here, because the `set_language()` view is routed outside of
 `i18n_patterns()`, `not language_from_path and i18n_patterns_used and not
 prefixed_default_language` is `True` and so the language is **always** set
 to `settings.LANGUAGE_CODE`. This means that `translate_url()` never gets
 a match trying to resolve the url to translate (because the wrong language
 is activated).

 **IF** you route the `set_language()` view inside `i18n_patterns()` then
 the test passes **but you can't do that** because it's
 
[https://docs.djangoproject.com/en/2.2/topics/i18n/translation/#django.views.i18n.set_language
 explicitly warned against in the docs]:

 > **Warning**
 > Make sure that you don’t include the above URL within i18n_patterns() -
 it needs to be language-independent itself to work correctly.

 Two thoughts:

 * I'm not sure right now why that warning is required. (Could it be
 changed?)
 * `translate_url()` only functions on URLs coming from the currently
 active language. Would it be feasible to have `set_language()` redetermine
 the request language before calling `translate_url()`?
 * Is `LocaleMiddleware's `not language_from_path and i18n_patterns_used
 and not prefixed_default_language` correct? (I mean it seems it but...)

 Option 2 seems the most likely. None of them look that nice.

 Claude: I'd be grateful if you could check my reasoning here. 😬 Thanks.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/28567#comment:14>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/066.364ba7522ee2504f4303763132a6f3aa%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to