首先,需要明确一点:我们要实现的中英对照翻译,这个翻译不是浏览器翻译的,也不是Django帮你翻译。这个需要你自己事先手动翻译好,存放在专门翻译文件中,Django只是事后调用而已。
第一步 新建项目后,修改settings.py
假如创建的项目叫xiangmu
,创建的app叫wangzhan
, 然后在xiangmu
目录下新建locale
文件夹,用于保存翻译消息文件(.po和.mo格式的文件)。修改配置文件settings.py:
python
# 引入模块
from django.utils.translation import ugettext_lazy as _
# 引入app
INSTALLED_APPS = [
...
'wangzhan',
]
# 引入语言中间件,(注意位置,不要变)
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware', # 语言插件
'django.middleware.common.CommonMiddleware',
...
]
# 默认语言为英文
LANGUAGE_CODE = 'en-us'
# 设置I18n和L10N为True
USE_I18N = True
USE_L10N = True
# 指定支持语言。这里为了简化只支持简体中文和英文
LANGUAGES = (
('en', _('English')),
('zh-hans', _('Simplified Chinese')),
)
# 用于存放django.po和django.mo编译过的翻译文件
PROJECT_ROOT = os.path.dirname(os.path.realpath(__name__))
LOCALE_PATHS = (
os.path.join(PROJECT_ROOT, 'locale'),
)
特别说明:
1、使用ugettext_lazy
这个方法的作用是在.py文件文件中标记需要翻译的字符串,对其进行惰性参照存储,而不是对字符串进行真正的翻译。
2,、在models.py和views.py文件中,定义字段时,会用到ugettext_lazy
,来指定标记需要翻译的字符串。
3、在模板html文件中,并不能直接使用ugettext_lazy
这个方法,而是使用
python
# 开头先要引入i18n
{% load i18n %}
# 该标签标记定义需要翻译的字符"string"
{% trans "string" %}
# 该标签标记定义需要翻译的变量
{% blocktrans%} {%endblocktrans %}
小知识:
- 这两个标签也不是对字符串进行真正的翻译,只是标记而已。
- i18n是国际化(Internationalization)的缩写。i 和 n 之间有 18 个字母,简称 I18N。
- l10n是本地化(localization)的缩写。l 和 n 之间有 10 个字母,简称 L10N。
第二步 修改项目的urls.py, 增加国际化i18n的支持
这里的urls.py是项目下的,而不是app下urls.py)。
i18n_patterns的作用:让每个url前面自动加上所选语言的代码,比如/en/, /zh-hans/ 等
python
# 项目下的urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.i18n import i18n_patterns
urlpatterns = [
path('i18n/', include('django.conf.urls.i18n')),
]
urlpatterns += i18n_patterns(
path('admin/', admin.site.urls),
path('', include('wangzhan.urls')),
)
python
# app(wangzhan)下的urls.py
from django.contrib import admin
from django.urls import path
from . import views
app_name = 'wangzhan'
urlpatterns = [
path('', views.index, name='index'),
]
此时,可以通过访问Django自带的admin,来检验语言国际化设置是否成功:
分别访问http://127.0.0.1:8000/en/admin/
和http://127.0.0.1:8000/zh-hans/admin/
第三步 修改视图文件views.py
在视图中我们使用ugettext_lazy方法标记了一个需要翻译的字符串"Welcome to China"。
python
from django.shortcuts import render
# 进入ugettext_lazy方法
from django.utils.translation import ugettext_lazy as _
# Create your views here.
def index(request):
context = {'msg': _("Welcome to China")} # 定义要翻译的字符
return render(request, 'wangzhan/index.html', context)
第四步 在index.html调用标签
python
<!DOCTYPE html>
{% load static %}
{% load i18n %}
<html lang="en">
<head>
...
...
...
# 用于语言的选择切换 (必须是POST请求)
<form class="form-inline ml-3-md" action="{% url 'set_language' %}" method="post"> # 变量set_language = /i18n/setlang/
{% csrf_token %}
<div class="input-group">
<input name="next" type="hidden" value="{{ redirect_to }}" />
<select name="language" class="form-control">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}"{% if language.code == LANGUAGE_CODE %} selected{% endif %}>
{{ language.name_local }}
</option>
{% endfor %}
</select>
<div class="input-group-append">
<button type="submit" class="btn btn-inline btn-sm bg-warning">
{% trans "Select" %}
</button>
</div>
</div>
</form>
...
...
...
#
{% block content %}
<div class="py-4 px-3 bg-light">
<div class="container">
{% get_current_language as LANGUAGE_CODE %}
<h4>{% trans 'Current language code' %}: {{ LANGUAGE_CODE }}</h4>
<p><small>{% trans "Welcome to our page" %}</small></p>
<hr/>
<p>{% blocktrans %} {{ msg }} {% endblocktrans %}</p>
</div>
</div>
{% endblock %}
- {% load i18n %}以后,你可以使用get_current_language标签获得当前语言。
- 模板中使用{% trans "string" %},string是需要翻译的文本。
- {% blocktrans%} {%endblocktrans %}标签来标记了两个需要翻译的字符串,
一个是模板中已存在的,一个是视图函数传递过来的变量。
更多用法:
#普通用法
{% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %}
#增加过滤器
{% blocktrans with amount=article.price %}
That will cost $ {{ amount }}.
{% endblocktrans %}
{% blocktrans with myvar=value|filter %}
This will have {{ myvar }} inside.
{% endblocktrans %}
#多个过滤器
{% blocktrans with book_t=book|title author_t=author|title %}
This is {{ book_t }} by {{ author_t }}
{% endblocktrans %}
#注意:其他bolck tags (例如 {% for %} or {% if %}) 不允许在 blocktrans tag内部.
此时,启动测试服务器,应该能看到页面已经能正确显示。但是当你切换不同语言时,页面显示的内容还是一样的,这是因为我们还没对那些字符串进行翻译啊
第五步 生成.po和.mo编译消息文件
1、在\xiangmu\locale\zh_HANS\LC_MESSAGES
目录下,生成.po
文件
python
# django-admin makemessages -l 语言简写
django-admin makemessages -l zh_Hans # 简体中文
django-admin makemessages -l zh_Hant # 繁体中文
django-admin makemessages -l ko-kr # 韩文
django-admin makemessages -l ja # 日文
# 等等(以此类推....)
注意:
在JavaScript多语言这里遇到个坑,js的翻译不管是中文还是英文,都是显示英文翻译。原因是编译的时候,应该用 zh_Hans
而不是zh_hans 或者zh_cn等等
然后,翻译对应字段的.po文件,翻译指定的字符如下:
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-02-02 13:22+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: .\wangzhan\templates\wangzhan\index.html:45
msgid "Select"
msgstr "选择"
#: .\wangzhan\templates\wangzhan\index.html:58
msgid "Current language code"
msgstr "当前语言代码"
#: .\wangzhan\templates\wangzhan\index.html:59
msgid "Welcome to our page"
msgstr "欢迎访问我们的页面"
#: .\wangzhan\templates\wangzhan\index.html:61
#, python-format
msgid " %(msg)s "
msgstr ""
#: .\wangzhan\views.py:10
msgid "Welcome to China"
msgstr "欢迎来到中国北京"
自己手动翻译对应字符后,然后才可以进行下一步的编译!
2、在\xiangmu\locale\zh_HANS\LC_MESSAGES
目录下,生成.mo
文件
python
# 该命令生成一个django.mo的文件
python manage.py compilemessages
这个就是Django最后需要调用的翻译文件,里面包含了翻译过后的字符串列表。
重新启动服务器,就可以看到语言切换的效果了
重要提醒:
提醒(1)、windows系统下使用makemessages和compilemessages命令时会出现错误。
这是因为windows缺少基于GNU的gettext模块。安装方式如下:
-
安装或解压缩到C盘或D盘, 比如C:\Program Files (x86)\gettext
-
把gettex下的bin地址,比如C:\Program Files (x86)\gettext\bin加入到系统PATH的环境变量
(在控制面板>系统>高级>环境变量中添加)。
-
如果pycharm的terminal中运行两个命令有问题,请直接在windows的cmd窗口运行。
-
对于Linux系统如果缺少可以使用
sudo apt-get install gettext
安装。
提醒(2)、多语言国际化的时候渲染模板的方法要用render(request,'xxxxx.html',{}),而不是render_to_response('xxxx.html',{})方法
提醒(3),使用 --extension 或 -e 选项指定文件扩展名来检测
python
django-admin.py makemessages -l de -e txt
# 用逗号和(或)使用-e 或--extension来分隔多项扩展名:
django-admin.py makemessages -l de -e html,txt -e xml
当创建JavaScript翻译目录时,你需要使用特殊的Django域:not -e js
更详细的说明,跳转官方文档查看!