Как заставить фреймворк сообщений 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
. Для ответа мне нужно больше информации о представлении и шаблонах.
Я решил проблемы, и теперь сайт ведет себя последовательно и так, как ожидалось. Странное поведение было вызвано двумя проблемами:
- Порядок промежуточного программного обеспечения имеет значение.
- Позаботьтесь о том, чтобы любые пользовательские теги шаблона, используемые для установки или переключения языка сайта, не создавали побочных эффектов. См. этот ответ для этого конкретного вопроса.
Я установил промежуточное ПО на нижеуказанное, и сообщения и переводы теперь работают как ожидалось:
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",
]