问题描述

最近做的网站需要中英双语可以切换,内容大致相同,只是文字上需要做翻译,而且可以让用户进行语言的选择。

问题解决

其实页面大部分内容是相同的,只是文字和部分图片不同。django提供了i18n(internationalization)的解决方案。

i18n提供接口让web开发者在制作网站时将需要翻译的部分标记出来,然后生成翻译文件,在翻译文件中对标记的字符串进行翻译,然后编译生成供django使用的翻译文件即可。下面按步骤记录下过程。

1.添加url

在url文件中添加:

url(r'^i18n/', include('django.conf.urls.i18n')),

这样,发送i18n/开头的Post会送给django的i18n处理。

2. 在settings中更新国际化的相关设置

在settings.py中添加:

USE_I18N = True
ugettext = lambda s: s LANGUAGES = ( ('en-us', ugettext('English')), ('zh-CN', ugettext('Chinese')),
)

3.模板设置

在settings.py里面的TEMPLATES列表里面的OPTIONS里面的context_processors里面添加一条:

'django.template.context_processors.i18n',

4.添加django.middleware.locale.LocaleMiddleware中间件

需要放在 
django.contrib.sessions.middleware.SessionMiddleware后面, 
django.middleware.common.CommonMiddleware的前面,如下:

MIDDLEWARE = ['django.contrib.sessions.middleware.SessionMiddleware','django.middleware.locale.LocaleMiddleware','django.middleware.common.CommonMiddleware',
]

5.同步数据库

i18n需要section数据库表的支持,所以需要同步数据库。

6.添加待翻译标记

待翻译部分可能位于模板中,也可能位于视图函数中,两者标记的方式不同。

试图函数方法如下:

首先引入ugettext:

from django.utils.translation import ugettext as _

然后将待翻译的字符串作为ugettext的参数,比如:

_('Please input correct verification code'))

这样这个字符串在处理好i18n后就可能会被替换成其他语言。

在模板中方式如下:

首先要引入i18n:

{% load i18n %}

然后将待翻译的字符串用{%trans ‘some strings’ %}包裹起来,比如:

{%trans 'please input password' %}

这样在i18n中’please input password就会被替换成其他语言。

7.创建并更新语言文件

先在app中创建一个名为locale的路径,然后执行:

$ django-admin makemessages -l zh_CN

这样就会在locale目录下生成一个zh_CN/LC_MESSAGES/这样的路径里面有个名为django.po的文件,这个文件将我们标记出来的字符串列了出来,我们可以在这里进行翻译。

翻译完成后执行:

$ django-admin compilemessages

生成一个名为django.mo的文件,就是django使用的翻译文件。

做到这一步,就可以根据用户的浏览器语言设置,使用相应的语言。但如果需要用户自己选择他的语言种类,还需要更进一步。

8.提供用户选择语言种类的接口

在模板中提供一个表单:

<form name="testform" id="testform" method='post'>{% csrf_token %}<select id="language" name="language" onchange="selectdb(this)"><option value="1">{% trans "Languages" %}</option>{% for lang in LANGUAGES %}<option value="{{ lang.0 }}" > {{ lang.1 }}</option>{% endfor %}</select>
</form><script>
function selectdb(obj) {str="/i18n/setlang/";myform = document.getElementById('testform');myform.method = "POST";myform.action = str;myform.submit();
}
</script>

这个表单可以将用户选择的语言种类传给/i18n/setlang/,进行语言选择。

另外,如果需要在试图函数中获得当前用户使用的语言,可以使用如下值:

request.LANGUAGE_CODE

http://blog.csdn.net/pipisorry/article/details/45061579

如果你要实现多种语言版本的django网站,如英语和中文的两个网站,lz将介绍一个最快捷的方法。

Note:lz建议不会经常变动的字符如网页表头、title什么的用资源.po文件实现翻译。而admin后台管理员填写的内容在model中设置多个语种的字段,再在views中判断当前请求的语言,来返回相应语种的字段。

Django 国际化简介

国际化 -- Internationalization,i 和 n 之间有 18 个字母,简称 I18N,。本地化 -- localization, l 和 n 之间有 10 个字母,简称 L10N。国际化意味着 Web 产品有适用于任何地方的潜力,针对程序开发人员;本地化则是指使一个国际化的程序为了在某个特定地区使用而进行实际翻译的过程,针对翻译人员而言。

Django 的开发和维护者对 Django 框架本身进行了完全国际化,我们可以在 ./Python2.5/site-packages/django/conf/locale/ 找到相关的语言文件。目前 Django-1.2.1 带着 52 个不同的本地化语言文件发行的,使用户能够方便的使用它现有的管理界面。

