Skip to content

Commit

Permalink
Merge pull request #796 from ambv/vary
Browse files Browse the repository at this point in the history
Fixes #17866: Vary: Accept-Language header when language prefix used
  • Loading branch information
honzakral committed Feb 23, 2013
2 parents 9b97f01 + 539900f commit c2a0451
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 13 deletions.
26 changes: 17 additions & 9 deletions django/middleware/locale.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ class LocaleMiddleware(object):
is available, of course). is available, of course).
""" """


def __init__(self):
self._supported_languages = dict(settings.LANGUAGES)
self._is_language_prefix_patterns_used = False
for url_pattern in get_resolver(None).url_patterns:
if isinstance(url_pattern, LocaleRegexURLResolver):
self._is_language_prefix_patterns_used = True
break

def process_request(self, request): def process_request(self, request):
check_path = self.is_language_prefix_patterns_used() check_path = self.is_language_prefix_patterns_used()
language = translation.get_language_from_request( language = translation.get_language_from_request(
Expand All @@ -26,9 +34,11 @@ def process_request(self, request):


def process_response(self, request, response): def process_response(self, request, response):
language = translation.get_language() language = translation.get_language()
if (response.status_code == 404 and language_from_path = translation.get_language_from_path(
not translation.get_language_from_path(request.path_info) request.path_info, supported=self._supported_languages
and self.is_language_prefix_patterns_used()): )
if (response.status_code == 404 and not language_from_path
and self.is_language_prefix_patterns_used()):
urlconf = getattr(request, 'urlconf', None) urlconf = getattr(request, 'urlconf', None)
language_path = '/%s%s' % (language, request.path_info) language_path = '/%s%s' % (language, request.path_info)
path_valid = is_valid_path(language_path, urlconf) path_valid = is_valid_path(language_path, urlconf)
Expand All @@ -42,8 +52,9 @@ def process_response(self, request, response):
request.get_host(), language, request.get_full_path()) request.get_host(), language, request.get_full_path())
return HttpResponseRedirect(language_url) return HttpResponseRedirect(language_url)
translation.deactivate() translation.deactivate()

if not (self.is_language_prefix_patterns_used()
patch_vary_headers(response, ('Accept-Language',)) and language_from_path):
patch_vary_headers(response, ('Accept-Language',))
if 'Content-Language' not in response: if 'Content-Language' not in response:
response['Content-Language'] = language response['Content-Language'] = language
return response return response
Expand All @@ -53,7 +64,4 @@ def is_language_prefix_patterns_used(self):
Returns `True` if the `LocaleRegexURLResolver` is used Returns `True` if the `LocaleRegexURLResolver` is used
at root level of the urlpatterns, else it returns `False`. at root level of the urlpatterns, else it returns `False`.
""" """
for url_pattern in get_resolver(None).url_patterns: return self._is_language_prefix_patterns_used
if isinstance(url_pattern, LocaleRegexURLResolver):
return True
return False
4 changes: 2 additions & 2 deletions django/utils/translation/__init__.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ def to_locale(language):
def get_language_from_request(request, check_path=False): def get_language_from_request(request, check_path=False):
return _trans.get_language_from_request(request, check_path) return _trans.get_language_from_request(request, check_path)


def get_language_from_path(path): def get_language_from_path(path, supported=None):
return _trans.get_language_from_path(path) return _trans.get_language_from_path(path, supported=supported)


def templatize(src, origin=None): def templatize(src, origin=None):
return _trans.templatize(src, origin) return _trans.templatize(src, origin)
Expand Down
2 changes: 1 addition & 1 deletion django/utils/translation/trans_null.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -58,6 +58,6 @@ def to_locale(language):
def get_language_from_request(request, check_path=False): def get_language_from_request(request, check_path=False):
return settings.LANGUAGE_CODE return settings.LANGUAGE_CODE


def get_language_from_path(request): def get_language_from_path(request, supported=None):
return None return None


20 changes: 20 additions & 0 deletions tests/regressiontests/i18n/patterns/tests.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -172,6 +172,26 @@ def test_pt_br_redirect(self):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)




class URLVaryAcceptLanguageTests(URLTestCaseBase):
"""
Tests that 'Accept-Language' is not added to the Vary header when using
prefixed URLs.
"""
def test_no_prefix_response(self):
response = self.client.get('/not-prefixed/')
self.assertEqual(response.status_code, 200)
self.assertEqual(response.get('Vary'), 'Accept-Language')

def test_en_redirect(self):
response = self.client.get('/account/register/', HTTP_ACCEPT_LANGUAGE='en')
self.assertRedirects(response, '/en/account/register/')
self.assertFalse(response.get('Vary'))

response = self.client.get(response['location'])
self.assertEqual(response.status_code, 200)
self.assertFalse(response.get('Vary'))


class URLRedirectWithoutTrailingSlashTests(URLTestCaseBase): class URLRedirectWithoutTrailingSlashTests(URLTestCaseBase):
""" """
Tests the redirect when the requested URL doesn't end with a slash Tests the redirect when the requested URL doesn't end with a slash
Expand Down
3 changes: 2 additions & 1 deletion tests/regressiontests/i18n/tests.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@
from .patterns.tests import (URLRedirectWithoutTrailingSlashTests, from .patterns.tests import (URLRedirectWithoutTrailingSlashTests,
URLTranslationTests, URLDisabledTests, URLTagTests, URLTestCaseBase, URLTranslationTests, URLDisabledTests, URLTagTests, URLTestCaseBase,
URLRedirectWithoutTrailingSlashSettingTests, URLNamespaceTests, URLRedirectWithoutTrailingSlashSettingTests, URLNamespaceTests,
URLPrefixTests, URLResponseTests, URLRedirectTests, PathUnusedTests) URLPrefixTests, URLResponseTests, URLRedirectTests, PathUnusedTests,
URLVaryAcceptLanguageTests)




here = os.path.dirname(os.path.abspath(upath(__file__))) here = os.path.dirname(os.path.abspath(upath(__file__)))
Expand Down

0 comments on commit c2a0451

Please sign in to comment.