Как заставить фреймворк сообщений Django хорошо работать с i18n?

Используя django 4.0.6, я использовал фреймворк messages для отображения сообщений, когда пользователи успешно заполняли форму. Затем я добавил i18n:

Когда выбран язык по умолчанию, сообщения отображаются на втором экране после отправки формы, а не на первом.

Когда активен язык не по умолчанию, непереведенные сообщения отображаются на первом экране после создания сообщения (как и ожидалось).

Я пробовал использовать и gettext_lazy и gettext и это не помогло.

Это необычная ошибка, и я не уверен, что я сделал неправильно?

просмотров:

from django.utils.translation import gettext_lazy as _
from django.views.generic.edit import CreateView
...

class ContactView(SuccessMessageMixin, CreateView):

    template_name = "contact-form.html"
    form_class = ContactForm
    success_url = reverse_lazy("base:home")
    success_message = _("Thanks for contacting us.")

    def form_valid(self, form):
        if contact_form_filter(form):
            create_and_send_contact_form_email(form)
        return super().form_valid(form)

    def form_invalid(self, form):
        """If the form is invalid, render the invalid form."""
        return self.render_to_response(self.get_context_data(form=form))

настройки:

TIME_ZONE = "CET"
LANGUAGE_CODE = "en"
USE_I18N = True
WAGTAIL_I18N_ENABLED = True
USE_L10N = True  # Deprecated in Django 4, but still used in Wagtail I believe
USE_TZ = True

WAGTAIL_CONTENT_LANGUAGES = LANGUAGES = [
    ("en", _("English")),
    ("nl", _("Dutch")),
]

INSTALLED_APPS = [
    ...
    "django.contrib.messages",
    ...
]

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "corsheaders.middleware.CorsMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.locale.LocaleMiddleware",
    "django.middleware.cache.UpdateCacheMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.cache.FetchFromCacheMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
    "wagtail.contrib.redirects.middleware.RedirectMiddleware",
    "compression_middleware.middleware.CompressionMiddleware",
]

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [str(APPS_DIR / "built"), str(APPS_DIR / "templates")],
        "OPTIONS": {
            "loaders": [
                "django.template.loaders.filesystem.Loader",
                "django.template.loaders.app_directories.Loader",
            ],
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.template.context_processors.i18n",
                "django.template.context_processors.media",
                "django.template.context_processors.static",
                "django.template.context_processors.tz",
                "django.contrib.messages.context_processors.messages",
                "lettergun.utils.context_processors.settings_context",
                "lettergun.utils.context_processors.pass_",
                "lettergun.utils.context_processors.toggle_customer_testimonials",
            ],
        },
    }
]


Переводы вместе с сообщениями - очень интересная вещь.

Каждый message в словаре messages дождитесь собственного рендеринга через {{ messages }} в шаблоне.

Значит, если в следующем шаблоне нет этого тега - вы не сможете увидеть сообщения, они не могут быть отрисованы и должны подождать.

А lazy_translation - это wrapper, который ничего не делает, пока не будет вызвана функция str/unicode для этого перевода. В вашем случае - сообщение имеет lazy_translation, и они ждут render вызова.

Попробуем - выберите язык. Откройте от. Заполните форму. Нажмите Сохранить. Закройте браузер до того, как увидите ответ.

Ваши сообщения все еще ждут момента для саморендеринга. Lasy_translation тоже подождите.

Откройте браузер, откройте совершенно другую ссылку с другим языком. Если шаблон имеет {{ messages }}, вы увидите старое сообщение со старой информацией из другого вида с переводом на текущий язык.

Если вы измените lazy_translation на gettext - и выполните тот же процесс. Вы должны увидеть сообщение со старым языком.

Мое мнение. Каждый должен переопределить функцию get_success_message и обернуть super().get_success_message в str. Это сделает ожидаемое поведение переводов в сообщениях.

Следующий вопрос - почему вы не видите messages. Для ответа мне нужно больше информации о представлении и шаблонах.

Я решил проблемы, и теперь сайт ведет себя последовательно и так, как ожидалось. Странное поведение было вызвано двумя проблемами:

  1. Порядок промежуточного программного обеспечения имеет значение.
  2. Позаботьтесь о том, чтобы любые пользовательские теги шаблона, используемые для установки или переключения языка сайта, не создавали побочных эффектов. См. этот ответ для этого конкретного вопроса.

Я установил промежуточное ПО на нижеуказанное, и сообщения и переводы теперь работают как ожидалось:

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.middleware.http.ConditionalGetMiddleware",
    "django.middleware.cache.UpdateCacheMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "corsheaders.middleware.CorsMiddleware",
    "django.middleware.locale.LocaleMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
    "wagtail.contrib.redirects.middleware.RedirectMiddleware",
    "django.middleware.cache.FetchFromCacheMiddleware",
]

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