Django 国际化的本质就是开发者对需要翻译的字符串进行标记,并对字符串进行相应的翻译。当用户访问该 Web 时,Django 内部框架根据用户使用偏好进行 Web 呈现。

Django 国际化使用的翻译模块是使用 Python 自带的 gettext 标准模块。通过一个到 GNU gettext 消息目录库的接口,这个模块为 Python 程序提供了国际化 (I18N) 和本地化 (L10N)。

开发人员和翻译人员需要完成一下 3 个步骤:

1. 第一步:在 Python 代码和模板中嵌入待翻译的字符串,

2. 第二步:把那些字符串翻译成需要支持的语言,并进行相应的编译

3. 第三步:在 Django settings 文件中激活本地中间件

http://blog.csdn.net/pipisorry/article/details/45061579

安装配置gettext

Django框架具有很好的I18N和L10N的支持,其实现是基于GNU的gettext,所以要想在Django中使用I18N还需要先安装配置gettext。

Windows下的gettext(linux下可能不用安装)

对于那些要提取消息或编译消息文件的人们来说,需要的只有这么多。翻译工作本身仅仅包含编辑这个类型的现存文件,但如果你要创建你自己的消息文件,或想要测试或编译一个更改过的消息文件,你将需要这个gettext公用程序。

1. 从http://sourceforge.net/projects/gettext下载以下zip文件

gettext-runtime-0.17.zip

gettext-tools-0.17.zip

  • 同一文件夹下(e.g.D:\Downloads\Programming\gettext)展开这2个压缩文件中的bin\。(注意目录合并了)

  • 更新系统路径

    • 控制面板>系统>高级>环境变量,在系统变量列表中,点击Path,点击Edit,把;D:\Downloads\Programming\gettext\bin加到变量值字段的末尾。

Note:安装时一定要注意版本对应,如django1.7对应版本0.15+;安装可能需要libiconv-1.9.1.tar.gz
在CMD中验证下我们的配置是否正确xgettext --version或者gettext --version。

Note:
1. 可能先要用命令CHCP 65001修改cmd编码为utf-8,否则执行gettext --version会出现乱码和死循环打印奇怪字符。(lz也是醉了- -!)[windows命令行cmd设置和快捷键]
2. 只要xgettext--version命令正常工作,你亦可使用从别处获得的gettext的二进制代码。有些版本的0.14.4二进制代码被发现不支持这个命令。 不要试图与Django公用程序一起使用一个gettext。在一个windows命令提示窗口输入命令 `` xgettext —version``将导致出现一个错误弹出窗口–“xgettext.exe产生错误并且将被windows关闭”。
3. gettext-tools-X.binzip中的readme提到This package contains Win32 binaries of GNU gettext-tools 0.17.Together with these binaries, you also need the Win32 binaries of GNU gettext-runtime (0.17.1) and of GNU libiconv (1.9.1 or newer).Unpack them in the same directory as this package.7
4. If you don’t have the gettext utilities installed,makemessages will create empty files.

配置

settings.py 里面有一个属性LANGUAGE_CODE = 'en',这里设置了网站默认的语言。

启用i18n

由于settings.py里面的属性支持重写,首先在project的setting.py 文件中启用i18n和l10n,及设置USE_I18N =TRUE和USE_L10N=TRUE,一般情况下这两个值默认是开启状态

如果您不需要国际化支持,那么您可以在您的设置文件中设置 USE_I18N=False 。 如果USE_I18N 被设为 False ,那么Django会进行一些优化,而不加载国际化支持机制。您也可以从您的TEMPLATE_CONTEXT_PROCESSORS 设置中移除'django.core.context_processors.i18n' 。

[Django的官方文档上的i18n]

http://blog.csdn.net/pipisorry/article/details/47185795

声明需要进行国际化的字符串

这又分为.py文件的国际化和html模板文件的国际化。
py文件的国际化

在.py文件中指定翻译字符串的 4 个主要函数及其用途:

django.utils.translation.ugettext()        指定一个翻译字符串,一般都用于 views.py

No-op翻译django.utils.translation.gettext_noop()

标记一个不需要立即翻译的字符串。 这个串会稍后从变量翻译。使用这种方法的环境是,有字符串必须以原始语言的形式存储(如储存在数据库中的字符串)而在最后需要被 翻译出来(如显示给用户时)。

惰性翻译django.utils.translation.gettext_lazy()

ugettext_lazy() 将字符串作为惰性参照存储,而不是实际翻译 , 一般会用于 models.py。 翻译工作将在字符串在字符串上下文中被用到时进行,比如在 Django 管理页面提交模板时。在 Django 模型中总是无一例外的使用惰性翻译。lazy 是一种延迟计算,使用它表示一种对结果的承诺,但只有当真正需要时才会去计算。只要你不是真是需要,你得到的并不是真正的结果。

