覆盖默认的 Django 翻译

发布于 2024-12-12 02:09:19 字数 249 浏览 0 评论 0原文

我有一个这样的模板:

{% trans "Log out" %}

Django 自动将其翻译为西班牙语 Terminar sesión。不过我想将其翻译为Cerrar sesión

我尝试将此文字添加到 .po 文件中,但是在编译消息时收到一条错误消息,指出此文字重复。

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

谢谢。

I have a template with this:

{% trans "Log out" %}

This is translated automatically by Django to Spanish as Terminar sesión. However I would like to translate it as Cerrar sesión.

I have tried to add this literal to the .po file, however I get an error saying this literal is duplicated when I compile the messages.

Is there a way to change/override default Django translations?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

临走之时 2024-12-19 02:09:19

这对我有用:

  • 在您的应用程序文件夹中创建一个文件,该文件将保存需要覆盖翻译的 django 消息,例如 django_standard_messages.py

  • 在 django lib 文件夹或中django.po 文件找到需要覆盖的消息(字符串),例如 django.forms/fields.py 有消息 _(u"This field is必需的。”)我们想要以不同的方式翻译成德语

  • django_standard_messages 中将其以不同方式翻译为德语

    .py 添加所有此类消息,如下所示:

#编码:utf-8
_ = 拉姆达 s: s
django_standard_messages_to_override = [
_(“此字段是必需的。”),
...
]
  • 翻译文件(makemessagescompilemessages) - makemessages 将在您的应用程序 .po 文件中添加添加的 django 标准消息,找到它们并翻译,运行compilemessages 来更新 .mo 文件
  • 试用

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

当您需要翻译所有或大部分 django 默认消息时,另

一种可能性(我没有尝试过)是复制默认消息django .po 文件放在我们的语言环境或其他一些特殊文件夹中,并修复翻译并在 LOCALE_PATHS django settings 文件中注册文件夹(如果是新的)作为第一个条目 列表。

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

This is what worked for me:

  • create a file in your app folder which will hold django messages for which translations need to be overridden, e.g. django_standard_messages.py

  • in django lib folder or in django.po files find the message (string) that needs to be overridden, e.g. django.forms/fields.py has message _(u"This field is required.") which we want to translate to german differently

  • in django_standard_messages.py add all such messages like this:

# coding: utf-8
_ = lambda s: s
django_standard_messages_to_override = [
_("This field is required."),
...
]
  • Translate the file (makemessages, compilemessages) - makemessages will add added django standard messages in your application .po file, find them and translate, run compilemessages to update .mo file
  • tryout

The logic behind: (I think ;) ) - when ugettext function searches translation for one message (string), there are several .po/.mo files that needs to be searched through. The first match is used. So, if our local app .po/.mo is first in that order, our translations will override all other (e.g. django default).

Alternative

When you need to translate all or most of django default messages, the other possibility (which I didn't tried) is to copy default django .po file in our locale or some other special folder, and fix translations and register the folder (if new) in LOCALE_PATHS django settings file as first entry in the list.

The logic behind: is the very similar as noted in previous section.

幼儿园老大 2024-12-19 02:09:19

根据 Robert Lujo 的回答,他的替代方案完全有效。而且 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 方)字符串

  • 添加新的 .po 文件“myproject/locale_extra/en/LC_MESSAGES/django.po”以及替代翻译:
    • <块引用>

      msgstr "最近的操作"
      msgstr "最后的操作"

  • 照常编译您的消息

Based on Robert Lujo answer, his alternative is totally working. And IMO simpler (keep the overriden locales in a special .po file only). Here are the steps:

  • Add an extra path to the LOCALE_PATHS Django settings.

    • LOCALE_PATHS = (
      # the default one, where the makemessages command will generate the files
      os.path.join(BASE_DIR, 'myproject', 'locale'),
      # our new, extended locale dir
      os.path.join(BASE_DIR, 'myproject', 'locale_extra'),
      )

  • find the original Django (or 3rd party) string to be translated

  • Add the new .po file "myproject/locale_extra/en/LC_MESSAGES/django.po" with the alternative translation :
    • msgid "Recent actions"
      msgstr "Last actions"

  • Compile your messages as usual
安静 2024-12-19 02:09:19

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

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

编辑:罗伯特卢霍的答案是干净的方法

The easiest way is to collect the .po file found in the django.contrib.admin locale folder and re-compiling it (you can use POEdit for doing so).

You could also override the django.contrib.admin templates by putting them in your projects templates folder (for example: yourproject/templates/admin/change_form.html) then running makemessages from the project root (although this is no longer supported for django 1.4 alpha if i'm correct)

edit: Robert Lujo's answer is the clean method

橘味果▽酱 2024-12-19 02:09:19

这是我们部署的另一个解决方案。它涉及猴子修补 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。

This is another solution we deployed. It involved monkey patching the _add_installed_apps_translations method of the DjangoTranslation class to prioritize the translations of the project apps over the translations of the Django apps.

# 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

Then in the .ready() method of your main app, call 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

The main change are these lines:

        # 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)

The original are:

        app_configs = reversed(list(apps.get_app_configs()))

Instead of interpreting the translations of the apps in the order they appear in the INSTALLED_APPS setting, this block outputs the list of apps placing the project apps before the Django apps. Since this only happens when determining the translation to use, it doesn't affect any other part of the code and no other changes are necessary.

It works on Django version 1.11 up to 2.2.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文