summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Charette <charette.s@gmail.com>2015-12-14 12:36:09 -0500
committerSimon Charette <charette.s@gmail.com>2016-03-03 12:08:49 -0500
commitd0451e4cadf4277f117b9b581530c68d8dc43c6a (patch)
tree53a7838ca76ce68fa7fa4f56eb1f71b4aa8796b0
parent2404d209a5e8c4573927e14587735562b79e13ed (diff)
downloaddjango-d0451e4cadf4277f117b9b581530c68d8dc43c6a.tar.gz
Fixed #26295 -- Allowed using i18n_patterns() in any root URLconf.
Thanks Tim for the review.
-rw-r--r--django/middleware/locale.py19
-rw-r--r--docs/releases/1.10.txt4
-rw-r--r--docs/topics/i18n/translation.txt10
-rw-r--r--tests/i18n/patterns/tests.py13
4 files changed, 34 insertions, 12 deletions
diff --git a/django/middleware/locale.py b/django/middleware/locale.py
index 063a4896bc..c9db673759 100644
--- a/django/middleware/locale.py
+++ b/django/middleware/locale.py
@@ -5,9 +5,8 @@ from django.http import HttpResponseRedirect
from django.urls import (
LocaleRegexURLResolver, get_resolver, get_script_prefix, is_valid_path,
)
-from django.utils import translation
+from django.utils import lru_cache, translation
from django.utils.cache import patch_vary_headers
-from django.utils.functional import cached_property
class LocaleMiddleware(object):
@@ -21,17 +20,19 @@ class LocaleMiddleware(object):
response_redirect_class = HttpResponseRedirect
def process_request(self, request):
+ urlconf = getattr(request, 'urlconf', settings.ROOT_URLCONF)
language = translation.get_language_from_request(
- request, check_path=self.is_language_prefix_patterns_used)
+ request, check_path=self.is_language_prefix_patterns_used(urlconf)
+ )
translation.activate(language)
request.LANGUAGE_CODE = translation.get_language()
def process_response(self, request, response):
language = translation.get_language()
language_from_path = translation.get_language_from_path(request.path_info)
+ urlconf = getattr(request, 'urlconf', settings.ROOT_URLCONF)
if (response.status_code == 404 and not language_from_path
- and self.is_language_prefix_patterns_used):
- urlconf = getattr(request, 'urlconf', None)
+ and self.is_language_prefix_patterns_used(urlconf)):
language_path = '/%s%s' % (language, request.path_info)
path_valid = is_valid_path(language_path, urlconf)
path_needs_slash = (
@@ -52,20 +53,20 @@ class LocaleMiddleware(object):
)
return self.response_redirect_class(language_url)
- if not (self.is_language_prefix_patterns_used
+ if not (self.is_language_prefix_patterns_used(urlconf)
and language_from_path):
patch_vary_headers(response, ('Accept-Language',))
if 'Content-Language' not in response:
response['Content-Language'] = language
return response
- @cached_property
- def is_language_prefix_patterns_used(self):
+ @lru_cache.lru_cache(maxsize=None)
+ def is_language_prefix_patterns_used(self, urlconf):
"""
Returns `True` if the `LocaleRegexURLResolver` is used
at root level of the urlpatterns, else it returns `False`.
"""
- for url_pattern in get_resolver(None).url_patterns:
+ for url_pattern in get_resolver(urlconf).url_patterns:
if isinstance(url_pattern, LocaleRegexURLResolver):
return True
return False
diff --git a/docs/releases/1.10.txt b/docs/releases/1.10.txt
index 436160e336..8622c34e89 100644
--- a/docs/releases/1.10.txt
+++ b/docs/releases/1.10.txt
@@ -244,7 +244,9 @@ Generic Views
Internationalization
~~~~~~~~~~~~~~~~~~~~
-* ...
+* The :func:`~django.conf.urls.i18n.i18n_patterns` helper function can now be
+ used in a root URLConf specified using :attr:`request.urlconf
+ <django.http.HttpRequest.urlconf>`.
Management Commands
~~~~~~~~~~~~~~~~~~~
diff --git a/docs/topics/i18n/translation.txt b/docs/topics/i18n/translation.txt
index 0ce746cbad..86778859e9 100644
--- a/docs/topics/i18n/translation.txt
+++ b/docs/topics/i18n/translation.txt
@@ -1328,7 +1328,7 @@ Language prefix in URL patterns
.. function:: i18n_patterns(*pattern_list)
-This function can be used in your root URLconf and Django will automatically
+This function can be used in a root URLconf and Django will automatically
prepend the current active language code to all url patterns defined within
:func:`~django.conf.urls.i18n.i18n_patterns`. Example URL patterns::
@@ -1373,10 +1373,16 @@ function. Example::
.. warning::
- :func:`~django.conf.urls.i18n.i18n_patterns` is only allowed in your root
+ :func:`~django.conf.urls.i18n.i18n_patterns` is only allowed in a root
URLconf. Using it within an included URLconf will throw an
:exc:`~django.core.exceptions.ImproperlyConfigured` exception.
+.. versionchanged:: 1.10
+
+ In older version, using ``i18n_patterns`` in a root URLconf different from
+ :setting:`ROOT_URLCONF` by setting :attr:`request.urlconf
+ <django.http.HttpRequest.urlconf>` wasn't supported.
+
.. warning::
Ensure that you don't have non-prefixed URL patterns that might collide
diff --git a/tests/i18n/patterns/tests.py b/tests/i18n/patterns/tests.py
index 83c7fd93e5..c533a57204 100644
--- a/tests/i18n/patterns/tests.py
+++ b/tests/i18n/patterns/tests.py
@@ -7,6 +7,7 @@ from django.http import HttpResponsePermanentRedirect
from django.middleware.locale import LocaleMiddleware
from django.template import Context, Template
from django.test import SimpleTestCase, override_settings
+from django.test.client import RequestFactory
from django.test.utils import override_script_prefix
from django.urls import clear_url_caches, reverse, translate_url
from django.utils import translation
@@ -92,6 +93,18 @@ class URLDisabledTests(URLTestCaseBase):
self.assertEqual(reverse('prefixed'), '/prefixed/')
+class RequestURLConfTests(SimpleTestCase):
+
+ @override_settings(ROOT_URLCONF='i18n.patterns.urls.path_unused')
+ def test_request_urlconf_considered(self):
+ request = RequestFactory().get('/nl/')
+ request.urlconf = 'i18n.patterns.urls.default'
+ middleware = LocaleMiddleware()
+ with translation.override('nl'):
+ middleware.process_request(request)
+ self.assertEqual(request.LANGUAGE_CODE, 'nl')
+
+
@override_settings(ROOT_URLCONF='i18n.patterns.urls.path_unused')
class PathUnusedTests(URLTestCaseBase):
"""