
在构建支持多语言的django网站时,经常会遇到需要翻译模型中charfield或integerfield字段的choices选项值的情况。直接在模板中使用{% blocktranslate %}{{ variable }}{% endblocktranslate %}来翻译动态变量(如each_order.status)往往无法达到预期效果,因为blocktranslate期望的是静态字符串或已标记为可翻译的字符串。django为此提供了更为优雅和推荐的解决方案,即结合使用textchoices、gettext_lazy和get_foo_display方法。
核心问题分析当模型字段定义了choices选项时,例如:
class Order_product(models.Model):
# ...
status = models.CharField(max_length = 255, choices = [('Pending', 'Pending'), ('Need-Delivery', 'Need-Delivery'), ...]) 在模板中直接显示{{ each_order.status }}会输出原始的英文值(如'Pending')。如果尝试用blocktranslate包裹它,Django的makemessages工具可能会生成一个包含%(each_order.status)s的msgid,这表明它将变量视为一个插值,而不是一个可以直接翻译的字符串,导致翻译失效。
解决方案:TextChoices 与 get_FOO_displayDjango 3.0及更高版本推荐使用TextChoices(或IntegerChoices)来定义模型字段的选项。这种方式不仅使代码更具可读性,还与Django的国际化(i18n)功能更好地集成。
1. 定义可翻译的Choices首先,我们需要在模型中定义可翻译的choices。这通过django.utils.translation.gettext_lazy(通常别名为_)来实现。gettext_lazy会延迟翻译字符串,直到它们被实际使用时,这对于模型定义非常重要,因为它避免了在应用启动时就加载所有翻译。
修改 models.py 如下:
from django.db import models
from django.utils.translation import gettext_lazy as _
class OrderStatus(models.TextChoices):
PENDING = "Pending", _("Pending")
NEED_DELIVERY = "Need-Delivery", _("Need-Delivery")
DELIVERY = "Delivery", _("Delivery")
SUCCESS = "Success", _("Success")
RETURN_ORDER = "Return-Order", _("Return-Order")
CANCEL = "Cancel", _("Cancel")
class Order_product(models.Model):
name = models.CharField(max_length=255)
note = models.TextField()
status = models.CharField(
max_length=255,
choices=OrderStatus.choices,
default=OrderStatus.PENDING # 可以设置默认值
)
def __str__(self):
return f"{self.name} - {self.get_status_display()}" 在上述代码中:
- 我们创建了一个OrderStatus枚举类,它继承自models.TextChoices。
- 每个枚举成员的第二个元素都通过_()函数包裹,将其标记为可翻译字符串。
- Order_product模型中的status字段现在使用OrderStatus.choices作为其选项。
Django模型实例提供了一个便捷的方法来获取choices字段的“人类可读”表示,这个方法命名约定是get_FOO_display,其中FOO是字段的名称。例如,对于status字段,这个方法就是get_status_display()。这个方法会自动返回当前活动语言环境下的翻译值。
修改 test.html 如下:
Teleporthq
一体化AI网站生成器,能够快速设计和部署静态网站
182
查看详情
{% load i18n %} {# 确保加载i18n标签 #}
{% for each_order in get_order %}
<p>
{{ each_order.get_status_display }}
</p>
{% endfor %} 注意,这里不再需要{% blocktranslate %}标签,因为get_status_display方法本身就负责返回已翻译的字符串。
3. 视图层保持不变views.py 中的逻辑无需改变,因为它只是简单地获取模型实例并传递给模板:
from django.shortcuts import render
from .models import Order_product # 导入具体的模型
def test(request):
get_order = Order_product.objects.all()
return render(request, 'test/test.html', {'get_order': get_order}) 4. 生成和编译翻译文件
完成上述修改后,需要更新Django的翻译文件:
-
生成翻译消息文件:
运行以下命令来扫描项目中的可翻译字符串,并更新.po文件:
python manage.py makemessages -l vi # 替换'vi'为你的目标语言代码
执行此命令后,在locale/vi/LC_MESSAGES/django.po文件中,你会找到类似这样的条目:
msgid "Pending" msgstr ""
-
添加翻译:
打开django.po文件,为msgid对应的字符串添加msgstr翻译。例如:
msgid "Pending" msgstr "待处理" # 越南语可能是 "Đang chờ" 或其他
msgid "Success" msgstr "成功" # 越南语可能是 "Thành công"
-
编译翻译文件:
保存django.po文件后,运行以下命令编译翻译文件,使其生效:
python manage.py compilemessages
确保你的settings.py中包含了LocaleMiddleware,它是处理语言切换的关键:
# settings.py
MIDDLEWARE = [
# ...
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware', # 确保在 SessionMiddleware 之后,CommonMiddleware 之前
'django.middleware.common.CommonMiddleware',
# ...
]
# 定义支持的语言
LANGUAGES = [
('en', _('English')),
('vi', _('Vietnamese')),
# ... 其他语言
]
# 定义翻译文件查找路径
LOCALE_PATHS = [
BASE_DIR / 'locale',
] 注意事项与总结
- TextChoices的优势: TextChoices不仅提供了更好的代码组织和可读性,还与Django的国际化系统无缝集成,是定义模型选项的推荐方式。
- gettext_lazy的重要性: 使用gettext_lazy而不是gettext(或_()的直接调用)来标记choices字符串,可以避免在应用启动时过早地进行翻译,这在某些情况下是必要的。
- get_FOO_display方法: 这是获取choices字段翻译值的标准方法,它会自动处理当前语言环境,无需手动在模板中进行翻译。
- 翻译流程: 记住makemessages -> 编辑.po -> compilemessages的完整流程,以确保所有翻译都已正确生成和加载。
- LocaleMiddleware: 它是Django处理HTTP请求中语言偏好的核心组件,必须正确配置。
通过采用TextChoices结合get_FOO_display的方法,Django开发者可以高效且优雅地实现模型choices字段的国际化,确保在多语言环境下用户能够看到正确翻译的选项值。这种方法避免了在模板中直接处理动态翻译的复杂性,使代码更加清晰和易于维护。
以上就是Django中模型Choices字段的动态翻译实践指南的详细内容,更多请关注知识资源分享宝库其它相关文章!
相关标签: python html go 工具 session 多语言 django django 中间件 html 枚举类型 字符串 继承 http 大家都在看: Python单元测试:正确Mock类方法中条件分支的内部函数调用 Python zip对象行为解析:迭代器的一次性遍历特性与多重使用策略 Python高效处理超大XML文件:使用ElementTree流式解析 python如何处理命令行选项和参数_python命令行参数处理模块argparse详解 Python处理超大型XML文件:使用ElementTree进行高效流式解析






发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。