django.utils.translation.ungettext()    函数包括三个参数: 单数形式的翻译字符串,复数形式的翻译字符串,和对象的个数(将以 count 变量传递给需要翻译的语言)。

这里强烈要求使用惰性翻译,这样能够有效节省django的性能开支。以下我们以惰性翻译为例举个例子:
from django.utils.translation import gettext_lazy as _
transText = _("please login")

模板文件中的国际化
标签修改有两种{% trans "string" %}和{% blocktrans%},{%endblocktrans %},这两个标签都需要在模板的最开始地方加入{% load i18n %}

Note:模板中的 {% load %} 标签用于加载已有的模板。在 /usr/local/lib/Python2.5/site-packages/django/templatetags/i18n.py 文件中定义了指定模版中翻译字符串的模板标签。在 django 的模板前加入 {% load i18n %},在 i18n.py 源文件中的定义标签就可以在有 load 语句的模板中使用了。

{% trans "string" %}

{% load i18n %}
<!DOCTYPE html>
<html lang="en">
<head>
<title> Learning Center {% trans "Welcome You" %}--Learn Center</title>

这样,我们就指定了要进行国际化的字符串welcome you,在适当的时机Django就能够将其翻译成相对应的文字。

Note:一般情况下这两个标签没有什么区别,翻译工作都准备就绪了,接下来就是体现到模板上去了,首先加载i18n,在模板文件的头部加入{% load i18n%},下来对于需要i18n支持的字段使用{% trans 'Key' %},这里的Key就是某个msgid。
只有需要翻译的字符串包含了django的变量,我们才不得不使用blocktrans来标识。
翻译的内容中含有参数的情况{% blocktrans%},{%endblocktrans %}
1.)在html中使用模板参数,此时必须使用{% blocktrans %}代替{% trans %},例如:
{% blocktrans %}This string will have {{ value }} inside.{%endblocktrans %}
其中{{ value }}是一个django模板变量,由django在将模板转换成具体的html时传入;
2.)如果要使用模板过滤器来翻译一个模板表达式,需要在翻译的这段文本中将表达式绑定到一个本地变量中:
{% blocktrans with value|filter as myvar %} This will have {{ myvar}} inside. {% endblocktrans %}
myvar就是用来绑定表达式本地变量;filter是django所支持的所有过滤器,下面是个使用length的例子;
例如:有一个模板变量{{ funcname }},在翻译串内需要用到该变量的字符长度:
{% blocktrans with funcname|length as len %}
There is {{ len }} letter in {{ funcname }}.
{% endblocktrans %}
len :本地变量,用来绑定(或者说保存){{funcname}}的长度,然后在作为参数出现在翻译字符串内;
{{ funcname }}: 就是1.)里面所讲的模板变量;
这里又引出了另一个问题,就是如果len大于1怎么办? Good question,its answer is using {%plural %} tag. 简单的说就是把单复数形式的句子都写一遍,用{% plural%}区分开,先写单数形式,再写复数形式,实际翻译时,会自动根据len的值来选择句子,具体如下:
{% blocktrans with funcname|length as len %}
There is only one letter in {{funcname}}.
{% plural %}
There are {{ len }} letters in {{ funcname }}.
{% endblocktrans %}
[模板标签的实现原理]

