From 0a3c8f03e064e3c0502e9df64ad06764204c4b4a Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Wed, 6 Feb 2008 01:04:30 +0000 Subject: [PATCH] Fixed #6409 -- Unbreak compound locale name parsing (e.g. zh-cn). This was inadvertently broken back in [6608]. Slightly backwards-incompatible: people specifying "es_AR" in their LANGUAGES list will need to change that to "es-ar". Thanks, simonb and Ramiro Morales for making the effort to fix this. git-svn-id: http://code.djangoproject.com/svn/django/trunk@7091 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/conf/global_settings.py | 2 +- django/utils/translation/trans_real.py | 21 +++++++----- tests/regressiontests/i18n/misc.py | 45 ++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 9 deletions(-) diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py index 187eb0645e..d722fecd23 100644 --- a/django/conf/global_settings.py +++ b/django/conf/global_settings.py @@ -47,7 +47,7 @@ LANGUAGES = ( ('el', gettext_noop('Greek')), ('en', gettext_noop('English')), ('es', gettext_noop('Spanish')), - ('es_AR', gettext_noop('Argentinean Spanish')), + ('es-ar', gettext_noop('Argentinean Spanish')), ('fa', gettext_noop('Persian')), ('fi', gettext_noop('Finnish')), ('fr', gettext_noop('French')), diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py index a7259b3ce5..f8a39710b4 100644 --- a/django/utils/translation/trans_real.py +++ b/django/utils/translation/trans_real.py @@ -42,7 +42,10 @@ accept_language_re = re.compile(r''' ''', re.VERBOSE) def to_locale(language, to_lower=False): - "Turns a language name (en-us) into a locale name (en_US)." + """ + Turns a language name (en-us) into a locale name (en_US). If 'to_lower' is + True, the last component is lower-cased (en_us). + """ p = language.find('-') if p >= 0: if to_lower: @@ -357,19 +360,20 @@ def get_language_from_request(request): return lang_code accept = request.META.get('HTTP_ACCEPT_LANGUAGE', '') - for lang, unused in parse_accept_lang_header(accept): - if lang == '*': + for accept_lang, unused in parse_accept_lang_header(accept): + if accept_lang == '*': break # We have a very restricted form for our language files (no encoding # specifier, since they all must be UTF-8 and only one possible # language each time. So we avoid the overhead of gettext.find() and - # look up the MO file manually. + # work out the MO file manually. - normalized = locale.locale_alias.get(to_locale(lang, True)) + # 'normalized' is the root name of the locale in POSIX format (which is + # the format used for the directories holding the MO files). + normalized = locale.locale_alias.get(to_locale(accept_lang, True)) if not normalized: continue - # Remove the default encoding from locale_alias normalized = normalized.split('.')[0] @@ -378,10 +382,11 @@ def get_language_from_request(request): # need to check again. return _accepted[normalized] - for lang in (normalized, normalized.split('_')[0]): + for lang, dirname in ((accept_lang, normalized), + (accept_lang.split('-')[0], normalized.split('_')[0])): if lang not in supported: continue - langfile = os.path.join(globalpath, lang, 'LC_MESSAGES', + langfile = os.path.join(globalpath, dirname, 'LC_MESSAGES', 'django.mo') if os.path.exists(langfile): _accepted[normalized] = lang diff --git a/tests/regressiontests/i18n/misc.py b/tests/regressiontests/i18n/misc.py index fa22fd05d3..eb64263799 100644 --- a/tests/regressiontests/i18n/misc.py +++ b/tests/regressiontests/i18n/misc.py @@ -2,6 +2,11 @@ tests = """ >>> from django.utils.translation.trans_real import parse_accept_lang_header >>> p = parse_accept_lang_header +# +# Testing HTTP header parsing. First, we test that we can parse the values +# according to the spec (and that we extract all the pieces in the right order). +# + Good headers. >>> p('de') [('de', 1.0)] @@ -54,4 +59,44 @@ Bad headers; should always return []. >>> p('') [] +# +# Now test that we parse a literal HTTP header correctly. +# + +>>> from django.utils.translation.trans_real import get_language_from_request +>>> g = get_language_from_request +>>> from django.http import HttpRequest +>>> r = HttpRequest +>>> r.COOKIES = {} + +These tests assumes the es, es_AR, pt and pt_BR translations exit in the Django +source tree. +>>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'pt-br'} +>>> g(r) +'pt-br' +>>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'pt'} +>>> g(r) +'pt' +>>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'es,de'} +>>> g(r) +'es' +>>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'es-ar,de'} +>>> g(r) +'es-ar' + +This test assumes there won't be a Django translation to a US variation +of the Spanish language, a safe assumption. When the user sets it +as the preferred language, the main 'es' translation should be selected +instead. +>>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'es-us'} +>>> g(r) +'es' + +This tests the following scenario: there isn't a main language (zh) +translation of Django but there is a translation to variation (zh_CN) +the user sets zh-cn as the preferred language, it should be selected by +Django without falling back nor ignoring it. +>>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'zh-cn,de'} +>>> g(r) +'zh-cn' """