覆盖默认的Django翻译

时间:2011-10-24 15:28:19

标签: django internationalization

我有一个模板:

{% trans "Log out" %}

这是由Django自动翻译为Terminarsesión的西班牙语。但是,我想将其翻译为Cerrarsesión

我曾尝试将此文字添加到.po文件中,但是当我编译邮件时,我收到一条错误,说这个文字是重复的。

有没有办法更改/覆盖默认的Django翻译?

感谢。

4 个答案:

答案 0 :(得分:26)

这对我有用:

  • 在您的app文件夹中创建一个文件,该文件将保存需要覆盖翻译的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."),
...
]
  • 翻译文件(makemessagescompilemessages) - makemessages将在您的应用程序.po文件中添加添加的django标准消息,找到并翻译,运行compilemessages以更新.mo文件
  • 试用

背后的逻辑:(我认为;)) - 当 ugettext 函数搜索一条消息(字符串)的翻译时,有几个{{1需要搜索的/ .po个文件。 使用第一个匹配。因此,如果我们的本地应用.mo / .po按此顺序排在第一位,我们的翻译将覆盖所有其他应用(例如django默认值)。

替代

当您需要翻译所有或大部分django默认消息时,另一种可能性(我没有尝试)是复制我们的语言环境或其他特殊文件夹中的默认django .mo文件,修复翻译并将.po django LOCALE_PATHS文件中的文件夹(如果是新文件)注册为列表中的第一个条目。

背后的逻辑:与上一节中提到的非常相似。

答案 1 :(得分:5)

最简单的方法是收集django.contrib.admin语言环境文件夹中找到的.po文件并重新编译它(您可以使用POEdit执行此操作)。

您还可以通过将django.contrib.admin模板放入项目模板文件夹(例如:yourproject / templates / admin / change_form.html),然后从项目根目录运行makemessages来覆盖django.contrib.admin模板(尽管不再支持对于django 1.4 alpha,如果我是正确的)

编辑:Robert Lujo的回答是干净的方法

答案 2 :(得分:5)

基于Robert Lujo answer,他的选择完全正常。并且IMO更简单(仅将覆盖的语言环境保留在特殊的.po文件中)。以下是步骤:

  • 为LOCALE_PATHS Django设置添加额外路径。

    •   

      LOCALE_PATHS =(
           #默认值,makemessages命令将生成文件      os.path.join(BASE_DIR,'myproject','locale'),
           #our new,extended locale目录
           os.path.join(BASE_DIR,'myproject','locale_extra'),   )

  • 找到要翻译的原始Django(或第三方)字符串

  • 使用替代翻译添加新的.po文件“myproject / locale_extra / en / LC_MESSAGES / django.po”:
    •   msgstr“最近的行动”   msgstr“最后的行动”

  • 照常编译邮件

答案 3 :(得分:0)

这是我们部署的另一个解决方案。它涉及到猴子修补_add_installed_apps_translations类的DjangoTranslation方法的过程,以使项目应用程序的翻译优先于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。