django 国际化问题

配置django url时注意的问题

Your URL pattern '^$' uses include with a regex ending with a '$'. Remove the dollar from the regex to avoid problems including URLs.9

在配url时,如果包含include参数,正则表达式不要包含$符号,不然django就会在console中提示以上警告。警告的原因是因为,如果url中包$符,则只能完全匹配正则中的字符,而不能包含include中的正则。

配置Admin后台使用中文

在settings.py中的MIDDLEWARE参数中添加如下代码:
'django.middleware.locale.LocaleMiddleware'

配置自定义Model中文

利用内置Meta类可以使Admin中的显示成中文:

1
2
3
class Meta:
verbose_name=u"中文"
verbose_name_plural = u"中文的复数"

更改App的名称

在app.py文件里 给Config类添加verbose_name属性:

1
2
3
class WechatConfig(AppConfig):
name = 'wechat'
verbose_name = u"小程序"

通过继承更改第三方app的名称

有时候我们安装了第三方的app,那么如何更改第三方app的名称呢,虽然可以通过修改源码的方式进行,但是这里我们推荐通过继承的方式进行修改,这样不会影响到同样引用了第三方的另一个应用的代码。

1
2
3
4
from sequences.apps import SequencesConfig
class MySequecesConfig(SequencesConfig):
verbose_name =u'序列'

国际化

很多时候我们也许只是需要修改一下翻译,那么我可以使用第三方模块的国际化语言,使之本地化。

配置翻译路径

首先,我们需要手动在项目中创建一个locale文件夹,然后在配置文件中配置好文件夹路径:

1
2
3
LOCALE_PATHS = (
os.path.join(BASE_DIR, 'locale'),
)

并开启国际化支持:

1
2
3
4
MIDDLEWARE_CLASSES = (
...
'django.middleware.locale.LocaleMiddleware',
)

注意:MIDDLEWARE_CLASSES中要增加’django.middleware.locale.LocaleMiddleware’,该中间件要出现在SessionMiddleware和CacheMiddleware后,其他所有中间件之前,而TEMPLATE_CONTEXT_PROCESSORS 中要增加 ‘django.core.context_processors.i18n’.

多语言支持

1
2
3
4
LANGUAGES=(
('zh-hans','zh_CN'),
('en','EN'),
)

默认语言设置

1
LANGUAGE_CODE = ('en')

其他设置

1
2
3
4
5
6
7
8
#是否自动判断Accept-Language头转换语言
LOCALEURL_USE_ACCEPT_LANGUAGE=False
#是否显示语言前缀
PREFIX_DEFAULT_LOCALE = True
#是否在session中保存用户指定的语言
LOCALEURL_USE_SESSION=True

编辑和编译

使用命令
python manage.py makemessages -l zh_hans
创建翻译文件
注意:对于django-1.8及以前版本,使用
python manage.py makemessages -l zh-cn
命令(下同)

使用poedit编辑 po文件,翻译完成后保存
最后一步,
使用命令:
python manage.py compilemessags
编译翻译文件,使之生效

django确定翻译语言的顺序

  1. 在用户session里查找django_language key
  2. 如果不存在session,查找django_language cookie
  3. 查找http头 Accept-Language
  4. 以后都未设置,使用settings.LANGUAGE_CODE

django查找mo文件的路径顺序

  1. settings LOCALE_PATHS变量指定的路径
  2. 每个app目录下的locale目录
  3. 工程目录下的locale目录
  4. 最后是django/conf/locale目录
    当有重复的mo文件时,mo优先级同查找顺序一致,即先找到的会屏蔽其后边的mo项

第三方app的翻译问题

如果使用的第三方app并没有中文版翻译,那么我们可以通过将第三方文件的翻译追加到本项目中的po文件中的方式完成第三方app的翻译。

App Name 的翻译

1
2
3
4
5
6
7
from django.utils.translation import ugettext_lazy as _
class WechatConfig(AppConfig):
name = 'wechat'
verbose_name = _("Min Pros")
class MySequecesConfig(SequencesConfig):
verbose_name = _('Sequence')

这里应该使用 ugettext_lazy而不能使用 ugettext. 两者的区别在于lazy版本的ugettext并不在定义的时候执行,只是返回一个proxy对象,只有当需要显示的时候才真正的执行,以给出最新的翻译。ugettext可以是用在template中,因为template每次request都执行一遍,因而能获取到最新的翻译。ugettext_lanzy大多是用在model表单和Model中。

如下的情况不能使用ugettext_lazy:
return HttpResponse(ugettext_lazy("Hello").encode('utf-8'))
因为此时需要使用的是string而不是proxy对象。

中文翻译的坑

django 1.11.2版本中,中文的代码已经变为zh-hans,在配置文件中应该使用zh-hans这是没有疑问的,但是在locale文件中,中文与之对应的文件夹名称应该为zh_Hans,注意这里的H一定要大写,否则写成zh_hans,zh_CN,zh_cn,zh-hans均不能被识别加载。