首页 > 解决方案 > 如何使用 Django 和 pgetttext() 在 .po 文件中获取 msgctxt

问题描述

我正在为具有英语和西班牙语的预订应用程序编写通知模块。它应该足够灵活以处理任何模型和任何状态变化(例如创建、更新、取消等)。

get_subject() 函数将使用相关对象的模型名称(例如约会)和状态动词为通知准备一个“主题”行。所以我们应该得到'Appointment 123ABC modified'或'Payment 789XYZ created'等。除了允许西班牙语单词的语法性别之外,我让它在翻译方面工作。因此,“Appointment 123ABC modified”将是“Cit a 123ABC actualizad a ”,而“Payment 123ABC modified”将是“Pag o 123ABC actualizad o ”。

我知道解决方案是在 .po 文件中使用 pgettext(context, string) 以及 msgctxt,但我只是不知道如何让 manage.py makemessages 在准备 .po 文件时添加 msgctxt .

我尝试了各种直接编辑 .po 的方法,但是在运行 compilemessages 时出现错误(执行 msgfmt 失败:backend/locale/es/LC_MESSAGES/django.po:3966:重复的消息定义......)并且 makemessages 只是覆盖无论如何我的编辑。

我不确定我需要的只是 po 文件的正确格式,还是我是否需要正确的方式让 makemessages 为我的情况正常工作。任何帮助将不胜感激。

class Notification(Uuidable, Timestampable):
    user = models.ForeignKey(User, related_name='notifications', verbose_name=_('notifications'), on_delete=models.CASCADE)
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, blank=True, null=True)
    object_id = models.UUIDField(blank=True, null=True)
    content_object = GenericForeignKey('content_type', 'object_id')
    subject = models.CharField(max_length=256, verbose_name=_('subject'))
    status_type = models.CharField(choices=NOTIFICACTION_STATUS_VERBS, max_length=256, verbose_name=_('status type'))
    details = models.TextField(null=True, blank=True, verbose_name=_('details'))
    read_at = models.DateTimeField(null=True, blank=True, verbose_name=_('read at'))
    email_sent_at = models.DateTimeField(null=True, blank=True, verbose_name=_('email sent at'))
    pusher_sent_at = models.DateTimeField(null=True, blank=True, verbose_name=_('pusher sent at'))

    def generate_subject(self):
        class_name = self.content_object._meta.verbose_name
        context = str(class_name).lower()

        with translation.override(self.user.locale.split('-')[0]):
            class_name_translated = translation.gettext(class_name).capitalize()
            status_translated = translation.pgettext(context, str(self.status_type))

        subject = f'{class_name_translated} {self.content_object.display_id} {status_translated}'
        return subject

    def __str__(self):
        return self.subject

    def get_email_template(self, template_type):
        return NOTIFICATION_EMAIL_TEMPLATES[self.content_object.__class__.__name__][self.status_type][template_type]

    def save(self, *args, **kwargs):
        self.subject = _(self.generate_subject())
        return super(Notification, self).save(*args, **kwargs)

标签: djangointernationalizationgettext

解决方案


来自的错误消息msgfmt表明您对.po文件中的 msgctxt 使用了错误的语法。它应该是这样的:

msgctxt "abbreviated_weekday"
msgid "Sun"
msgstr ""

但是您应该提取字符串而不是操作.po文件。解决方案是生成一个包含所有必需调用的虚拟源文件,pgettext()以便makemessages.

在您的代码中,对的调用pgettext()在变量中而不是字符串文字中具有消息上下文,并且此类调用当然会被xgettext().


推荐阅读