另一种实现-使用template filter[http://simple-is-better.com/news/407]

消息文件 - 翻译文件

制作消息文件

就是为一种语言创建一个信息文件。 信息文件是包含了某一语言翻译字符串和对这些字符串的翻译的一个文本文件。 信息文件以 .po 为后缀名。

这一步的前提是gettext配置好了,然后我们进入到project的根目录创建一个locale的文件夹(如果没有这个文件夹命令会出错)

Note:Changed in Django 1.7:When you runmakemessages from the root directory of your project, theextracted strings will be automatically distributed to the proper messagefiles. That is, a string extracted from a file of an app containing alocale directory will go in a message file under that directory.A string extracted from a file of an app without anylocaledirectorywill either go in a message file under the directory listed first inLOCALE_PATHS or will generate an error if LOCALE_PATHSis empty.Django中带有一个工具,bin/make-messages.py,它完成了这些文件的创建和维护工作。

下面两处处之一运行以下命令:Django项目根目录(包含manage.py的目录。e.g. E:\mine\python_workspace\WebSite\labsite\labsite);您Django应用的根目录。The script should be run from one of two places:The root directory of your Django project (the one that contains manage.py).The root directory of one of your Django apps.

创建或更新一个信息文件

django-admin.py makemessages -l zh

Note:

1. linux/migw使用命令django-admin.py makemessages -l en,如果是在windows环境下需要特别注意,因为这两个命令(+compilemessages)使用了一个windows下默认没有安装的组件,gettext。为在windows下运行,需要下载安装gettext。确保已经安装了gettext,否则出错:

2. windows命令行cmd中要指明路径使用命令pythonD:\python3.4.2/Lib/site-packages/django/bin/django-admin.py makemessages -l en来生成翻译的.po文件

3. zh_CN是所创建的信息文件的语言代码。 在这里,语言代码是以本地格式给出的。 例如,巴西地区的葡萄牙语为pt_BR ,德语de, 澳大利亚地区的德语为de_AT 。lz建议在windows下实现时将zh_CN改成zh,原因见《在settings.py中设置所支持的语言列表》部分Note2

4. 这段脚本遍历你的项目源树或你的应用程序源树并且提取出所有为翻译而被标记的字符串。 它在 locale/LANG/LC_MESSAGES 目录下创建(或更新)了一个信息文件。针对上面的de,应该是locale/de/LC_MESSAGES/django.po。

5. 作为默认, django-admin.py makemessages 检测每一个有.html 扩展名的文件。  以备你要重载缺省值,使用--extension 或-e 选项指定文件扩展名来检测。

django-admin.py makemessages -l de -e txt

用逗号和(或)使用-e或--extension来分隔多项扩展名:django-admin.py makemessages -l de -e html,txt -e xml

6. locale下子目录的样式有固定格式,如:locale/<language>/LC_MESSAGES/。如果是中文,对应的目录就是locale/zh_CN/LC_MESSAGES/。如果是英文,则应该是locale/en/LC_MESSAGES/

7. 为了在django里面使用i18n,po文件名必须为django.po,编译过后必须为django.mo,那么翻译的内容就固定在po文件里了。
8. 也可以自己创建目录在目录中使用python D:/python3.4.2/Tools/i18n/pygettext.py生成翻译文件模版messages.pot,改之,charset=gb2312 Content-Transfer-Encoding: utf8,保存之,文件名改为lang.po.

再参考[python国际化(i18n)和中英文切换]

消息文件错误处理

makemessages时解码错误UnicodeDecodeError:skipped file

windows下,如果html文件(包括注释,不仅仅是trans中的)中存在中文或者奇怪空字符&nbsp&nbsp,就会出现的错误:UnicodeDecodeError:skipped file

commanderror: errors happened while running msgmerge msgmetge:无法识别的选项“--previous"

解决

1. 如果trans中含有中文,建议将html文档编码改成gbk编码[windows小工具 - 转换文件编码]

2. 如果只是html中有中文(trans中没有),建议将D:\python3.4.2\Lib\site-packages\django\core\management\commands\makemessages.py中91/95行语句改成

with open(orig_file, 'r' if six.PY3 else 'rU', encoding='utf-8') as fp:
with open(os.path.join(self.dirpath, thefile), "w", encoding='utf-8') as fp:

原因及解释

html文件编码与django的解码器不对应,官方文档中提到html必须是utf-8编码的,但还是出现编码错误

lz通过分析django源码,发现UnicodeDecodeError错误来源于 makemessages(D:\python3.4.2\Lib\site-packages\django\core\management\commands\makemessages.py),

从第91行语句可见文件是以系统默认编码打开文件的 with open(orig_file, 'r' if six.PY3 else 'rU') as fp:

在文件D:\python3.4.2\Lib\site-packages\django\utils\encoding.py中print编码值,得到cp936而不是utf-8

"Content-Transfer-Encoding: 8bit\n"msgid "Home"msgstr "主页"msgid "News"msgstr "新闻"Note:

1. 格式相对比较简单,也是键值对的形式。如果是多行的话,需要使用msgstr""的形式,首行不写东西,在后续的几行写文本,翻译出来的结果会由程序自动把文字组合到一起。
2. 编写完的po文件需要编辑成二进制的mo文件才可以被django使用,django使用了gettext来实现翻译,所以mo格式也是gettext要求的。
3. 在linux下使用msgfmt -o django.modjango.po即可完成转换过程,相当方便,windows下需要下载poEdit这个软件。

[一词多译:Same string with different translation]

编译信息文件

创建信息文件之后,每次对其做了修改,都需要将它重新编译成一种更有效率的形式,供 gettext 使用。可以使用django-admin.pycompilemessages完成。

这个工具作用于所有有效的 .po 文件,创建优化过的二进制.mo 文件供gettext 使用。在你可以运行django-admin.pymakemessages的目录下,运行
django-admin.py compilemessages
Note:执行django-admin.pycompilemessages会将所有的po文件转成便于编译模块处理的*.mo文件;

知道了需要翻译的语言,Django就会相应的去查找mo文件

首先,Django查看setting.py中是否指定了LOCALE_PATHS,如果有,则使用此值。

如果setting中没有指定,则使用project的各个app目录下的locale文件。

如果project的各个app目录下没有locale,Django就会查找project的根目录,这也是为什么我们第三步在根目录下创建的原因。

如果根目录底下也没有,Django就会自动加载定义在django\conf\locale中的mo文件。

http://blog.csdn.net/pipisorry/article/details/45061579

Django处理语言偏好

一旦你准备好了翻译,如果希望在Django中使用,那么只需要激活这些翻译即可。在这些功能背后,Django拥有一个灵活的模型来确定在安装和使用应用程序的过程中选择使用的语言。

要设定一个安装阶段的语种偏好,请设定LANGUAGE_CODE。如果其他翻译器没有找到一个译文,Django将使用这个语种作为缺省的翻译最终尝试。

如果你只是想要用本地语言来运行Django,并且该语言的语言文件存在,只需要简单地设置LANGUAGE_CODE 即可。

如果要让每一个使用者各自指定语言偏好,就需要使用 LocaleMiddleware 。 LocaleMiddleware 使得Django基于请求的数据进行语言选择,从而为每一位用户定制内容。 它为每一个用户定制内容。

加入一些middleware来支持动态切换语言

使用 LocaleMiddleware需要在MIDDLEWARE_CLASSES中增加django.middleware.locale.LocalMiddleware(此选项用于支持动态国际化)

MIDDLEWARE_CLASSES = (
   'django.contrib.sessions.middleware.SessionMiddleware','django.middleware.locale.LocaleMiddleware','django.middleware.common.CommonMiddleware',
)

Note:

1. 中间件的顺序是有影响的,最好按照依照以下要求:保证它是第一批安装的中间件类。因为 LocalMiddleware 要用到session数据,所以需要放在SessionMiddleware 之后,因为需要从Session里面获取一个语言类型。如果你使用CacheMiddleware,把LocaleMiddleware放在它后面。[中间件]

2. 这里需要注意,需要用数据库保存 session。在本实例中用到了 mysql test2 数据库中的 django_session 数据表。我们在 /home/jerry/testsite 目录下运行 Python manage.py syncdb 就能产生 django_session 了。

LocaleMiddleware 按照如下算法确定用户的语言:

  • 首先,在当前用户的 session 的中查找django_language键;

  • 如未找到,它会找寻一个cookie

  • 还找不到的话,它会在 HTTP 请求头部里查找Accept-Language, 该头部是你的浏览器发送的,并且按优先顺序告诉服务器你的语言偏好。 Django会尝试头部中的每一个语种直到它发现一个可用的翻译。

  • 以上都失败了的话, 就使用全局的 LANGUAGE_CODE 设定值。

Note

1. 在上述每一处,语种偏好应作为字符串,以标准的语种格式出现。 例如,巴西葡萄牙语是pt-br。如果一个基本语种存在而亚语种没有指定,Django将使用基本语种。 比如,如果用户指定了de-at (澳式德语)但Django只有针对de 的翻译,那么 de 会被选用。

在settings.py中设置所支持的语言列表

只有在 LANGUAGES 设置中列出的语言才能被选用。 若希望将语言限制为所提供语言中的某些(因为应用程序并不提供所有语言的表示),则将LANGUAGES 设置为所希望提供语言的列表

测试你返回的是哪个语言的html

一旦LocaleMiddleware决定用户的偏好,它会让这个偏好作为request.LANGUAGE_CODE对每一个HttpRequest有效。请随意在你的视图代码中读一读这个值,如在view.py的某个view函数中写入语言测试代码:

def index(request):'''首页'''if request.LANGUAGE_CODE == 'en':return HttpResponse("You prefer to read english.")else:return HttpResponse("You prefer to read another language.")# return render(request, 'bigdata/index.html', locals())
Note:1. 尽管settings.py中设置了LANGUAGE_CODE = 'zh-CN',但是request.LANGUAGE_CODE却是en,可能是lz用的浏览器是英文版的,创建的session或者request中的lang设置成了en。2. 对于静态翻译(无中间件)而言,此语言在settings.LANGUAGE_CODE中,而对于动态翻译(中间件),它在request.LANGUAGE_CODE中。3. 如果你选择的是用两个不同的html来实现多语种就可以通过上面这个来选择显示的语言。至于request.LANGUAGE_CODE怎么设置下面可以通过html模板上的一个form实现语言选择和设置。在view中返回response?对象时可以用两种形式
return render(request, 'bigdata/index_e.html', locals())
return render_to_response('bigdata/index_e.html', locals(), RequestContext(request))
# return render_to_response('bigdata/index_e.html', locals(), context_instance=RequestContext(request))

在你自己的项目中使用翻译

Django使用以下算法寻找翻译:

  • 首先,Django在该视图所在的应用程序文件夹中寻找locale 目录。 若找到所选语言的翻译,则加载该翻译。

  • 第二步,Django在项目目录中寻找 locale 目录。 若找到翻译,则加载该翻译。

  • 最后,Django使用 django/conf/locale 目录中的基本翻译。

以这种方式,你可以创建包含独立翻译的应用程序,可以覆盖项目中的基本翻译。 或者,你可以创建一个包含几个应用程序的大项目,并将所有需要的翻译放在一个大的项目信息文件中。 决定权在你手中。


所有的信息文件库都是以同样方式组织的: 它们是:
  • $APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)

  • $PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)

  • 所有在settings文件中 LOCALE_PATHS 中列出的路径以其列出的顺序搜索<language>/LC_MESSAGES/django.(po|mo)

  • $PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)

