diff --git a/django/contrib/humanize/templatetags/humanize.py b/django/contrib/humanize/templatetags/humanize.py index 31880846f0..18a53adbe4 100644 --- a/django/contrib/humanize/templatetags/humanize.py +++ b/django/contrib/humanize/templatetags/humanize.py @@ -140,7 +140,8 @@ def intword(value): except (TypeError, ValueError): return value - if value < 1000000: + abs_value = abs(value) + if abs_value < 1000000: return value def _check_for_i18n(value, float_formatted, string_formatted): @@ -156,10 +157,10 @@ def intword(value): for exponent, converters in intword_converters: large_number = 10 ** exponent - if value < large_number * 1000: + if abs_value < large_number * 1000: new_value = value / large_number rounded_value = round_away_from_one(new_value) - return _check_for_i18n(new_value, *converters(rounded_value)) + return _check_for_i18n(new_value, *converters(abs(rounded_value))) return value diff --git a/docs/ref/contrib/humanize.txt b/docs/ref/contrib/humanize.txt index edbdb136b0..8914ef8de7 100644 --- a/docs/ref/contrib/humanize.txt +++ b/docs/ref/contrib/humanize.txt @@ -66,6 +66,7 @@ Examples: * ``1000000`` becomes ``1.0 million``. * ``1200000`` becomes ``1.2 million``. * ``1200000000`` becomes ``1.2 billion``. +* ``-1200000000`` becomes ``-1.2 billion``. Values up to 10^100 (Googol) are supported. @@ -75,12 +76,17 @@ e.g. with the ``'de'`` language: * ``1000000`` becomes ``'1,0 Million'``. * ``1200000`` becomes ``'1,2 Millionen'``. * ``1200000000`` becomes ``'1,2 Milliarden'``. +* ``-1200000000`` becomes ``'-1,2 Milliarden'``. .. versionchanged:: 3.0 All numeric values are now translated as plural, except ``1.0`` which is translated as a singular phrase. This may be incorrect for some languages. +.. versionchanged:: 3.1 + + Support for negative integers was added. + .. templatefilter:: naturalday ``naturalday`` diff --git a/docs/releases/3.1.txt b/docs/releases/3.1.txt index bbde94a34e..278752db90 100644 --- a/docs/releases/3.1.txt +++ b/docs/releases/3.1.txt @@ -77,6 +77,11 @@ Minor features * Added the :class:`~django.contrib.gis.db.models.functions.AsWKB` and :class:`~django.contrib.gis.db.models.functions.AsWKT` functions. +:mod:`django.contrib.humanize` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* :tfilter:`intword` template filter now supports negative integers. + :mod:`django.contrib.messages` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/humanize_tests/tests.py b/tests/humanize_tests/tests.py index 7396c417ab..a0d16bbfed 100644 --- a/tests/humanize_tests/tests.py +++ b/tests/humanize_tests/tests.py @@ -99,19 +99,27 @@ class HumanizeTests(SimpleTestCase): self.humanize_tester([100], ['100'], 'intcomma') def test_intword(self): - test_list = ( + # Positive integers. + test_list_positive = ( '100', '1000000', '1200000', '1290000', '1000000000', '2000000000', '6000000000000', '1300000000000000', '3500000000000000000000', - '8100000000000000000000000000000000', None, ('1' + '0' * 100), + '8100000000000000000000000000000000', ('1' + '0' * 100), ('1' + '0' * 104), ) - result_list = ( + result_list_positive = ( '100', '1.0 million', '1.2 million', '1.3 million', '1.0 billion', '2.0 billion', '6.0 trillion', '1.3 quadrillion', '3.5 sextillion', - '8.1 decillion', None, '1.0 googol', ('1' + '0' * 104), + '8.1 decillion', '1.0 googol', ('1' + '0' * 104), ) + # Negative integers. + test_list_negative = ('-' + test for test in test_list_positive) + result_list_negative = ('-' + result for result in result_list_positive) with translation.override('en'): - self.humanize_tester(test_list, result_list, 'intword') + self.humanize_tester( + (*test_list_positive, *test_list_negative, None), + (*result_list_positive, *result_list_negative, None), + 'intword', + ) def test_i18n_intcomma(self): test_list = (100, 1000, 10123, 10311, 1000000, 1234567.25, @@ -123,17 +131,25 @@ class HumanizeTests(SimpleTestCase): self.humanize_tester(test_list, result_list, 'intcomma') def test_i18n_intword(self): - test_list = ( + # Positive integers. + test_list_positive = ( '100', '1000000', '1200000', '1290000', '1000000000', '2000000000', '6000000000000', ) - result_list = ( + result_list_positive = ( '100', '1,0 Million', '1,2 Millionen', '1,3 Millionen', '1,0 Milliarde', '2,0 Milliarden', '6,0 Billionen', ) + # Negative integers. + test_list_negative = ('-' + test for test in test_list_positive) + result_list_negative = ('-' + result for result in result_list_positive) with self.settings(USE_L10N=True, USE_THOUSAND_SEPARATOR=True): with translation.override('de'): - self.humanize_tester(test_list, result_list, 'intword') + self.humanize_tester( + (*test_list_positive, *test_list_negative), + (*result_list_positive, *result_list_negative), + 'intword', + ) def test_apnumber(self): test_list = [str(x) for x in range(1, 11)]