Commit 8c8f94fe authored by Łukasz Langa's avatar Łukasz Langa
Browse files

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

parent 99edbe0e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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>
+7 −7
Original line number Diff line number Diff line
@@ -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]
        if '-' not in lang_code:
            raise KeyError("Unknown language code %s." % lang_code)
        generic_lang_code = lang_code.split('-')[0]
        try:
                return LANG_INFO[splited_lang_code]
            return LANG_INFO[generic_lang_code]
        except KeyError:
                raise KeyError("Unknown language code %s and %s." % (lang_code, splited_lang_code))
        raise KeyError("Unknown language code %s." % lang_code)
            raise KeyError("Unknown language code %s and %s." % (lang_code, generic_lang_code))
+22 −6
Original line number Diff line number Diff line
@@ -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')
+9 −1
Original line number Diff line number Diff line
@@ -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):
    """
+2 −2
Original line number Diff line number Diff line
@@ -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):