diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py index a7a89f9bd5..8a2527022d 100644 --- a/django/utils/translation/trans_real.py +++ b/django/utils/translation/trans_real.py @@ -43,9 +43,12 @@ accept_language_re = re.compile(r''' (?:\s*,\s*|$) # Multiple accepts per header. ''', re.VERBOSE) -language_code_re = re.compile(r'^[a-z]{1,8}(?:-[a-z0-9]{1,8})*$', re.IGNORECASE) +language_code_re = re.compile( + r'^[a-z]{1,8}(?:-[a-z0-9]{1,8})*(?:@[a-z0-9]{1,20})?$', + re.IGNORECASE +) -language_code_prefix_re = re.compile(r'^/([\w-]+)(/|$)') +language_code_prefix_re = re.compile(r'^/([\w@-]+)(/|$)') @receiver(setting_changed) diff --git a/docs/releases/1.9.txt b/docs/releases/1.9.txt index 3c2a35b149..831edc5d10 100644 --- a/docs/releases/1.9.txt +++ b/docs/releases/1.9.txt @@ -162,6 +162,10 @@ Internationalization * The :func:`django.utils.timezone.make_aware` function gained an ``is_dst`` argument to help resolve ambiguous times during DST transitions. +* You can now use locale variants supported by gettext. These are usually used + for languages which can be written in different scripts, for example Latin + and Cyrillic (e.g. ``be@latin``). + Management Commands ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/i18n/tests.py b/tests/i18n/tests.py index 69f6dbbe2e..d3daf6e183 100644 --- a/tests/i18n/tests.py +++ b/tests/i18n/tests.py @@ -1420,9 +1420,18 @@ class CountrySpecificLanguageTests(TestCase): self.assertTrue(check_for_language('en')) self.assertTrue(check_for_language('en-us')) self.assertTrue(check_for_language('en-US')) + self.assertTrue(check_for_language('be')) + self.assertTrue(check_for_language('be@latin')) + self.assertTrue(check_for_language('sr-RS@latin')) + self.assertTrue(check_for_language('sr-RS@12345')) self.assertFalse(check_for_language('en-ΓΌ')) self.assertFalse(check_for_language('en\x00')) self.assertFalse(check_for_language(None)) + self.assertFalse(check_for_language('be@ ')) + # Specifying encoding is not supported (Django enforces UTF-8) + self.assertFalse(check_for_language('tr-TR.UTF-8')) + self.assertFalse(check_for_language('tr-TR.UTF8')) + self.assertFalse(check_for_language('de-DE.utf-8')) def test_get_language_from_request(self): # issue 19919