我理解的国际化和本地化,是一个Web应用可以使用各种语言和格式提供内容,为全球各地,说着不同语言,写着不同文字的人使用提供便利。软件界面是可以被翻译为各国语言,可以据某些条件切换。显示的数字,日期的格式也可以自由选择。国际化英语称为internationalization,因为太长了,所以简写为i18n,因为i和n之间有18个字母。本地化称为localization,同样可以简写为l10n。还有很关键的一个是时区TimeZone,决定了显示的时间。
基本配置
项目下settings.py文件,添加LocaleMiddleware中间件:
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.locale.LocaleMiddleware', 'django.middleware.common.CommonMiddleware', ]
它应该位于
SessionMiddleware之后
,因为LocaleMiddleware
需要依赖session中的数据.它应该在CommonMiddleware之前,因为
CommonMiddleware需要语言数据去解析请求URL
.如果使用了
CacheMiddleware
, 把LocaleMiddleware
放到它后边.
LocaleMiddleware将会使用下边的逻辑确定用户期望使用的语言:
首先, 查看请求URL的前缀,比如/en/about将会使用英语翻译,怎样配置URL前缀,下文有介绍,详见官方文档。
如果失败了(没有发现语言标记),就会去cookie中寻找django_language键的信息(这个名称可通过LANGUAGE_COOKIE_NAME 配置)。
又失败了, 就会去查看HTTP请求头中的 Accept-Language 项,django会按优先级逐个查找头信息中期望的语言,直到找到为止.
又失败了, 将会使用全局的LANGUAGE_CODE的配置.
其他一些配置:
from django.utils.translation import gettext_lazy as _LANGUAGE_CODE = 'en-us'TIME_ZONE = 'UTC'USE_I18N = TrueUSE_L10N = TrueUSE_TZ = TrueLOCALE_PATHS = [os.path.join(BASE_DIR, 'mysite/locale')]LANGUAGES = [ ('en', _('English')), ('zh-hans', _('Simplified Chinese')),]
其中USE_I18N,USE_L10N是使能开关。
LOCALE_PATHS很重要,这个路径存放翻译文件,而且它的优先级很高,每个app都有自己的翻译文件,但是对于安装的第三方app修改源码路径的翻译文件不太好,可以在这里进行覆盖。
LANGUAGES直接限定了系统存在的翻译语言种类,这里没有的语言就不会去local路径搜索了,加速系统的运行,这里的_('English')就是自动翻译的标记,所以最上边的import是为它服务的。
在python代码中使用
其实上边的配置文件也是python代码,已经用过了,这里主要指在view中如何使用。
from django.http import HttpResponsefrom django.utils.translation import gettext as _def my_view(request): output = _("Welcome to my site.") return HttpResponse(output)
最终_("Welcome to my site.")会根据会话决定的语言,查找对应的翻译文件,把翻译的内容返回给output变量赋值。更多的技巧见官方文档。关于如何制作翻译文件稍后再说。
在模板文件中使用
模板文件会被模板引擎自动填充扩展成HTML代码,其中有很多文字是需要翻译的,这里使用{% trans %}和{% blocktrans %}。
<title>{% trans "This is the title." %}title><title>{% trans myvar %}title>{% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %}
更多使用方法和细节参看官网手册。
在JS中使用
JavaScript的情况更复杂些,因为它不是在服务端执行的,要把相关翻译文件和函数传给浏览器,然后才能使用。
在urlpatterns中注册资源链接地址:
from django.views.i18n import JavaScriptCatalogurlpatterns = [ path('jsi18n/', JavaScriptCatalog.as_view(),name='javascript-catalog'), ]
在模板中引入资源:
<script type="text/javascript" src="{% url 'javascript-catalog' %}">script>
在代码中使用相关函数:
document.write(gettext('this is to be translated'));
或者将上文的JavaScriptCatalog类似的JSONCatalog 引入,可以获得一条json格式的翻译文件链接,由其他js库调用。
在URL中使用
在URL中有两个机制,一个是在url中添加语言的前缀,一个是使用翻译。
添加前缀很简单,在注册url时,使用i18n_patterns包装一下:
urlpatterns += i18n_patterns( path('about/', about_views.main, name='about'), path('news/', include(news_patterns, namespace='news')),)
这样在不同的语言配置下,最终链接会变成/en/about,/zh/news格式
第二个是直接在URL中使用翻译:
from django.utils.translation import gettext_lazy as _urlpatterns += i18n_patterns( path(_('about/'), about_views.main, name='about'), path(_('news/'), include(news_patterns, namespace='news')),)
在模板中使用这种链接可以使用{% language %}标记:
{% language lang_code %} <a href="{% url 'category' slug=category.slug %}">{{ lang_name }}a>{% endlanguage %}
如何制作翻译文件
为什么我们要先写代码再制作翻译文件呢?因为要翻译哪些内容只有写代码时才能确定,并且有工具命令把需要翻译的内容做成列表,然后我们完成列表中内容的翻译就行了。生成翻译文件:
python3 manage.py makemessages -l zh_Hans(或者django-admin makemessages -l zh_Hans )
在app的翻译路径会出现这个文件locale/zh_Hans/LC_MESSAGES/django.po
假如代码中使用了_("Welcome to my site.")标记,文件中就会有它对应的翻译:
#: path/to/python/module.py:23msgid "Welcome to my site."msgstr "欢迎来到我的网站"
msgstr的内容就是你要翻译的内容,可不会自动生成。
翻译完成之后,进行编译:
python3 manage.py compilemessages(或者django-admin compilemessages)到
这时翻译路径就会出现编译好的locale/zh_Hans/LC_MESSAGES/django.mo文件
这时就可以启动项目查看效果了,这里只是大体上的过程,有很多细节我没有写到,还是那句话详见官网文档。
官网相关链接:https://docs.djangoproject.com/en/3.0/topics/i18n/