Fixes #19763 - LocaleMiddleware should check for supported languages in settings.LANGUAGE_CODE

This commit is contained in:
Łukasz Langa 2013-02-24 14:43:45 +01:00
parent 99edbe0e27
commit 8c8f94fe9d
5 changed files with 41 additions and 16 deletions

View File

@ -328,6 +328,7 @@ answer newbie questions, and generally made Django that much better:
Denis Kuzmichyov <kuzmichyov@gmail.com>
Panos Laganakos <panos.laganakos@gmail.com>
Nick Lane <nick.lane.au@gmail.com>
Łukasz Langa <lukasz@langa.pl>
Stuart Langridge <http://www.kryogenix.org/>
Paul Lanier <planier@google.com>
David Larlet <http://david.larlet.fr>

View File

@ -187,10 +187,10 @@ def get_language_info(lang_code):
try:
return LANG_INFO[lang_code]
except KeyError:
if '-' in lang_code:
splited_lang_code = lang_code.split('-')[0]
try:
return LANG_INFO[splited_lang_code]
except KeyError:
raise KeyError("Unknown language code %s and %s." % (lang_code, splited_lang_code))
if '-' not in lang_code:
raise KeyError("Unknown language code %s." % lang_code)
generic_lang_code = lang_code.split('-')[0]
try:
return LANG_INFO[generic_lang_code]
except KeyError:
raise KeyError("Unknown language code %s and %s." % (lang_code, generic_lang_code))

View File

@ -356,6 +356,20 @@ def check_for_language(lang_code):
return True
return False
def get_supported_language_variant(lang_code, supported=None):
"""
Returns the language-code that's listed in supported languages, possibly
selecting a more generic variant. Raises LookupError if nothing found.
"""
if supported is None:
from django.conf import settings
supported = dict(settings.LANGUAGES)
if lang_code and lang_code not in supported:
lang_code = lang_code.split('-')[0] # e.g. if fr-ca is not supported fallback to fr
if lang_code and lang_code in supported and check_for_language(lang_code):
return lang_code
raise LookupError(lang_code)
def get_language_from_path(path, supported=None):
"""
Returns the language-code if there is a valid language-code
@ -396,11 +410,10 @@ def get_language_from_request(request, check_path=False):
lang_code = request.COOKIES.get(settings.LANGUAGE_COOKIE_NAME)
if lang_code and lang_code not in supported:
lang_code = lang_code.split('-')[0] # e.g. if fr-ca is not supported fallback to fr
if lang_code and lang_code in supported and check_for_language(lang_code):
return lang_code
try:
return get_supported_language_variant(lang_code, supported)
except LookupError:
pass
accept = request.META.get('HTTP_ACCEPT_LANGUAGE', '')
for accept_lang, unused in parse_accept_lang_header(accept):
@ -434,6 +447,9 @@ def get_language_from_request(request, check_path=False):
_accepted[normalized] = lang
return lang
try:
return get_supported_language_variant(settings.LANGUAGE_CODE, supported)
except LookupError:
return settings.LANGUAGE_CODE
dot_re = re.compile(r'\S')

View File

@ -19,7 +19,7 @@ from django.utils import translation
TEMPLATE_DIRS=(
os.path.join(os.path.dirname(upath(__file__)), 'templates'),
),
LANGUAGE_CODE='en',
LANGUAGE_CODE='en-us',
LANGUAGES=(
('nl', 'Dutch'),
('en', 'English'),
@ -171,6 +171,14 @@ class URLRedirectTests(URLTestCaseBase):
response = self.client.get(response['location'])
self.assertEqual(response.status_code, 200)
def test_pl_pl_redirect(self):
# language from outside of the supported LANGUAGES list
response = self.client.get('/account/register/', HTTP_ACCEPT_LANGUAGE='pl-pl')
self.assertRedirects(response, '/en/account/register/')
response = self.client.get(response['location'])
self.assertEqual(response.status_code, 200)
class URLVaryAcceptLanguageTests(URLTestCaseBase):
"""

View File

@ -958,7 +958,7 @@ class TestLanguageInfo(TestCase):
self.assertEqual(li['bidi'], False)
def test_unknown_language_code(self):
six.assertRaisesRegex(self, KeyError, "Unknown language code '?xx'?.", get_language_info, 'xx-xx')
six.assertRaisesRegex(self, KeyError, r"Unknown language code xx\.", get_language_info, 'xx')
def test_unknown_only_country_code(self):
li = get_language_info('de-xx')
@ -968,7 +968,7 @@ class TestLanguageInfo(TestCase):
self.assertEqual(li['bidi'], False)
def test_unknown_language_code_and_country_code(self):
six.assertRaisesRegex(self, KeyError, "Unknown language code '?xx-xx'? and '?xx'?.", get_language_info, 'xx-xx')
six.assertRaisesRegex(self, KeyError, r"Unknown language code xx-xx and xx\.", get_language_info, 'xx-xx')
class MultipleLocaleActivationTests(TestCase):