mirror of https://github.com/django/django.git
Fixed #24122 -- Redirected to translated url after setting language
Thanks gbdlin for the initial patch and Tim Graham for the review.
This commit is contained in:
parent
a8991b9b9f
commit
aa5ab114e3
|
@ -24,7 +24,8 @@ from django.utils.functional import cached_property, lazy
|
|||
from django.utils.http import RFC3986_SUBDELIMS, urlquote
|
||||
from django.utils.module_loading import module_has_submodule
|
||||
from django.utils.regex_helper import normalize
|
||||
from django.utils.translation import get_language
|
||||
from django.utils.six.moves.urllib.parse import urlsplit, urlunsplit
|
||||
from django.utils.translation import get_language, override
|
||||
|
||||
# SCRIPT_NAME prefixes for each thread are stored here. If there's no entry for
|
||||
# the current thread (which is the only one we ever access), it is assumed to
|
||||
|
@ -652,3 +653,26 @@ def is_valid_path(path, urlconf=None):
|
|||
return True
|
||||
except Resolver404:
|
||||
return False
|
||||
|
||||
|
||||
def translate_url(url, lang_code):
|
||||
"""
|
||||
Given a URL (absolute or relative), try to get its translated version in
|
||||
the `lang_code` language (either by i18n_patterns or by translated regex).
|
||||
Return the original URL if no translated version is found.
|
||||
"""
|
||||
parsed = urlsplit(url)
|
||||
try:
|
||||
match = resolve(parsed.path)
|
||||
except Resolver404:
|
||||
pass
|
||||
else:
|
||||
to_be_reversed = "%s:%s" % (match.namespace, match.url_name) if match.namespace else match.url_name
|
||||
with override(lang_code):
|
||||
try:
|
||||
url = reverse(to_be_reversed, args=match.args, kwargs=match.kwargs)
|
||||
except NoReverseMatch:
|
||||
pass
|
||||
else:
|
||||
url = urlunsplit((parsed.scheme, parsed.netloc, url, parsed.query, parsed.fragment))
|
||||
return url
|
||||
|
|
|
@ -6,6 +6,7 @@ import os
|
|||
from django import http
|
||||
from django.apps import apps
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import translate_url
|
||||
from django.template import Context, Engine
|
||||
from django.utils import six
|
||||
from django.utils._os import upath
|
||||
|
@ -37,6 +38,9 @@ def set_language(request):
|
|||
if request.method == 'POST':
|
||||
lang_code = request.POST.get('language', None)
|
||||
if lang_code and check_for_language(lang_code):
|
||||
next_trans = translate_url(next, lang_code)
|
||||
if next_trans != next:
|
||||
response = http.HttpResponseRedirect(next_trans)
|
||||
if hasattr(request, 'session'):
|
||||
request.session[LANGUAGE_SESSION_KEY] = lang_code
|
||||
else:
|
||||
|
|
|
@ -127,7 +127,8 @@ Generic Views
|
|||
Internationalization
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
* ...
|
||||
* The :func:`django.views.i18n.set_language` view now properly redirects to
|
||||
:ref:`translated URLs <url-internationalization>`, when available.
|
||||
|
||||
Management Commands
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -4,7 +4,7 @@ import os
|
|||
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.core.urlresolvers import (
|
||||
clear_url_caches, reverse, set_script_prefix,
|
||||
clear_url_caches, reverse, set_script_prefix, translate_url,
|
||||
)
|
||||
from django.http import HttpResponsePermanentRedirect
|
||||
from django.middleware.locale import LocaleMiddleware
|
||||
|
@ -135,6 +135,18 @@ class URLTranslationTests(URLTestCaseBase):
|
|||
with translation.override('pt-br'):
|
||||
self.assertEqual(reverse('users'), '/pt-br/usuarios/')
|
||||
|
||||
def test_translate_url_utility(self):
|
||||
with translation.override('en'):
|
||||
self.assertEqual(translate_url('/en/non-existent/', 'nl'), '/en/non-existent/')
|
||||
self.assertEqual(translate_url('/en/users/', 'nl'), '/nl/gebruikers/')
|
||||
# Namespaced URL
|
||||
self.assertEqual(translate_url('/en/account/register/', 'nl'), '/nl/profiel/registeren/')
|
||||
self.assertEqual(translation.get_language(), 'en')
|
||||
|
||||
with translation.override('nl'):
|
||||
self.assertEqual(translate_url('/nl/gebruikers/', 'en'), '/en/users/')
|
||||
self.assertEqual(translation.get_language(), 'nl')
|
||||
|
||||
|
||||
class URLNamespaceTests(URLTestCaseBase):
|
||||
"""
|
||||
|
|
Binary file not shown.
|
@ -16,6 +16,10 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: urls.py:78
|
||||
msgid "^translated/$"
|
||||
msgstr "^vertaald/$"
|
||||
|
||||
#: views/csrf.py:98
|
||||
msgid "Forbidden"
|
||||
msgstr "Verboden"
|
||||
|
|
|
@ -67,6 +67,23 @@ class I18NTests(TestCase):
|
|||
self.assertEqual(language_cookie['path'], '/test/')
|
||||
self.assertEqual(language_cookie['max-age'], 3600 * 7 * 2)
|
||||
|
||||
@modify_settings(MIDDLEWARE_CLASSES={
|
||||
'append': 'django.middleware.locale.LocaleMiddleware',
|
||||
})
|
||||
def test_lang_from_translated_i18n_pattern(self):
|
||||
response = self.client.post(
|
||||
'/i18n/setlang/', data={'language': 'nl'},
|
||||
follow=True, HTTP_REFERER='/en/translated/'
|
||||
)
|
||||
self.assertEqual(self.client.session[LANGUAGE_SESSION_KEY], 'nl')
|
||||
self.assertRedirects(response, 'http://testserver/nl/vertaald/')
|
||||
# And reverse
|
||||
response = self.client.post(
|
||||
'/i18n/setlang/', data={'language': 'en'},
|
||||
follow=True, HTTP_REFERER='/nl/vertaald/'
|
||||
)
|
||||
self.assertRedirects(response, 'http://testserver/en/translated/')
|
||||
|
||||
def test_jsi18n(self):
|
||||
"""The javascript_catalog can be deployed with language settings"""
|
||||
for lang_code in ['es', 'fr', 'ru']:
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
from os import path
|
||||
|
||||
from django.conf.urls import include, url
|
||||
from django.conf.urls.i18n import i18n_patterns
|
||||
from django.utils._os import upath
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views import defaults, i18n, static
|
||||
|
||||
from . import views
|
||||
|
@ -73,6 +75,10 @@ urlpatterns = [
|
|||
url(r'^site_media/(?P<path>.*)$', static.serve, {'document_root': media_dir}),
|
||||
]
|
||||
|
||||
urlpatterns += i18n_patterns(
|
||||
url(_(r'^translated/$'), views.index_page, name='i18n_prefixed'),
|
||||
)
|
||||
|
||||
urlpatterns += [
|
||||
url(r'view_exception/(?P<n>[0-9]+)/$', views.view_exception, name='view_exception'),
|
||||
url(r'template_exception/(?P<n>[0-9]+)/$', views.template_exception, name='template_exception'),
|
||||
|
|
Loading…
Reference in New Issue