mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	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
This commit is contained in:
		| @@ -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')), | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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' | ||||
| """ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user