From 901a1691982cab76349d33e51b72c40120ec927a Mon Sep 17 00:00:00 2001 From: Zainab Amir Date: Thu, 16 Jun 2022 00:11:36 +0500 Subject: [PATCH] Fixed #23689 -- Made parsing HTTP Accept-Language header case-insensitive. Thank you Daniel Samuels for test project. --- django/utils/translation/trans_null.py | 2 +- django/utils/translation/trans_real.py | 5 +++-- tests/i18n/tests.py | 8 ++++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/django/utils/translation/trans_null.py b/django/utils/translation/trans_null.py index a687572b69..c8bfb1256e 100644 --- a/django/utils/translation/trans_null.py +++ b/django/utils/translation/trans_null.py @@ -61,7 +61,7 @@ def get_language_from_path(request): def get_supported_language_variant(lang_code, strict=False): - if lang_code == settings.LANGUAGE_CODE: + if lang_code and lang_code.lower() == settings.LANGUAGE_CODE.lower(): return lang_code else: raise LookupError(lang_code) diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py index 7c81e8bee2..423f30eaba 100644 --- a/django/utils/translation/trans_real.py +++ b/django/utils/translation/trans_real.py @@ -478,8 +478,9 @@ def check_for_language(lang_code): def get_languages(): """ Cache of settings.LANGUAGES in a dictionary for easy lookups by key. + Convert keys to lowercase as they should be treated as case-insensitive. """ - return dict(settings.LANGUAGES) + return {key.lower(): value for key, value in dict(settings.LANGUAGES).items()} @functools.lru_cache(maxsize=1000) @@ -510,7 +511,7 @@ def get_supported_language_variant(lang_code, strict=False): supported_lang_codes = get_languages() for code in possible_lang_codes: - if code in supported_lang_codes and check_for_language(code): + if code.lower() in supported_lang_codes and check_for_language(code): return code if not strict: # if fr-fr is not supported, try fr-ca. diff --git a/tests/i18n/tests.py b/tests/i18n/tests.py index d79cdcd34d..2c9096179c 100644 --- a/tests/i18n/tests.py +++ b/tests/i18n/tests.py @@ -1902,9 +1902,10 @@ class MiscTests(SimpleTestCase): USE_I18N=True, LANGUAGES=[ ("en", "English"), + ("ar-dz", "Algerian Arabic"), ("de", "German"), ("de-at", "Austrian German"), - ("pt-br", "Portuguese (Brazil)"), + ("pt-BR", "Portuguese (Brazil)"), ], ) def test_get_supported_language_variant_real(self): @@ -1915,8 +1916,11 @@ class MiscTests(SimpleTestCase): self.assertEqual(g("de-at"), "de-at") self.assertEqual(g("de-ch"), "de") self.assertEqual(g("pt-br"), "pt-br") + self.assertEqual(g("pt-BR"), "pt-BR") self.assertEqual(g("pt"), "pt-br") self.assertEqual(g("pt-pt"), "pt-br") + self.assertEqual(g("ar-dz"), "ar-dz") + self.assertEqual(g("ar-DZ"), "ar-DZ") with self.assertRaises(LookupError): g("pt", strict=True) with self.assertRaises(LookupError): @@ -1946,7 +1950,6 @@ class MiscTests(SimpleTestCase): LANGUAGES=[ ("en", "English"), ("en-latn-us", "Latin English"), - ("en-Latn-US", "BCP 47 case format"), ("de", "German"), ("de-1996", "German, orthography of 1996"), ("de-at", "Austrian German"), @@ -1970,6 +1973,7 @@ class MiscTests(SimpleTestCase): ("/de/", "de"), ("/de-1996/", "de-1996"), ("/de-at/", "de-at"), + ("/de-AT/", "de-AT"), ("/de-ch/", "de"), ("/de-ch-1901/", "de-ch-1901"), ("/de-simple-page-test/", None),