赞
踩
目录
多语言站点可以让不同语言的用户更好地使用和理解网站内容,提升用户体验和覆盖范围。为了实现多语言功能,我们将使用Django内置的国际化和本地化支持。我收集了一些知识点整理在这一部分,感兴趣的可以看看。直接跳过此部分也行。也可以看看官方文档:
在开始介绍实现方式之前,让我们先了解一下Django的国际化和本地化是什么。国际化是指把程序的文本和用户界面设计得可以适应不同的语言和地区。本地化是指根据用户所在的语言和地区来提供相应的语言翻译和格式化。Django提供了一套完整的国际化和本地化解决方案,可以帮助我们轻松地创建和管理多语言站点。
locale name¶
区域名称,可以是 ll
形式的语言规范,也可以是 ll_CC
形式的语言和国家组合规范。例如:it
、de_AT
、es
、pt_BR
、sr_Latn
。语言部分总是用小写。国家部分如果超过两个字符,则首字母大写,否则全部大写。分隔符为下划线。
language code¶
代表语言名。浏览器使用这个格式来在 Accept-Language
HTTP header 里发送浏览器接受的语言名。比如:it
, de-at
, es
, pt-br
。语言代码一般用小写表示,但是 HTTP Accept-Language
header 不区分大小写。用破折号来间隔。
message file¶
一个消息文件是文本文件,代表一种语言,包含所有可用的 translation strings ,以及它们如何在给定的语言里表示。消息文件的文件扩展名是 .po
。
translation string¶
可以翻译的文字。
format file¶
格式文件是一个 Python 模块,用于定义本地数据格式。
Django LANGUAGE_CODE 有两个作用:
Django 使用的语言代码遵循 ISO 639-1 标准。以下是 Django 支持的所有语言代码列表(中文的是zh开头,所以在列表的最后面,包括zh-hans简体中文,zh-hant繁体中文。这个和以往用zh或zh-CN不太一样。具体看1.3):
- LANGUAGES = (
- ('af', 'Afrikaans'),
- ('ar', 'Arabic'),
- ('ast', 'Asturian'),
- ('az', 'Azerbaijani'),
- ('bg', 'Bulgarian'),
- ('be', 'Belarusian'),
- ('bn', 'Bengali'),
- ('br', 'Breton'),
- ('bs', 'Bosnian'),
- ('ca', 'Catalan'),
- ('cs', 'Czech'),
- ('cy', 'Welsh'),
- ('da', 'Danish'),
- ('de', 'German'),
- ('dsb', 'Lower Sorbian'),
- ('el', 'Greek'),
- ('en', 'English'),
- ('en-gb', 'British English'),
- ('eo', 'Esperanto'),
- ('es', 'Spanish'),
- ('es-ar', 'Argentinian Spanish'),
- ('et', 'Estonian'),
- ('eu', 'Basque'),
- ('fa', 'Persian'),
- ('fi', 'Finnish'),
- ('fr', 'French'),
- ('fy', 'Frisian'),
- ('ga', 'Irish'),
- ('gd', 'Scottish Gaelic'),
- ('gl', 'Galician'),
- ('he', 'Hebrew'),
- ('hi', 'Hindi'),
- ('hr', 'Croatian'),
- ('hsb', 'Upper Sorbian'),
- ('hu', 'Hungarian'),
- ('hy', 'Armenian'),
- ('ia', 'Interlingua'),
- ('id', 'Indonesian'),
- ('is', 'Icelandic'),
- ('it', 'Italian'),
- ('ja', 'Japanese'),
- ('ka', 'Georgian'),
- ('kk', 'Kazakh'),
- ('km', 'Khmer'),
- ('kn', 'Kannada'),
- ('ko', 'Korean'),
- ('lb', 'Luxembourgish'),
- ('lt', 'Lithuanian'),
- ('lv', 'Latvian'),
- ('mk', 'Macedonian'),
- ('ml', 'Malayalam'),
- ('mn', 'Mongolian'),
- ('my', 'Burmese'),
- ('nb', 'Norwegian Bokmal'),
- ('ne', 'Nepali'),
- ('nl', 'Dutch'),
- ('nn', 'Norwegian Nynorsk'),
- ('os', 'Ossetic'),
- ('pa', 'Punjabi'),
- ('pl', 'Polish'),
- ('pt', 'Portuguese'),
- ('pt-br', 'Brazilian Portuguese'),
- ('ro', 'Romanian'),
- ('ru', 'Russian'),
- ('sk', 'Slovak'),
- ('sl', 'Slovenian'),
- ('sq', 'Albanian'),
- ('sr', 'Serbian'),
- ('sr-latn', 'Serbian Latin'),
- ('sv', 'Swedish'),
- ('sw', 'Swahili'),
- ('ta', 'Tamil'),
- ('te', 'Telugu'),
- ('th', 'Thai'),
- ('tr', 'Turkish'),
- ('tt', 'Tatarish'),
- ('udm', 'Udmurt'),
- ('uk', 'Ukrainian'),
- ('ur', 'Urdu'),
- ('vi', 'Vietnamese'),
- ('zh-hans', 'Simplified Chinese'),
- ('zh-hant', 'Traditional Chinese'),
- )
一个语言的描述规则是下面这样的:
- language-extlang-script-region-variant-extension-privateuse
- 语言文字种类-扩展语言文字种类-变体(或方言)-使用区域-变体(或方言)-扩展-私有
这些字符串对应的值拼接起来可以对应一个准确的语言。为了方便辨识和识别,通常还有约定:
所以问题“zh-cn 与 zh-hans 是什么关系、有什么区别?”中的惯用写法应该改成 zh-CN 和 zh-Hans。前者第二位用了地区限制匹配范围,后者用了文字变体限制。具体值对应的内容可以在这里搜索https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
RequestContext对象有三个针对翻译的变量LANGUAGES,LANGUAGE_CODE和LANGUAGE_BIDI,分别表示语言列表,当前用户语言的偏好,和语言的书写方式:
如果是在windows系统下,需要进行环境配置及下载第三方库gettext。如果没有这个工具在生成多语言文件时,会报错:
Can't find msguniq. Make sure you have GNU gettext tools 0.15 or newer installed.
进入网址gettext 0.21 and iconv 1.16 - Binaries for Windows | mlocati - Michele Locati下载软件gettext或者压缩包,下载后安装。安装后在path中配置环境变量。配置好后,退出pycharm再重新进入,使配置生效。
然后再cmd.EXT里运行命令检查是否安装和配置正确
使用函数 gettext() 来指定翻译字符串。按照惯例,将其作为下划线( _ )导入,以保存输入。
from django.utils.translation import gettext_lazy as _
- MIDDLEWARE = [
- 'django.middleware.security.SecurityMiddleware',
- 'django.contrib.sessions.middleware.SessionMiddleware',
- 'django.middleware.locale.LocaleMiddleware', # 多语言(LocaleMiddleware这个中间件,应于SessionMiddleware之后,CommonMiddleware之前)
- 'django.middleware.common.CommonMiddleware',
- 'django.middleware.csrf.CsrfViewMiddleware',
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.contrib.messages.middleware.MessageMiddleware',
- 'django.middleware.clickjacking.XFrameOptionsMiddleware',
- ]
- TEMPLATES = [
- {
- 'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'DIRS': [BASE_DIR / 'templates']
- ,
- 'APP_DIRS': True,
- 'OPTIONS': {
- 'context_processors': [
- 'django.template.context_processors.debug',
- 'django.template.context_processors.request',
- 'django.contrib.auth.context_processors.auth',
- 'django.contrib.messages.context_processors.messages',
- 'django.template.context_processors.i18n', # i18n上下文渲染器
- ],
- },
- },
- ]
- LANGUAGE_CODE = 'zh-hans' # admin 后台默认语言
- TIME_ZONE = 'Asia/Shanghai' # 时区:亚洲上海
- USE_I18N = True # 开启国际化(Internationalization)
- USE_L10N = True # 开启本地化(localization)
- USE_TZ = False # 关闭时区支持(是否错过8小时)
-
- LANGUAGES = (
- ('en', _('English')),
- ('zh-hans', _('中文简体')),
- )
- LOCALE_PATHS = [os.path.join(BASE_DIR, 'locale'),] # 多语言翻译文件存放位置
LOCAL_PATHS注意配置的格式,如果写的不对也会报错。
- from django.contrib import admin, auth
- from django.urls import path,include
- from django.conf.urls.i18n import i18n_patterns
-
-
- urlpatterns = [
- # path('i18n/', include('django.conf.urls.i18n')),
- # path('admin/', admin.site.urls),
- ]
- urlpatterns += i18n_patterns(
- path('admin/', admin.site.urls),
i18n_patterns这个方法的作用,可以参考下面源代码前面的注释:
将语言代码前缀添加到此函数中的每个URL模式。
这只能用于根URLconf,而不能用于包含的URLconf。
- def i18n_patterns(*urls, **kwargs):
- """
- Adds the language code prefix to every URL pattern within this
- function. This may only be used in the root URLconf, not in an included
- URLconf.
- """
- if not settings.USE_I18N:
- return list(urls)
- prefix_default_language = kwargs.pop('prefix_default_language', True)
- assert not kwargs, 'Unexpected kwargs for i18n_patterns(): %s' % kwargs
- return [LocaleRegexURLResolver(list(urls), prefix_default_language=prefix_default_language)]
根据3.1中LOCAL_PATHS中的配置,在项目manage.py同级目录下,创建文件夹locale
在locale
文件夹中,Django会为每种语言创建一个对应的子文件夹。在每个子文件夹中,我们需要创建一个.po
文件,用于存放翻译的文本。.po
文件是一种可以用于人类和机器阅读的文件格式,包含了原始文本和翻译文本的对应关系。
python manage.py makemessages -l zh_hans
python manage.py makemessages -l en
这里注意一下,1.locale下必须生成相应的文件,2.执行上面命令的过程可能会有一些提示,按照提示操作就好,3.如果这步骤报错,耐心去找原因,并解决。
这句命令会把我们在template里、*.py文件里使用的msgid放入到*.po文件,我们再去po文件里的填写其它语言。
python manage.py compilemessages
假设我们要创建英语和中文简体的翻译文件。首先,我们需要在locale
文件夹中创建en
和zh_CN
两个子文件夹。然后,在每个子文件夹中创建一个与项目同名的.po
文件,例如对于英语,我们可以创建一个django.po
文件。
接下来,我们使用翻译工具,如Poedit,打开.po
文件,并进行翻译。在.po
文件中,每个待翻译的文本都由一个前缀为msgid
的消息标识符表示,而翻译后的文本则由一个前缀为msgstr
的消息字符串表示。
- msgid "Hello, world!"
- msgstr "你好,世界!"
这一部分,我这次还没开始做,第一研究的时候,做过一次。然后参照了这篇文章:
Django提供了一个内置的模板标签trans
,用于将待翻译的文本传递给翻译引擎。
{%load i18n%}
在模板中,在模板的前面加上{%load i18n%},
与所有模板标签一样,这个标签需要在所有需要翻译的模板中加载,甚至那些从其他模板继承(extend)而来的模板,也需要继承 i18n
标签。
{% trans %}
使用{% trans %}
标签将待翻译的文本包裹起来。例如,如果我们在模板中要翻译一个标题为”Hello, world!”的文本,可以这样写:
- {% load i18n %}
-
- <h1>{% trans "Hello, world!" %}</h1>
除了在模板中使用翻译文本外,我们还可以在Python代码中动态翻译文本。Django提供了一个全局函数gettext
,用于在Python代码中进行翻译。我们可以通过导入django.utils.translation
模块来使用该函数。
- from django.utils.translation import gettext as _
-
- def welcome_message(request):
- message = _('Hello, world!')
- return HttpResponse(message)
为了让用户可以切换语言,我们可以在模板中添加语言切换链接。Django提供了一个内置的标签{% language %}
,用于生成语言切换链接。我们可以将该标签放置在模板的适当位置,并使用url
参数指定切换语言时的URL。
- {% load i18n %}
-
- <ul>
- <li><a href="{% language 'en' %}">English</a></li>
- <li><a href="{% language 'zh-cn' %}">中文简体</a></li>
- <!-- 添加更多语言切换链接... -->
- </ul>
在Django中,使用i18n_patterns
时,如果你遇到了POST请求被转换成GET请求的问题,这通常是因为URL语言前缀的原因。当Django处理国际化的URL时,它会将语言前缀添加到每个请求的path
中,这可能会导致POST请求变成GET请求。
所以,当后台使用request.method == 'POST'处理逻辑时,一直失败。
还没有研究更好的办法,继续搜索中。解决方案如下:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。