Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixes #19919: get_language_from_request() disregards "en-us" and "en"…

… languages

when matching Accept-Language
  • Loading branch information...
commit 92ebb29c5376c1811e8607e96bddc90d24e44e2a 1 parent 90f1170
Łukasz Langa ambv authored
Showing with 54 additions and 13 deletions.
  1. +15 −12 django/utils/translation/trans_real.py
  2. +39 −1 tests/i18n/tests.py
27 django/utils/translation/trans_real.py
View
@@ -364,10 +364,14 @@ def get_supported_language_variant(lang_code, supported=None):
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
+ if lang_code:
+ # e.g. if fr-CA is not supported, try fr-ca;
+ # if that fails, fallback to fr.
+ variants = (lang_code, lang_code.lower(), lang_code.split('-')[0],
+ lang_code.lower().split('-')[0])
+ for code in variants:
+ if code in supported and check_for_language(code):
+ return code
raise LookupError(lang_code)
def get_language_from_path(path, supported=None):
@@ -438,14 +442,13 @@ def get_language_from_request(request, check_path=False):
# need to check again.
return _accepted[normalized]
- for lang, dirname in ((accept_lang, normalized),
- (accept_lang.split('-')[0], normalized.split('_')[0])):
- if lang.lower() not in supported:
- continue
- for path in all_locale_paths():
- if os.path.exists(os.path.join(path, dirname, 'LC_MESSAGES', 'django.mo')):
- _accepted[normalized] = lang
- return lang
+ try:
+ accept_lang = get_supported_language_variant(accept_lang, supported)
+ except LookupError:
+ continue
+ else:
+ _accepted[normalized] = accept_lang
+ return accept_lang
try:
return get_supported_language_variant(settings.LANGUAGE_CODE, supported)
40 tests/i18n/tests.py
View
@@ -30,7 +30,8 @@
ngettext, ngettext_lazy,
ungettext, ungettext_lazy,
pgettext, pgettext_lazy,
- npgettext, npgettext_lazy)
+ npgettext, npgettext_lazy,
+ check_for_language)
from .commands.tests import can_run_extraction_tests, can_run_compilation_tests
if can_run_extraction_tests:
@@ -1114,3 +1115,40 @@ def test_streaming_response(self):
self.assertContains(response, "Oui/Non")
response = self.client.get('/en/streaming/')
self.assertContains(response, "Yes/No")
+
+@override_settings(
+ USE_I18N=True,
+ LANGUAGES=(
+ ('bg', 'Bulgarian'),
+ ('en-us', 'English'),
+ ),
+ MIDDLEWARE_CLASSES=(
+ 'django.middleware.locale.LocaleMiddleware',
+ 'django.middleware.common.CommonMiddleware',
+ ),
+)
+class CountrySpecificLanguageTests(TestCase):
+
+ urls = 'i18n.urls'
+
+ def setUp(self):
+ trans_real._accepted = {}
+ self.rf = RequestFactory()
+
+ def test_check_for_language(self):
+ self.assertTrue(check_for_language('en'))
+ self.assertTrue(check_for_language('en-us'))
+ self.assertTrue(check_for_language('en-US'))
+
+
+ def test_get_language_from_request(self):
+ r = self.rf.get('/')
+ r.COOKIES = {}
+ r.META = {'HTTP_ACCEPT_LANGUAGE': 'en-US,en;q=0.8,bg;q=0.6,ru;q=0.4'}
+ lang = get_language_from_request(r)
+ self.assertEqual('en-us', lang)
+ r = self.rf.get('/')
+ r.COOKIES = {}
+ r.META = {'HTTP_ACCEPT_LANGUAGE': 'bg-bg,en-US;q=0.8,en;q=0.6,ru;q=0.4'}
+ lang = get_language_from_request(r)
+ self.assertEqual('bg', lang)

6 comments on commit 92ebb29

Leszek Piątek

On what Python did you tried your tests? On my setup I get 4 errors, with 9012833 i18n/tests.py I do not have those errors...

my python==2.7.3

Łukasz Langa

Both Python 2.7.3 and Python 3.3.1. No errors, nobody during the DjangoCon sprints complained after it's been integrated. Your comment will be more helpful with a traceback.

Łukasz Langa

By nobody I also mean our kindly Mr Jenkins: http://ci.djangoproject.com/job/Django/2659/

Leszek Piątek

http://pastebin.com/Nvkn1sK0

Maybe I'll try find You tommorow at sprint? :)

Łukasz Langa

The paths in your log suggest you are trying to run tests against a different copy of Django, installed in your virtualenv. Try the following:

  1. Create a new virtualenv without installing Django in it.
  2. Create a django.pth file in the virtualenv's site-packages with the path /home/lechup/github/django/ in it.
  3. Run tests again.

Also, do you know of a concept called pastebin? :neckbeard: GitHub has gist for instance.

Leszek Piątek

Thanks for pointers, actually /home/lechup/.virtualenvs/django-sprint/local/lib/python2.7/site-packages/django/ is a symlink to /home/lechup/github/django/django/ .

I'll try that .pth thing, but I think it is not the case.

PS: Pastebin? I though about it but to late (when I've already seen big letters)... Thanks for pointing this out. :+1:

Please sign in to comment.
Something went wrong with that request. Please try again.