Ugettext_lazy - app1 передает сообщения django в app2. Сообщения не переводятся в app2, строки переводятся в app1

Я управляю двумя приложениями django, созданными третьими лицами.

Одно из этих приложений управляет пользовательским интерфейсом (app-ui), а другое является внутренним приложением (app-api).

Теперь app-api использует django messages. Язык по умолчанию - английский, автор сделал переводы на итальянский. Переводы собраны в файле app-api/apps/sub_app1/locale/it/LC_MESSAGES/django.po.

Функция django, используемая для управления переведенными сообщениями - ugettext_lazy

from django.utils.translation import ugettext_lazy as _

Кроме того, у app-api есть и другие приложения. Одно из них - sub_app. В нем есть модели, определенные в sub_app1/models.py, а также некоторые проверки данных.

Среди них есть и такой:

if client.status != ACTIVE:
            raise ValidationError(_(f'customer {customer.name} not active'))

Когда пользователь переходит по app-ui, он отправляет запросы к app-api, и если вышеуказанное условие выполняется, возникает ValidationError, и сообщение об ошибке 'customer {customer.name} not active' передается в app-ui, который показывает его в верхней части окна.

Я добавил и изменил переводы для app-api в app-api/apps/sub_app1/locale/it/LC_MESSAGES/django.po, запустил django-admin makemessages и django-admin compilemessages, изменил настройки браузера на запрос страниц на итальянском языке, и получил все отмеченные строки, успешно переведенные в app-api.

Однако строки, которые выводятся как сообщения django в app-ui, не переводятся, они по-прежнему на английском, даже если они помечены так же, как и другие строки.

В чем проблема и как я могу ее решить?

Объяснение

Интерполирование строк с помощью Formatted String Literals портит встроенный в django механизм перевода, поскольку строки форматируются до того, как gettext_lazy просматривает их как msgids.

Итак, в строку подставляются значения переменных, затем она передается в gettext_lazy, который ищет в файле django.po msgid строку, содержащую значения переменных, и не находит совпадений.

Примеры

Пример:

f'customer {customer.name} not active'

отформатирован как

"customer John Doe not active"

и затем ищется по gettext_lazy в файле django.po, который ожидает найти его среди msgids.

Чтобы избежать этого, мы хотим, чтобы строки заменялись значениями переменных после того, как gettext_lazy их просмотрит.

Мы можем добиться этого, отформатировав строки с помощью метода формата строки

Пример:

"customer {} not active".format(customer.name)

впервые просматривается gettext_lazy как

"customer {} not active"

найден в django.po среди msgid, и поэтому переведен в

"cliente {} non abilitato"

и только после этого форматируется в

"cliente John Doe non abilitato"

Исправление примера

Так что я решил эту проблему путем

#1 добавление в заголовок каждого запроса app-ui к app-ui, пары ключ-значение

'Accept-Language': 'it-IT'  # also tryed with 'Accept-Language': 'it'

#2 заменяя

if client.status != ACTIVE:
            raise ValidationError(_(f'customer {customer.name} not active'))

с

if client.status != ACTIVE:
            raise ValidationError(_("customer {} not active").format({customer.name}))

ЗАМЕТКА

это не так

if client.status != ACTIVE:
            raise ValidationError(_("customer {} not active".format({customer.name})))

.format после закрывающей кавычки),
это

if client.status != ACTIVE:
            raise ValidationError(_("customer {} not active").format({customer.name}))

.format после закрывающей скобки gettext_lazy)

потому что мы хотим форматировать сообщения только после их перевода, а не до него.

Вернуться на верх