django提供自带的翻译工具django.utils.translation,除了django自带的工具外你还可以使用pybabel等工具来实现多语言。
我们介绍一下如何在django中一步一步配置多语言翻译的功能,篇幅不长都是干货。
-
首先指定默认语言并且确保你的国际化钩子是开启的,django默认是开启的:
# settings.py ... USE_I18N = True # 国际化钩子是开启的 LANGUAGE_CODE = 'zh-hans' # 默认语言设置为中文 ...
-
使用翻译函数将你需要翻译的字符串“包一下”,比如我在我的用户app中的views.py中返回“你好”。
这一步相当于后面的使用,我提前写在这里是因为我门下一步可以通过命令自动寻找需要翻译的文本:
# views.py ... from django.utils.translation import gettext_lazy as _ ... class TestHello(BaseView): async def get(self, request): msg = _("你好") return HttpResponse(str(msg))
我们使用了惰性翻译,惰性翻译不会实时翻译为结果,有点类似queryset,所以我们需要使用str()函数让这个对象变成翻译后的字符串,当然你也可以使用gettext来代替gettext_lazy直接翻译
-
当我们将需要的翻译的字符串都"包好"之后我们就可以生成翻译文件了
-
首先需要配置翻译文件的目录并且设置我们需要用到哪些语言,这里举例为简体中文和英文,注意我们的语言名字要符合标准的语言格式
# settings.py ... USE_I18N = True # 国际化钩子是开启的 LANGUAGE_CODE = 'zh-hans' # 默认语言设置为中文 # 需要翻译的语言,只有 LANGUAGES 设置中列出的语言才能被选择 LANGUAGES = [ ('zh-hans', '简体中文'), ('en', 'English') ] # LOCALE_PATHS 中列出的目录优先级最高,先出现的比后出现的优先级高,我们只配置一个目录 LOCALE_PATHS = [ BASE_DIR / 'i18n' ] ...
-
我们还需要在各自的app中添加locale目录,这个目录可以不添加,如果不添加那么所有的翻译文本都将集中在上面配置的目录中,如果在app中添加了locale目录那么在后面生成的翻译文件也会根据各自app收集到的文本自动添加在各自的locale目录中,建议是将翻译也解耦到各自的app中
-
接下来执行命令来生成翻译文本,官方给的命令是使用django-admin,这里我们不用,我们直接执行
manage.py
来生成文件# 这行命令生成英文翻译的文本 python manage.py makemessages -l en # 这行命令生成中文翻译的文本 python manage.py makemessages -l zh_HAns
执行完上面的命令后我们可以在项目目录中发现
i18n/
这个目录并且在各个添加了locale目录的app中的locale/
目录下发现和i18n/
目录中一样的文件,大概是这个样子# 项目目录下的文件 i18n/ en/ LC_MESSAGES/ django.po zh_HAns/ LC_MESSAGES/ django.po # app下的文件 myapp/ locale/ en/ LC_MESSAGES/ django.po zh_HAns/ LC_MESSAGES/ django.po
.po文件中大概是下面这个样子,msgid是我们的原始字符串,msgstr就是我们需要翻译成的字符串,我们可以将en目录下的这个文件msgstr赋值为"Hello"
# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-05-17 14:29+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=2; plural=(n != 1);\n" #: fu_generator/base.py:49 msgid "你好" msgstr "Hello"
在将所有的.po文件都翻译准备好后接下来要生成编译文件.mo这个文件才是django最后拿翻译的文件
# 这行命令生成英文翻译的文本 python manage.py compilemessages --ignore "env/*" # --ignore 参数可以忽略一些文件不去编译,当然上面的makemessages命令一样可以添加这个参数
-
-
现在翻译文件也生成了,我们可以添加中间件来生效我们的配置了,可以使用官方自带的中间件
django.middleware.locale.LocaleMiddleware
,当然我们的需求是根据前端传递不同的语言参数来动态拿对应的翻译,所以我们自定义中间件,我们在settings.py同级的目录中添加middleware.py文件from asgiref.sync import iscoroutinefunction, markcoroutinefunction from django.utils import translation class LanguageMiddleware: async_capable = True sync_capable = False def __init__(self, get_response): self.get_response = get_response if iscoroutinefunction(self.get_response): markcoroutinefunction(self) async def __call__(self, request): # 我们假设前端的语言参数是在headers中传递的,参数名为Fu-Language language = request.META.get('HTTP_FU_LANGUAGE') if language: # 设置翻译语言 translation.activate(language) request.LANGUAGE_CODE = translation.get_language() response = await self.get_response(request) return response
然后在settings.py里注册我们的自定义中间件
MIDDLEWARE = [ "django.contrib.sessions.middleware.SessionMiddleware", "projectname.middleware.LanguageMiddleware", # "django.middleware.common.CommonMiddleware", ... ]
到这里我们的翻译工作就做完了,如果language传的是"en"那我们最后返回的就是"Hello",如果传的是"zh-hans"那我门返回的就是"你好"