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
просматривает их как msgid
s.
Итак, в строку подставляются значения переменных, затем она передается в gettext_lazy
, который ищет в файле django.po msgid
строку, содержащую значения переменных, и не находит совпадений.
Примеры
Пример:
f'customer {customer.name} not active'
отформатирован как
"customer John Doe not active"
и затем ищется по gettext_lazy
в файле django.po, который ожидает найти его среди msgid
s.
Чтобы избежать этого, мы хотим, чтобы строки заменялись значениями переменных после того, как 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
)
потому что мы хотим форматировать сообщения только после их перевода, а не до него.