要创建信息文件,也是使用 django-admin.py makemessages.py 工具,和Django信息文件一样。 需要做的就是进入正确的目录——conf/locale (在源码树的情况下)或者locale/ (在应用程序信息或项目信息的情况下)所在的目录下。 同样地,使用compile-messages.py 生成gettext 需要使用的二进制django.mo 文件。

您亦可运行django-admin.py compilemessages--settings=path.to.settings 来使编译器处理所有存在于您LOCALE_PATHS 设置中的目录。

应用程序信息文件稍微难以发现——因为它们需要 LocaleMiddle 。如果不使用中间件,Django只会处理Django的信息文件和项目的信息文件。

最后,需要考虑一下翻译文件的结构。 若应用程序要发放给其他用户,应用到其它项目中,可能需要使用应用程序相关的翻译。 但是,使用应用程序相关的翻译和项目翻译在使用make-messages 时会产生古怪的问题。它会遍历当前路径下所有的文件夹,这样可能会把应用消息文件里存在的消息ID重复放入项目消息文件中。


最容易的解决方法就是将不属于项目的应用程序(因此附带着本身的翻译)存储在项目树之外。 这样做的话,项目级的make-messages 将只会翻译与项目精确相关的,而不包括那些独立发布的应用程序中的字符串。http://blog.csdn.net/pipisorry/article/details/45061579在html模板中设置语言选项设置显示语言

