【问题标题】:Override default Django translations覆盖默认的 Django 翻译
【发布时间】:2011-12-14 05:59:11
【问题描述】:

我有一个这样的模板:

{% trans "Log out" %}

这是由 Django 自动翻译成西班牙语的 Terminar sesión。不过我想把它翻译成Cerar sesión

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

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

谢谢。

【问题讨论】:

    标签: django internationalization


    【解决方案1】:

    这对我有用:

    • 在您的应用文件夹中创建一个文件,该文件将保存需要覆盖其翻译的 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函数搜索翻译一条消息(字符串)时,有几个.po/@ 987654331@ 需要搜索的文件。 使用第一个匹配项。因此,如果我们的本地应用程序 .po/.mo 在该顺序中排在第一位,我们的翻译将覆盖所有其他应用程序(例如 django 默认)。

    另类

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

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

    【讨论】:

    • 这是一个很好的答案,因为它保持包不变并且代码最少。 (而且它有效。)
    • 我只是将我的应用程序的语言环境路径放在我的设置中的 LOCALE_PATHS 元组中,它似乎可以覆盖所有默认字符串。
    • 谢谢!这是非常好的解决方案。它适用于我(django 1.9)。
    【解决方案2】:

    基于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 方)字符串

    • 使用替代翻译添加新的 .po 文件“myproject/locale_extra/en/LC_MESSAGES/django.po”:
      • msgstr "最近的操作"
        msgstr "上次操作"

    • 照常编译您的消息

    【讨论】:

    • 我已经尝试了这两种解决方案,恕我直言,这是最好和最干净的答案。 [10 0 万后更新]:你会被警告。不要将您的“自定义”语言环境文件夹创建到应用程序中,否则makemessages 会将应用程序的字符串放入该“自定义”语言环境文件夹并将您的“新”自定义翻译放入 cmets。您必须在您的应用程序外部(例如在您的“全局应用程序”目录中)创建一个新文件夹。
    【解决方案3】:

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

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

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-20
        • 2017-04-26
        • 2014-01-05
        • 2012-03-15
        相关资源
        最近更新 更多