Django 多语言实现详解
Django 多语言实现详解
一、多语言实现原理
Django 的多语言支持基于以下核心原理:
- 国际化(i18n):使应用程序能够适应不同语言和地区
- 本地化(l10n):为特定语言和地区提供翻译和格式
- 翻译系统:通过 gettext 工具链提取和编译翻译字符串
- 中间件:检测用户语言偏好并设置相应语言环境
- 模板和视图:在代码中标记可翻译文本
二、一步步实现过程
步骤 1:配置 Django 设置
# settings.py
# 1. 启用国际化支持
USE_I18N = True
USE_L10N = True
# 2. 设置支持的语言
LANGUAGES = [
('en', 'English'),
('zh-hans', '简体中文'),
('zh-hant', '繁體中文'),
('ja', '日本語'),
]
# 3. 设置默认语言
LANGUAGE_CODE = 'en'
# 4. 指定翻译文件位置
LOCALE_PATHS = [
os.path.join(BASE_DIR, 'locale'),
]
# 5. 添加中间件(确保在SessionMiddleware之后)
MIDDLEWARE = [
# ...
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware', # 语言中间件
'django.middleware.common.CommonMiddleware',
# ...
]步骤 2:标记可翻译文本
在 Python 代码中:
# views.py
from django.utils.translation import gettext as _
from django.utils.translation import gettext_lazy
def my_view(request):
# 普通翻译
output = _("Welcome to my site.")
# 带变量的翻译
name = "John"
output = _("Hello, %(name)s") % {'name': name}
# 复数形式
count = 3
output = ngettext(
'There is %(count)d item',
'There are %(count)d items',
count
) % {'count': count}
return HttpResponse(output)
# models.py
from django.db import models
from django.utils.translation import gettext_lazy as _
class Product(models.Model):
name = models.CharField(_("Product name"), max_length=100)
description = models.TextField(_("Product description"))
class Meta:
verbose_name = _("Product")
verbose_name_plural = _("Products")在模板中:
<!-- 加载 i18n 标签 -->
{% load i18n %}
<!-- 简单翻译 -->
<h1>{% trans "Welcome" %}</h1>
<!-- 带变量的翻译 -->
<p>{% trans "Hello" %} {{ user.name }}</p>
<p>{% blocktrans with username=user.username %}
Welcome, {{ username }}!
{% endblocktrans %}</p>
<!-- 带过滤器的翻译 -->
<p>{{ product.name|title }}</p>
<!-- 复数形式 -->
<p>
{% blocktrans count counter=cart.items.count %}
There is {{ counter }} item in your cart.
{% plural %}
There are {{ counter }} items in your cart.
{% endblocktrans %}
</p>
<!-- 在模板中设置语言 -->
<form action="{% url 'set_language' %}" method="post">
{% csrf_token %}
<input name="next" type="hidden" value="{{ request.path }}">
<select name="language">
{% 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 }} ({{ language.code }})
</option>
{% endfor %}
</select>
<input type="submit" value="Go">
</form>步骤 3:提取翻译字符串
# 1. 创建 locale 目录(如果不存在)
mkdir -p locale
# 2. 提取所有可翻译字符串到 .po 文件
# Django 会扫描所有模板和代码文件
django-admin makemessages -l zh_hans # 简体中文
django-admin makemessages -l zh_hant # 繁体中文
django-admin makemessages -l ja # 日语
# 针对特定目录
django-admin makemessages -l zh_hans -i venv # 排除 venv 目录
# 重新提取所有语言
django-admin makemessages -a步骤 4:翻译 .po 文件
.po 文件示例:
# locale/zh_hans/LC_MESSAGES/django.po
msgid "Welcome to my site."
msgstr "欢迎来到我的网站。"
msgid "Hello, %(name)s"
msgstr "你好,%(name)s"
# 复数形式
msgid "There is %(count)d item"
msgid_plural "There are %(count)d items"
msgstr[0] "有 %(count)d 个项目"
msgstr[1] "有 %(count)d 个项目"步骤 5:编译翻译文件
# 编译所有 .po 文件为 .mo 文件(机器可读格式)
django-admin compilemessages
# 针对特定语言
django-admin compilemessages -l zh_hans步骤 6:配置 URL 和语言切换
# urls.py
from django.conf.urls.i18n import i18n_patterns
from django.urls import path, include
from django.views.i18n import set_language
urlpatterns = [
path('i18n/', include('django.conf.urls.i18n')),
]
# 使用 i18n_patterns 为不同语言创建URL前缀
urlpatterns += i18n_patterns(
path('', home_view, name='home'),
path('about/', about_view, name='about'),
# 这些URL会自动添加语言前缀,如 /en/about/, /zh-hans/about/
)步骤 7:实现语言切换视图
# views.py
from django.conf import settings
from django.http import HttpResponseRedirect
from django.utils import translation
def set_language_view(request, language_code):
# 验证语言代码是否在支持的语言列表中
if language_code in dict(settings.LANGUAGES).keys():
# 设置用户会话中的语言偏好
request.session[translation.LANGUAGE_SESSION_KEY] = language_code
# 设置 cookie(可选)
response = HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
response.set_cookie(
settings.LANGUAGE_COOKIE_NAME,
language_code,
max_age=settings.LANGUAGE_COOKIE_AGE,
path=settings.LANGUAGE_COOKIE_PATH,
domain=settings.LANGUAGE_COOKIE_DOMAIN,
)
return response
return HttpResponseRedirect('/')三、高级功能和最佳实践
1. 翻译模型数据
# 使用 django-modeltranslation
# 安装:pip install django-modeltranslation
# 创建 translation.py
from modeltranslation.translator import translator, TranslationOptions
from .models import Product
class ProductTranslationOptions(TranslationOptions):
fields = ('name', 'description',)
translator.register(Product, ProductTranslationOptions)2. JavaScript 国际化
// 在模板中
<script src="{% url 'javascript-catalog' %}"></script>
// 使用
const text = gettext('Welcome');
const ntext = ngettext('item', 'items', count);3. 时区和本地化格式
# settings.py
USE_TZ = True
TIME_ZONE = 'Asia/Shanghai'
# 格式化本地化
from django.utils.formats import date_format, number_format
localized_date = date_format(date_obj)
localized_number = number_format(1234.56)4. 检测用户语言偏好
# 基于浏览器设置
def get_client_language(request):
return request.META.get('HTTP_ACCEPT_LANGUAGE', '')
# 基于用户设置(如果有用户系统)
if request.user.is_authenticated and request.user.language_preference:
language = request.user.language_preference四、常见问题解决
翻译不生效:
- 检查
LOCALE_PATHS配置 - 确保
.mo文件已编译 - 重启开发服务器
- 检查
缺少翻译字符串:
- 重新运行
makemessages - 检查代码中是否使用了正确的翻译函数
- 重新运行
URL 语言前缀问题:
- 确保使用
i18n_patterns - 检查
LocaleMiddleware顺序
- 确保使用
性能优化:
- 使用缓存存储翻译
- 避免在循环中进行翻译
五、工作流程总结
- 开发阶段:使用
gettext()和{% trans %}标记所有用户可见文本 - 提取阶段:使用
makemessages生成.po文件 - 翻译阶段:翻译人员编辑
.po文件 - 编译阶段:使用
compilemessages生成.mo文件 - 部署阶段:配置服务器,确保语言中间件正常工作
- 维护阶段:更新翻译时重复步骤 2-4
这样,Django 就能根据用户的语言偏好自动提供相应语言的界面和内容了。
(來自deepseek)