Django 翻译与 LANGUAGE_CODE
LANGUAGE_CODE[1]
LANGUAGE_CODE 是 language code 的字符串。格式与 Accept-Language HTTP header 相同,不区分大小写,比如:zh, es, zh-hans
。所有的 language codes 见 http://www.i18nguy.com/unicode/language-identifiers.html 。
Django LANGUAGE_CODE 有两个作用:
- 如果没有设置 locale 中间件,那么这个用于给所有用户提供翻译。适用于只需要一种翻译的情况
- 如果设置了 locale 中间件,那么作为翻译的后备物品,用于没有匹配到语言的情况
LocaleMiddleware 决定用户语言的算法,顺序为 URL 语言前缀、session、cookie、Accept-Language HTTP 头部,最后是 LANGUAGE_CODE[2]。
注意:Django 的 LANGUAGE_CODE 是不区分大小的,但第三方 APP 就不一定了,比如 django-ckeditor
只有在 LANGUAGE_CODE 为 zh-hans
时翻译才会生效,所以它是区分大小写的。
寻找翻译的算法
在运行时,Django 会构建一个在内存中的、统一的文字翻译目录。依次在以下路径中加载信息文件(.mo)以及对同一字符串的翻译优先级如果对统一字符串存在多个翻译:
- LOCALE_PATHS 有最高优先级,在 LOCALE_PATHS 中出现在前面的优先级更高。
- 然后查看 INSTALLED_APPS 中各个 APP 目录下的 locale/,也是在前面的 APP 优先级高
- 最后,
django/conf/locale
作为后备
存放翻译文件的目录名为 locale name。在我看来就是将对应的 language code 的 -
替换为 _
。比如 language code zh-Hans
的 locale name 为 zh_Hans
。这点可以在 Django 自己的翻译中得到验证,比如 env/lib/python3.6/site-packages/django/conf/locale/zh_Hans
。
替换虚拟环境中第三方 APP 的翻译
我将第三方 APP 的替代翻译放在 LOCALE_PATHS 中,但只有在 env/
在和 manage.py
同目录的情况下才能生效。不清楚这样的原因,因为按照上面的算法,LOCALE_PATHS 的优先级是最高的。
目前采用的办法是,fork 该第三方 APP,然后将翻译直接放到第三方 APP 的 locale 中,然后使用 submodule 安装 fork 后的第三方库。