set_language 重定向视图

方便起见,Django自带了一个 django.views.i18n.set_language 视图,作用是设置用户语言偏好并重定向返回到前一页面。

Make sure that the following item is in your TEMPLATE_CONTEXT_PROCESSORS list in your settings file:

TEMPLATE_CONTEXT_PROCESSORS = ('django.core.context_processors.i18n','django.contrib.auth.context_processors.auth',
)

在URLconf中加入下面这行代码来激活这个视图(在urls.py里面配置一个i18n的辅助应用):

(r'^i18n/', include('django.conf.urls.i18n')),

Note:

1. 注意这使得这个视图在 /i18n/setlang/ 中有效

2. 这个视图是通过 GET 方法调用的,在请求中包含了language 参数。 如果session已启用(默认已启用'django.contrib.sessions.middleware.SessionMiddleware',),这个视图会将语言选择保存在用户的session中。 否则,它会以缺省名django_language在cookie中保存这个语言选择。(这个名字可以通过LANGUAGE_COOKIE_NAME设置来改变)

html模板中设置语言选项表格

实现1(推荐,lz亲试)

<form action="{% url 'set_language' %}" method="post">{% csrf_token %}<input name="next" type="hidden" value="{{ redirect_to }}"/><select name="language">{% for language in LANGUAGES %}<option value="{{ language.0 }}"{% if language.0 == LANGUAGE_CODE %} selected="selected"{% endif %}>{{ language.1 }} ({{ language.0 }}){% endfor %}</select><input type="submit" value="Go"/>
</form>

Note:

1. 点击"Submit" 按钮, form-data 数据(就是input中的value和select选中的option中的value)就会被送到服务器上的url 'set_language'对应的页面(也可以使用下面实现2中的"/i18n/setlang/".)action启用了django.views.i18n.set_language 视图,它的作用是设置用户语言偏好并重定向返回到前一页面。[html_form_submit]

2. 如果出现错误Forbidden (403)CSRF verification failed. Request aborted.要在<form action="/i18n/setlang/" method="post">下一行加上 {% csrf_token %}[CSRF verification failed. Request aborted. ]

