【发布时间】:2011-12-14 05:59:11
【问题描述】:
我有一个这样的模板:
{% trans "Log out" %}
这是由 Django 自动翻译成西班牙语的 Terminar sesión。不过我想把它翻译成Cerar sesión。
我已尝试将此文字添加到 .po 文件中,但是当我编译消息时收到一条错误消息,提示此文字重复。
有没有办法改变/覆盖默认的 Django 翻译?
谢谢。
【问题讨论】:
标签: django internationalization
我有一个这样的模板:
{% trans "Log out" %}
这是由 Django 自动翻译成西班牙语的 Terminar sesión。不过我想把它翻译成Cerar sesión。
我已尝试将此文字添加到 .po 文件中,但是当我编译消息时收到一条错误消息,提示此文字重复。
有没有办法改变/覆盖默认的 Django 翻译?
谢谢。
【问题讨论】:
标签: django internationalization
这对我有用:
在您的应用文件夹中创建一个文件,该文件将保存需要覆盖其翻译的 django 消息,例如django_standard_messages.py
在 django lib 文件夹或django.po 文件中找到需要覆盖的消息(字符串),例如django.forms/fields.py 有消息 _(u"This field is required."),我们希望将其翻译成不同的德语
在django_standard_messages.py 中添加所有此类消息,如下所示:
# coding: utf-8 _ = lambda s: s django_standard_messages_to_override = [ _("This field is required."), ... ]
makemessages,compilemessages) - makemessages 将在您的应用程序 .po 文件中添加添加的 django 标准消息,找到它们并翻译,运行 compilemessages 以更新 .mo 文件背后的逻辑:(我认为;)) - 当ugettext函数搜索翻译一条消息(字符串)时,有几个.po/@ 987654331@ 需要搜索的文件。 使用第一个匹配项。因此,如果我们的本地应用程序 .po/.mo 在该顺序中排在第一位,我们的翻译将覆盖所有其他应用程序(例如 django 默认)。
当您需要翻译全部或大部分 django 默认消息时,另一种可能性(我没有尝试过)是复制 默认的 django .po 文件在我们的语言环境或其他一些特殊文件夹中,并修复翻译并将 LOCALE_PATHS django settings 文件中的文件夹(如果新)注册为列表中的第一个条目。
背后的逻辑:与上一节中提到的非常相似。
【讨论】:
基于Robert Lujo answer,他的替代方案完全有效。并且 IMO 更简单(仅将覆盖的语言环境保留在特殊的 .po 文件中)。步骤如下:
为 LOCALE_PATHS Django 设置添加一个额外的路径。
LOCALE_PATHS = (
# 默认的,makemessages 命令将在其中生成文件 os.path.join(BASE_DIR, 'myproject', 'locale'),
# 我们新的扩展语言环境目录
os.path.join(BASE_DIR, 'myproject', 'locale_extra'), )
找到要翻译的原始 Django(或第 3 方)字符串
msgstr "最近的操作"
msgstr "上次操作"
【讨论】:
makemessages 会将应用程序的字符串放入该“自定义”语言环境文件夹并将您的“新”自定义翻译放入 cmets。您必须在您的应用程序外部(例如在您的“全局应用程序”目录中)创建一个新文件夹。
最简单的方法是收集在 django.contrib.admin 语言环境文件夹中找到的 .po 文件并重新编译它(您可以使用 POEdit 这样做)。
您也可以覆盖 django.contrib.admin 模板,方法是将它们放在项目模板文件夹中(例如:yourproject/templates/admin/change_form.html),然后从项目根目录运行 makemessages(尽管不再支持这对于 django 1.4 alpha,如果我是正确的)
编辑:Robert Lujo 的答案是干净的方法
【讨论】:
这是我们部署的另一个解决方案。它涉及猴子修补DjangoTranslation 类的_add_installed_apps_translations 方法,以将项目应用程序的翻译优先于Django 应用程序的翻译。
# patches.py
from __future__ import absolute_import, unicode_literals
import os
from django.apps import apps
from django.core.exceptions import AppRegistryNotReady
from django.utils.translation.trans_real import DjangoTranslation
def patchDjangoTranslation():
"""
Patch Django to prioritize the project's app translations over
its own. Fixes GitLab issue #734 for Django 1.11.
Might needs to be updated for future Django versions.
"""
def _add_installed_apps_translations_new(self):
"""Merges translations from each installed app."""
try:
# Django apps
app_configs = [
app for app in apps.get_app_configs() if app.name.startswith('django.')
]
# Non Django apps
app_configs = [
app for app in apps.get_app_configs() if not app.name.startswith('django.')
]
app_configs = reversed(app_configs)
except AppRegistryNotReady:
raise AppRegistryNotReady(
"The translation infrastructure cannot be initialized before the "
"apps registry is ready. Check that you don't make non-lazy "
"gettext calls at import time.")
for app_config in app_configs:
localedir = os.path.join(app_config.path, 'locale')
if os.path.exists(localedir):
translation = self._new_gnu_trans(localedir)
self.merge(translation)
DjangoTranslation._add_installed_apps_translations = _add_installed_apps_translations_new
然后在你的主应用的.ready()方法中,调用patchDjangoTranslation:
from .patches import patchDjangoTranslation
class CommonApp(MayanAppConfig):
app_namespace = 'common'
app_url = ''
has_rest_api = True
has_tests = True
name = 'mayan.apps.common'
verbose_name = _('Common')
def ready(self):
super(CommonApp, self).ready()
patchDjangoTranslation() # Apply patch
主要变化是以下几行:
# Django apps
app_configs = [
app for app in apps.get_app_configs() if app.name.startswith('django.')
]
# Non Django apps
app_configs = [
app for app in apps.get_app_configs() if not app.name.startswith('django.')
]
app_configs = reversed(app_configs)
原文是:
app_configs = reversed(list(apps.get_app_configs()))
此块不是按照应用程序在INSTALLED_APPS 设置中出现的顺序来解释应用程序的翻译,而是输出将项目应用程序放在 Django 应用程序之前的应用程序列表。由于这只发生在确定要使用的翻译时,它不会影响代码的任何其他部分,也不需要进行其他更改。
它适用于 Django 版本 1.11 到 2.2。
【讨论】: