#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 django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
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