diff --git a/django/contrib/auth/password_validation.py b/django/contrib/auth/password_validation.py
index 2af5202207..aba2d6f1cf 100644
--- a/django/contrib/auth/password_validation.py
+++ b/django/contrib/auth/password_validation.py
@@ -10,9 +10,10 @@ from django.core.exceptions import ImproperlyConfigured, ValidationError
from django.utils import lru_cache
from django.utils._os import upath
from django.utils.encoding import force_text
+from django.utils.functional import lazy
from django.utils.html import format_html
from django.utils.module_loading import import_string
-from django.utils.six import string_types
+from django.utils.six import string_types, text_type
from django.utils.translation import ugettext as _, ungettext
@@ -77,7 +78,7 @@ def password_validators_help_texts(password_validators=None):
return help_texts
-def password_validators_help_text_html(password_validators=None):
+def _password_validators_help_text_html(password_validators=None):
"""
Return an HTML string with all help texts of all configured validators
in an
.
@@ -85,6 +86,7 @@ def password_validators_help_text_html(password_validators=None):
help_texts = password_validators_help_texts(password_validators)
help_items = [format_html('- {}
', help_text) for help_text in help_texts]
return '' % ''.join(help_items) if help_items else ''
+password_validators_help_text_html = lazy(_password_validators_help_text_html, text_type)
class MinimumLengthValidator(object):
diff --git a/docs/releases/1.9.7.txt b/docs/releases/1.9.7.txt
index c93339a9d2..0a969d6609 100644
--- a/docs/releases/1.9.7.txt
+++ b/docs/releases/1.9.7.txt
@@ -11,3 +11,6 @@ Bugfixes
* Removed the need for the ``request`` context processor on the admin login
page to fix a regression in 1.9 (:ticket:`26558`).
+
+* Fixed translation of password validators' ``help_text`` in forms
+ (:ticket:`26544`).
diff --git a/tests/auth_tests/test_forms.py b/tests/auth_tests/test_forms.py
index ac23c2e96a..d77c9a976b 100644
--- a/tests/auth_tests/test_forms.py
+++ b/tests/auth_tests/test_forms.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import datetime
@@ -350,6 +351,23 @@ class SetPasswordFormTest(TestDataMixin, TestCase):
self.assertEqual(form.cleaned_data['new_password1'], data['new_password1'])
self.assertEqual(form.cleaned_data['new_password2'], data['new_password2'])
+ @override_settings(AUTH_PASSWORD_VALIDATORS=[
+ {'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'},
+ {'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 'OPTIONS': {
+ 'min_length': 12,
+ }},
+ ])
+ def test_help_text_translation(self):
+ french_help_texts = [
+ 'Votre mot de passe ne peut pas trop ressembler à vos autres informations personnelles.',
+ 'Votre mot de passe doit contenir au minimum 12 caractères.',
+ ]
+ form = SetPasswordForm(self.u1)
+ with translation.override('fr'):
+ html = form.as_p()
+ for french_text in french_help_texts:
+ self.assertIn(french_text, html)
+
class PasswordChangeFormTest(TestDataMixin, TestCase):