Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Ungettext-related issues: #19158, #19034 #462

Closed
wants to merge 1 commit into from

1 participant

@uruz

ungettext is wrapped in lambdas, because we don't know the number at the time of definition.

@uruz

Commit db278c3 reverted corresponding changes, so this pull request is probably no longer makes any sense

@uruz uruz closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Oct 23, 2012
  1. @uruz
This page is out of date. Refresh to see the latest.
View
21 django/core/validators.py
@@ -7,7 +7,7 @@
from urlparse import urlsplit, urlunsplit
from django.core.exceptions import ValidationError
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import ugettext_lazy as _, ungettext_lazy
from django.utils.encoding import force_text
from django.utils.ipv6 import is_valid_ipv6_address
from django.utils import six
@@ -183,15 +183,26 @@ class MinValueValidator(BaseValidator):
code = 'min_value'
-class MinLengthValidator(BaseValidator):
+class MessageFunctionValidator(BaseValidator):
+ def __call__(self, value):
+ if self.message is None:
+ self.message = self.message_function(self.limit_value)
+ return super(MessageFunctionValidator, self).__call__(value)
+
+
+class MinLengthValidator(MessageFunctionValidator):
compare = lambda self, a, b: a < b
clean = lambda self, x: len(x)
- message = _('Ensure this value has at least %(limit_value)d characters (it has %(show_value)d).')
+ message_function = lambda self, n: ungettext_lazy('Ensure this value has at least %(limit_value)d character (it has %(show_value)d).',
+ 'Ensure this value has at least %(limit_value)d characters (it has %(show_value)d).', n)
+ message = None
code = 'min_length'
-class MaxLengthValidator(BaseValidator):
+class MaxLengthValidator(MessageFunctionValidator):
compare = lambda self, a, b: a > b
clean = lambda self, x: len(x)
- message = _('Ensure this value has at most %(limit_value)d characters (it has %(show_value)d).')
+ message_function = lambda self, n: ungettext_lazy('Ensure this value has at most %(limit_value)d character (it has %(show_value)d).',
+ 'Ensure this value has at most %(limit_value)d characters (it has %(show_value)d).', n)
code = 'max_length'
+ message = None
View
14 django/db/models/fields/files.py
@@ -10,7 +10,7 @@
from django.db.models import signals
from django.utils.encoding import force_str, force_text
from django.utils import six
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import ugettext_lazy as _, ungettext_lazy
class FieldFile(File):
def __init__(self, instance, field, name):
@@ -208,7 +208,8 @@ def __set__(self, instance, value):
class FileField(Field):
default_error_messages = {
- 'max_length': _('Filename is %(extra)d characters too long.')
+ 'max_length': lambda n: ungettext_lazy('Filename is %(extra)d character too long.',
+ 'Filename is %(extra)d characters too long.', n)
}
# The class to wrap instance attributes in. Accessing the file object off
@@ -249,8 +250,13 @@ def validate(self, value, model_instance):
filename = self.generate_filename(model_instance, value.name)
length = len(filename)
if self.max_length and length > self.max_length:
- error_values = {'extra': length - self.max_length}
- raise ValidationError(self.error_messages['max_length'] % error_values)
+ extra = length - self.max_length
+ error_values = {'extra': extra}
+ if callable(self.error_messages['max_length']):
+ error_text = self.error_messages['max_length'](extra) % error_values
+ else:
+ error_text = self.error_messages['max_length'] % error_values
+ raise ValidationError(error_text)
def get_internal_type(self):
return "FileField"
View
6 tests/modeltests/files/models.py
@@ -15,6 +15,11 @@
temp_storage_location = tempfile.mkdtemp()
temp_storage = FileSystemStorage(location=temp_storage_location)
+class FileFieldSubclass(models.FileField):
+ default_error_messages = {
+ 'max_length': 'Filename is %(extra)d character too long.'
+ }
+
class Storage(models.Model):
def custom_upload_to(self, filename):
return 'foo'
@@ -28,3 +33,4 @@ def random_upload_to(self, filename):
custom = models.FileField(storage=temp_storage, upload_to=custom_upload_to)
random = models.FileField(storage=temp_storage, upload_to=random_upload_to, max_length=16)
default = models.FileField(storage=temp_storage, upload_to='tests', default='tests/default.txt')
+ subclass = FileFieldSubclass(storage=temp_storage, upload_to=random_upload_to, max_length=16)
View
17 tests/modeltests/files/tests.py
@@ -10,6 +10,7 @@
from django.core.files.base import ContentFile
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase
+from django.test.utils import str_prefix
from django.utils import unittest
from .models import Storage, temp_storage, temp_storage_location
@@ -114,7 +115,21 @@ def test_max_length(self):
s1.full_clean()
with self.assertRaises(ValidationError):
Storage(random=SimpleUploadedFile(13 * 'x', b"content")).full_clean()
-
+ #Check for i18n and pluralization: singular form
+ self.assertRaisesRegexp(ValidationError, str_prefix(r"^{'random': \[%(_)s'Filename is 1 character too long\.'\]}$"),
+ Storage(random=SimpleUploadedFile(13 * 'x', b"content")).full_clean)
+ #and plural form
+ self.assertRaisesRegexp(ValidationError, str_prefix(r"^{'random': \[%(_)s'Filename is 2 characters too long\.'\]}$"),
+ Storage(random=SimpleUploadedFile(14 * 'x', b"content")).full_clean)
+
+ # Check that subclass which overrides default_error_messages['max_length']
+ # with a string behave exactly the same as usual FileField
+ s1 = Storage(subclass=SimpleUploadedFile(12 * 'x', b"content"))
+ s1.full_clean()
+ with self.assertRaises(ValidationError):
+ Storage(subclass=SimpleUploadedFile(13 * 'x', b"content")).full_clean()
+ self.assertRaisesRegexp(ValidationError, str_prefix(r"^{'subclass': \[%(_)s'Filename is 1 character too long\.'\]}$"),
+ Storage(subclass=SimpleUploadedFile(13 * 'x', b"content")).full_clean)
# Ticket #18515: validation for an already saved file should not check
# against a regenerated file name (and potentially raise a ValidationError
# if max_length is exceeded
View
38 tests/modeltests/validators/tests.py
@@ -9,6 +9,7 @@
from django.core.validators import *
from django.test.utils import str_prefix
from django.utils.unittest import TestCase
+from django.utils.translation import ugettext
NOW = datetime.now()
@@ -214,6 +215,43 @@ def test_message_dict(self):
self.assertEqual(str(v), str_prefix("{%(_)s'first': %(_)s'First Problem'}"))
self.assertEqual(repr(v), str_prefix("ValidationError({%(_)s'first': %(_)s'First Problem'})"))
+
+class UngettextValidators(TestCase):
+ def test_min_length_validator(self):
+ class MinLengthValidatorString(MinLengthValidator):
+ message = 'The length of value should be at least %(limit_value)d, but your value is of length %(show_value)d.'
+ string_validator = MinLengthValidatorString(10)
+ self.assertRaisesRegexp(ValidationError, str_prefix("%(_)s'[The length of value should be at least 10, but your value is of length 4']"),
+ string_validator, 'aaa!')
+ class MinLengthValidatorFunction(MinLengthValidator):
+ message_function = lambda self, n: 'Wow, so long!' if n > 6 else 'Too short!'
+ function_validator = MinLengthValidatorFunction(10)
+ self.assertRaisesRegexp(ValidationError, str_prefix(r"[%(_)s'Too short]"), function_validator, 'Mouse')
+ self.assertRaisesRegexp(ValidationError, str_prefix(r"[%(_)s'Wow, so long]"), function_validator, 'Longcat')
+ default_validator = MinLengthValidator(10)
+ expected = ugettext('Ensure this value has at least %(limit_value)d characters (it has %(show_value)d)')
+ expected = expected % {'limit_value': 10, 'show_value': 8}
+ expected = str_prefix(r"[%%(_)s'%s']" % expected)
+ self.assertRaisesRegexp(ValidationError, expected, default_validator, 'Shortcat')
+
+ def test_max_length_validator(self):
+ class MaxLengthValidatorString(MaxLengthValidator):
+ message = 'The length of value SHOULD NOT BE OVER %(limit_value)d, but your value TOO LONG: %(show_value)d.'
+ string_validator = MaxLengthValidatorString(5)
+ self.assertRaisesRegexp(ValidationError, str_prefix("%(_)s'[The length of value SHOULD NOT BE OVER 10, but your value TOO LONG: 36']"),
+ string_validator, 'Hippopotomonstrosesquippedaliophobia')
+ class MaxLengthValidatorFunction(MaxLengthValidator):
+ message_function = lambda self, n: 'Long enough' if n > 13 else 'A bit shorty'
+ function_validator = MaxLengthValidatorFunction(10)
+ self.assertRaisesRegexp(ValidationError, str_prefix("[%(_)s'Long enough]"), function_validator, 'Hippopotomonstrosesquippedaliophobia')
+ self.assertRaisesRegexp(ValidationError, str_prefix("[%(_)s'A bit shorty]"), function_validator, 'hippopotamus')
+ default_validator = MaxLengthValidator(10)
+ expected = ugettext('Ensure this value has at least %(limit_value)d characters (it has %(show_value)d)')
+ expected = expected % {'limit_value': 10, 'show_value': 8}
+ expected = str_prefix("[%%(_)s'%s']" % expected)
+ self.assertRaisesRegexp(ValidationError, expected, default_validator, 'Shortcat')
+
+
test_counter = 0
for validator, value, expected in TEST_DATA:
name, method = create_simple_test_method(validator, expected, value, test_counter)
Something went wrong with that request. Please try again.