3.name="next"和name="language"不能改成其它,因为在下面原理中的set_language函数会用到。

4. 第一个input是看不到的,直接向set_language参数request提供next属性,在next的value中指定切换语言后显示的页面,为空时set_language会处理为当前页面的HTTP_REFERER(这个就先当作是原来页面吧)

5.LANGUAGES是在settings.py中设置的全局函数,前面有讲到

6. option中的if应该是选择option中的对应于setting.py的LANGUAGE_CODE语种作为默

实现2

<form action="i18n/setlang/" method="post">{% csrf_token %}<input name="next" type="hidden" value="{{ redirect_to }}"/><select name="language">{% for lang in LANGUAGES %}<option value="{{ lang.0 }}">{{ lang.1 }}</option>{% endfor %}</select><input type="submit" value="Go"/>
</form>
这样,在html页面中选择某个语言,就会返回翻译过后的那个html页面,完成了多语种支持。

/i18n/setlang/中的处理函数分析(文件路径D:\python3.4.2\Lib\site-packages\django\views\i18n.py)

def set_language(request):
    """
    Redirect to a given url while setting the chosen language in the session or cookie. The url and the language code need to be specified in the request parameters.
    Since this view changes how the user will see the rest of the site, it must only be accessed as a POST request. If called as a GET request, it will redirect to the page in the request (the 'next' parameter) without changing any state.

当在 session 或 cookie 中设置所选择的语言时,会重定向到指定的网址。URL 和语言代码需要在 request 的参数中被指定。由于这个视图改变用户如何看到网站的其他部分,它必须只能通过 POST request. 如果调用 GET request, 它将重定向到 request 的那页,但没有任何状态改变。

"""
    next = request.POST.get('next', request.GET.get('next'))
    if not is_safe_url(url=next, host=request.get_host()):
        next = request.META.get('HTTP_REFERER')#using http://127.0.0.1:8000/
        if not is_safe_url(url=next, host=request.get_host()):
            next = '/'
    response = http.HttpResponseRedirect(next)#next is http://127.0.0.1:8000/
    if request.method == 'POST':
        lang_code = request.POST.get('language', None)
        if lang_code and check_for_language(lang_code):
            if hasattr(request, 'session'):
                request.session[LANGUAGE_SESSION_KEY] = lang_code;print(lang_code, 'session')#using this
            else:
                response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code,
                                    max_age=settings.LANGUAGE_COOKIE_AGE,
                                    path=settings.LANGUAGE_COOKIE_PATH,
                                    domain=settings.LANGUAGE_COOKIE_DOMAIN);print(lang_code, 'cookie')
    return response

从上面的代码,可以了解到保存了语言选择后,Django 根据以下算法来重定向页面:

(1)Django 在 POST 数据中寻找 next 参数。

(2)如果 next 参数不存在或为空,Django 尝试重定向页面为 HTML 头部信息中 Referer 的值。

(3)如果 Referer 也是空的,即该用户的浏览器并不发送 Referer 头信息,则页面将重定向到 / (页面根目录)。

这个视图是通过 POST 方法调用的,在请求中包含了 language 参数。所以在前面的模版的 select 的 name 和 id 必须为” language”。

如果 session 已启用(上面提到过默认已启用),这个视图会将语言选择保存在用户的 session 中。 否则,它会以缺省名 django_language 在 cookie 中保存这个语言选择。( 这个名字可以通过 LANGUAGE_COOKIE_NAME 设置来改变 )。

在浏览器中测试

Firefox 语言顺序的选择

工具 - 〉选项 - 〉内容,语言栏这一项选着,将汉语 / 中国 [zh-cn] 移到最上面。这样页面将会根据浏览器的配置,优先中文显示。

其它解决方案

1. Django多语言翻译轻量解决方案:使用localeurl和mothertongue来实现多语言支持,通过localurl实现URL的语言前缀,通过mothertougue来翻译相应的字段。可以对数据库中的内容进行翻译等等,还可以尝试调用google的翻译接口,对一些简单的单词进行翻译,在填入英文时自动翻译成中文。

[Django多语言翻译轻量解决方案]

2. 采用自定义tag的方式定义一个语言选择的下拉框

[django多语言支持]


from:http://blog.csdn.net/pipisorry/article/details/45061579ref:Internationalization: in template codeDjango实现国际化的步骤Django 国际化实例及原理分析基于gettext的Django国际化or多国语言支持(Internationlization)django 实现多语功能网站需要支持中英文切换的功能-CSDN论坛

python Django模板的使用方法(图文)

原文:https://www.cnblogs.com/alexyuyu/articles/7989800.html

