From 539900f117dce5d9b51e2b9e8ff225c423060d52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Langa?= Date: Sat, 23 Feb 2013 19:41:33 +0100 Subject: [PATCH] Fixes #17866: Vary: Accept-Language header when language prefix used --- django/middleware/locale.py | 26 +++++++++++++------- django/utils/translation/__init__.py | 4 +-- django/utils/translation/trans_null.py | 2 +- tests/regressiontests/i18n/patterns/tests.py | 20 +++++++++++++++ tests/regressiontests/i18n/tests.py | 3 ++- 5 files changed, 42 insertions(+), 13 deletions(-) diff --git a/django/middleware/locale.py b/django/middleware/locale.py index f693e4d242a..be0e5494956 100644 --- a/django/middleware/locale.py +++ b/django/middleware/locale.py @@ -17,6 +17,14 @@ class LocaleMiddleware(object): 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): check_path = self.is_language_prefix_patterns_used() language = translation.get_language_from_request( @@ -26,9 +34,11 @@ class LocaleMiddleware(object): def process_response(self, request, response): language = translation.get_language() - if (response.status_code == 404 and - not translation.get_language_from_path(request.path_info) - and self.is_language_prefix_patterns_used()): + language_from_path = translation.get_language_from_path( + request.path_info, supported=self._supported_languages + ) + if (response.status_code == 404 and not language_from_path + and self.is_language_prefix_patterns_used()): urlconf = getattr(request, 'urlconf', None) language_path = '/%s%s' % (language, request.path_info) path_valid = is_valid_path(language_path, urlconf) @@ -42,8 +52,9 @@ class LocaleMiddleware(object): request.get_host(), language, request.get_full_path()) return HttpResponseRedirect(language_url) translation.deactivate() - - patch_vary_headers(response, ('Accept-Language',)) + if not (self.is_language_prefix_patterns_used() + and language_from_path): + patch_vary_headers(response, ('Accept-Language',)) if 'Content-Language' not in response: response['Content-Language'] = language return response @@ -53,7 +64,4 @@ class LocaleMiddleware(object): 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: - if isinstance(url_pattern, LocaleRegexURLResolver): - return True - return False + return self._is_language_prefix_patterns_used diff --git a/django/utils/translation/__init__.py b/django/utils/translation/__init__.py index 292e4db8692..ace87fab4b5 100644 --- a/django/utils/translation/__init__.py +++ b/django/utils/translation/__init__.py @@ -165,8 +165,8 @@ def to_locale(language): def get_language_from_request(request, check_path=False): return _trans.get_language_from_request(request, check_path) -def get_language_from_path(path): - return _trans.get_language_from_path(path) +def get_language_from_path(path, supported=None): + return _trans.get_language_from_path(path, supported=supported) def templatize(src, origin=None): return _trans.templatize(src, origin) diff --git a/django/utils/translation/trans_null.py b/django/utils/translation/trans_null.py index 5c514682048..7ef07793a42 100644 --- a/django/utils/translation/trans_null.py +++ b/django/utils/translation/trans_null.py @@ -58,6 +58,6 @@ def to_locale(language): def get_language_from_request(request, check_path=False): return settings.LANGUAGE_CODE -def get_language_from_path(request): +def get_language_from_path(request, supported=None): return None diff --git a/tests/regressiontests/i18n/patterns/tests.py b/tests/regressiontests/i18n/patterns/tests.py index 639e03f2887..0a785ab1d61 100644 --- a/tests/regressiontests/i18n/patterns/tests.py +++ b/tests/regressiontests/i18n/patterns/tests.py @@ -172,6 +172,26 @@ class URLRedirectTests(URLTestCaseBase): 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): """ Tests the redirect when the requested URL doesn't end with a slash diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py index ad184d8da3e..aaa9b12c3b5 100644 --- a/tests/regressiontests/i18n/tests.py +++ b/tests/regressiontests/i18n/tests.py @@ -48,7 +48,8 @@ from .models import Company, TestModel from .patterns.tests import (URLRedirectWithoutTrailingSlashTests, URLTranslationTests, URLDisabledTests, URLTagTests, URLTestCaseBase, URLRedirectWithoutTrailingSlashSettingTests, URLNamespaceTests, - URLPrefixTests, URLResponseTests, URLRedirectTests, PathUnusedTests) + URLPrefixTests, URLResponseTests, URLRedirectTests, PathUnusedTests, + URLVaryAcceptLanguageTests) here = os.path.dirname(os.path.abspath(upath(__file__)))