Permalink
Browse files

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

… languages

when matching Accept-Language
  • Loading branch information...
1 parent 90f1170 commit 92ebb29c5376c1811e8607e96bddc90d24e44e2a @ambv ambv committed May 18, 2013
Showing with 54 additions and 13 deletions.
  1. +15 −12 django/utils/translation/trans_real.py
  2. +39 −1 tests/i18n/tests.py
@@ -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)
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

@lechup
lechup commented on 92ebb29 May 18, 2013

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

@ambv
ambv commented on 92ebb29 May 18, 2013

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.

@ambv
ambv commented on 92ebb29 May 18, 2013

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

@lechup
lechup commented on 92ebb29 May 18, 2013

http://pastebin.com/Nvkn1sK0

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

@ambv
ambv commented on 92ebb29 May 18, 2013

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.

@lechup
lechup commented on 92ebb29 May 18, 2013

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. 👍

Please sign in to comment.