django 国际化支持 I18N相关推荐

  1. django国际化与html语言,Django 国际化

    Django 国际化 Django 支持国际化,多语言.Django的国际化是默认开启的,如果您不需要国际化支持,那么您可以在您的设置文件中设置 USE_I18N = False,那么Django会进 ...

  2. java自定义序列化_Java中的自定义国际化(i18n)

    java自定义序列化 国际化(i18n)在我们的软件项目中非常重要. 它主要带来以下好处: 将UI字符串外部化为代码文件以外的外部文件,以及易于管理的UI内容. 支持多种语言. 在这篇文章中,将为Ec ...

  3. Java中的定制国际化(i18n)

    国际化(i18n)在我们的软件项目中非常重要. 它主要带来以下好处: 将UI字符串外部化为除代码文件之外的外部文件,以及易于管理的UI内容. 支持多种语言. 在这篇文章中,将为Eclipse和Java ...

  4. Spring MVC国际化(i18n)和本地化(L10n)示例

    Spring MVC国际化(i18n)和本地化(L10n)示例 欢迎来到Spring Internationalization(i18n)教程.任何遍布全球的用户,国际化(i18n)或本地化(L10n ...

  5. Spring容器创建流程(6)国际化支持

    initMessageSource 初始化MessageSource,Spring国际化支持(之前的执行步骤可在系列文章中找到) 容器refresh总览: synchronized (this.sta ...

  6. qt linux 国际化,多语言,配置CLion管理Qt项目国际化支持

    随着Qt 6的发布,cmake也正式宣告接管qmake的工作了. 在之前的一篇博客里我介绍了如何使用cmake管理你的qt项目,不过有一点我没有讲,那就是对国际化(i18n)的处理. 今天我们就来介绍 ...

  7. spring mvc国际化_Spring MVC国际化(i18n)和本地化(L10n)示例

    spring mvc国际化 Welcome to the Spring Internationalization (i18n) tutorial. Any web application with u ...

  8. 探索Java应用程序的国际化支持

    Java国际化的支持,用以显示符合各种区域和文化标准格式方式的文本元素. 且多种数据格式基于语言和文化的多样性. 地区,日期,时间,和货币格式的显示根据不同区域进行智能显示. 例如,一个区域的日期格式 ...

  9. Spring Boot 架构中的国际化支持实践—— Spring Boot 全球化解决方案

    背景 Spring Boot 主要通过 Maven 或 Gradle 这样的构建系统以继承方式添加依赖,同时继承了 Spring 框架中的优秀元素,减少了 Spring MVC 架构中的复杂配置,内置 ...

最新文章

  1. c++ 开方_刷屏时尚圈!The Story Shoulder稳坐风尚C位的背后究竟有什么奇妙魔力?...
  2. 失败的Omni协议与继续前行的虫洞协议
  3. (转)C# 3.0 LINQ 的演变及其对 C# 设计的影响
  4. python中字符串中文乱码_[python] 中文乱码问题
  5. 9月数据库排行:Microsoft SQL Server分数罕见下滑
  6. Java——File类
  7. ZOJ 1057 Undercut(简单模拟)
  8. 阿里P8架构师谈:深入探讨HashMap的底层结构、原理、扩容机制
  9. Prince2与PMP的区别
  10. keras模型训练参数
  11. 开源版多用户博客系统
  12. 通过ESP32 logging库来启发我们的思维吧~~
  13. MT 3DGIS 试用版本开发包及教程下载地址
  14. 这些免费、可商用的图片素材网站,绝对不能错过
  15. 【BZOJ4011】【HNOI2015】落忆枫音 题解
  16. mb.php js 劫持,黑帽seo防止网站被k的js劫持跳转代码
  17. mysql和mongodb查询性能测试_MongoDB 模糊查询,及性能测试
  18. python画喜羊羊_PYTHON养成日记 DAY-8
  19. iOS常用第三方集合(六)
  20. 编程练习:母牛的故事* 题解

热门文章

  1. 构建兰溪数字贸易新生态!“麒麟计划”兰溪跨境电商综合服务中心今日启动!
  2. 什么是KOA2?KOA2简介
  3. 华硕ASUS PRIME Z790-P D4主板单烤FPU蓝屏
  4. 在OpenFOAM中获取每个网格的Skewness
  5. 汽车加油问题 --贪心算法
  6. 如何优化页面加载速度
  7. ROS添加自定义消息
  8. php 生成图片并压缩保存到本地或者输出到网页imagejpeg方法
  9. 阿里云机器智能首席科学家闵万里:数据升维和智能降维,打造智能工业互联网平台...
  10. POOM(Pocket Outlook Object Model)开发介绍及应用