i18n failed in Chinese locale
发现 Django i18n 的一个中文支持的 bug
如果你的浏览器的 locale 只设置了 zh-cn 的话识别中文应该是没问题的,但是如果有多个 locale,僻如我一次设置了 zh-cn, en-us, de-de,那么中文就不可能被识别出来了。
要了解这个问题,我们先看下这段代码,在 trans_real.py 里面。
主要看一个名为 get_language_from_request 的函数。
从里面打开可以看到程序的基本流程。
- 检测 session 中有没有设置过 django_language,如果支持这个语言,那么就返回语言代码
- 检测 cookies 里面有没有 django_language,如果支持这个语言,那么就返回语言代码
- 最后就是要从 HTTP 头中的 ACCEPT-LANGUAGE 中分析语言。就是在这一步的时候,对中文的支持就存在 bug 了。
- 如果都无法识别,那么从返回默认的 settings.LANGUAGE_CODE
为什么会出现多个 locale 无法识别中文的情况呢?我们来看下面的关于分析 ACCEPT_LANGUAGE 的代码:
for lang, unused in parse_accept_lang_header(accept): if 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. normalized = locale.locale_alias.get(to_locale(lang, True)) # 这一步会将浏览器的 locale 字符串标准化,僻如 zh-cn -> zh_CN.gb2312 if not normalized: continue # Remove the default encoding from locale_alias normalized = normalized.split('.')[0] # 这里就把上面的的 zh_CN.gb2312 变成 zh_CN if normalized in _accepted: # We've seen this locale before and have an MO file for it, so no # need to check again. return _accepted[normalized] for lang in (normalized, normalized.split('_')[0]): # 这一步让 lang 成为 (zh_CN, zh),进而匹配 supported 这个支持的语言集合。 # 这是出错的关键,因为无论 zh 还是 zh_CN 都是无法匹配到的。 # 在 supported 里面只支持 zh-cn 和 zh-tw,对于 zh 和 zh_CN 是无法匹配的。 if lang not in supported: continue langfile = os.path.join(globalpath, lang, 'LC_MESSAGES', 'django.mo') if os.path.exists(langfile): _accepted[normalized] = lang return lang return settings.LANGUAGE_CODE