diff --git a/django/core/checks/translation.py b/django/core/checks/translation.py index 138ed07ff8..8457a6b89d 100644 --- a/django/core/checks/translation.py +++ b/django/core/checks/translation.py @@ -1,4 +1,5 @@ from django.conf import settings +from django.utils.translation import get_supported_language_variant from django.utils.translation.trans_real import language_code_re from . import Error, Tags, register @@ -55,7 +56,9 @@ def check_setting_languages_bidi(app_configs, **kwargs): @register(Tags.translation) def check_language_settings_consistent(app_configs, **kwargs): """Error if language settings are not consistent with each other.""" - available_tags = {i for i, _ in settings.LANGUAGES} | {'en-us'} - if settings.LANGUAGE_CODE not in available_tags: + try: + get_supported_language_variant(settings.LANGUAGE_CODE) + except LookupError: return [E004] - return [] + else: + return [] diff --git a/docs/releases/3.0.3.txt b/docs/releases/3.0.3.txt index 61ef456d93..27ace475d1 100644 --- a/docs/releases/3.0.3.txt +++ b/docs/releases/3.0.3.txt @@ -16,3 +16,7 @@ Bugfixes * Fixed a regression in Django 3.0 where ``QuerySet.values()`` and ``values_list()`` crashed if a queryset contained an aggregation and ``Exists()`` annotation (:ticket:`31136`). + +* Relaxed the system check added in Django 3.0 to reallow use of a sublanguage + in the :setting:`LANGUAGE_CODE` setting, when a base language is available in + Django but the sublanguage is not (:ticket:`31141`). diff --git a/tests/check_framework/test_translation.py b/tests/check_framework/test_translation.py index 4cd79d803f..8747a52cda 100644 --- a/tests/check_framework/test_translation.py +++ b/tests/check_framework/test_translation.py @@ -3,7 +3,7 @@ from django.core.checks.translation import ( check_language_settings_consistent, check_setting_language_code, check_setting_languages, check_setting_languages_bidi, ) -from django.test import SimpleTestCase +from django.test import SimpleTestCase, override_settings class TranslationCheckTests(SimpleTestCase): @@ -75,12 +75,36 @@ class TranslationCheckTests(SimpleTestCase): Error(msg % tag, id='translation.E003'), ]) + @override_settings(USE_I18N=True, LANGUAGES=[('en', 'English')]) def test_inconsistent_language_settings(self): msg = ( 'You have provided a value for the LANGUAGE_CODE setting that is ' 'not in the LANGUAGES setting.' ) - with self.settings(LANGUAGE_CODE='fr', LANGUAGES=[('en', 'English')]): - self.assertEqual(check_language_settings_consistent(None), [ - Error(msg, id='translation.E004'), - ]) + for tag in ['fr', 'fr-CA', 'fr-357']: + with self.subTest(tag), self.settings(LANGUAGE_CODE=tag): + self.assertEqual(check_language_settings_consistent(None), [ + Error(msg, id='translation.E004'), + ]) + + @override_settings( + USE_I18N=True, + LANGUAGES=[ + ('de', 'German'), + ('es', 'Spanish'), + ('fr', 'French'), + ('ca', 'Catalan'), + ], + ) + def test_valid_variant_consistent_language_settings(self): + tests = [ + # language + region. + 'fr-CA', + 'es-419', + 'de-at', + # language + region + variant. + 'ca-ES-valencia', + ] + for tag in tests: + with self.subTest(tag), self.settings(LANGUAGE_CODE=tag): + self.assertEqual(check_language_settings_consistent(None), [])