Commit 6cae2a55 authored by Jannis Leidel's avatar Jannis Leidel
Browse files

Fixed #16878 -- Improved intword filter to support numbers up to decillion and...

Fixed #16878 -- Improved intword filter to support numbers up to decillion and googol. Thanks to crodjer for the initial patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16897 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 33ad413c
Loading
Loading
Loading
Loading
+150 −37
Original line number Diff line number Diff line
@@ -4,14 +4,27 @@ msgid ""
msgstr ""
"Project-Id-Version: Django\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-05-16 17:30+0200\n"
"POT-Creation-Date: 2011-09-23 17:43+0200\n"
"PO-Revision-Date: 2010-05-13 15:35+0200\n"
"Last-Translator: Django team\n"
"Language-Team: English <en@li.org>\n"
"Language: en\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#: tests.py:101 templatetags/humanize.py:170
msgid "today"
msgstr ""

#: tests.py:101 templatetags/humanize.py:174
msgid "yesterday"
msgstr ""

#: tests.py:101 templatetags/humanize.py:172
msgid "tomorrow"
msgstr ""

#: templatetags/humanize.py:25
msgid "th"
msgstr ""
@@ -28,148 +41,248 @@ msgstr ""
msgid "rd"
msgstr ""

#: templatetags/humanize.py:78
#: templatetags/humanize.py:57
#, python-format
msgid "%(value).1f million"
msgid_plural "%(value).1f million"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:79
#: templatetags/humanize.py:58
#, python-format
msgid "%(value)s million"
msgid_plural "%(value)s million"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:84
#: templatetags/humanize.py:61
#, python-format
msgid "%(value).1f billion"
msgid_plural "%(value).1f billion"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:85
#: templatetags/humanize.py:62
#, python-format
msgid "%(value)s billion"
msgid_plural "%(value)s billion"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:90
#: templatetags/humanize.py:65
#, python-format
msgid "%(value).1f trillion"
msgid_plural "%(value).1f trillion"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:91
#: templatetags/humanize.py:66
#, python-format
msgid "%(value)s trillion"
msgid_plural "%(value)s trillion"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:108
#: templatetags/humanize.py:69
#, python-format
msgid "%(value).1f quadrillion"
msgid_plural "%(value).1f quadrillion"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:70
#, python-format
msgid "%(value)s quadrillion"
msgid_plural "%(value)s quadrillion"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:73
#, python-format
msgid "%(value).1f quintillion"
msgid_plural "%(value).1f quintillion"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:74
#, python-format
msgid "%(value)s quintillion"
msgid_plural "%(value)s quintillion"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:77
#, python-format
msgid "%(value).1f sextillion"
msgid_plural "%(value).1f sextillion"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:78
#, python-format
msgid "%(value)s sextillion"
msgid_plural "%(value)s sextillion"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:81
#, python-format
msgid "%(value).1f septillion"
msgid_plural "%(value).1f septillion"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:82
#, python-format
msgid "%(value)s septillion"
msgid_plural "%(value)s septillion"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:85
#, python-format
msgid "%(value).1f octillion"
msgid_plural "%(value).1f octillion"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:86
#, python-format
msgid "%(value)s octillion"
msgid_plural "%(value)s octillion"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:89
#, python-format
msgid "%(value).1f nonillion"
msgid_plural "%(value).1f nonillion"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:90
#, python-format
msgid "%(value)s nonillion"
msgid_plural "%(value)s nonillion"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:93
#, python-format
msgid "%(value).1f decillion"
msgid_plural "%(value).1f decillion"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:94
#, python-format
msgid "%(value)s decillion"
msgid_plural "%(value)s decillion"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:97
#, python-format
msgid "%(value).1f googol"
msgid_plural "%(value).1f googol"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:98
#, python-format
msgid "%(value)s googol"
msgid_plural "%(value)s googol"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:147
msgid "one"
msgstr ""

#: templatetags/humanize.py:108
#: templatetags/humanize.py:147
msgid "two"
msgstr ""

#: templatetags/humanize.py:108
#: templatetags/humanize.py:147
msgid "three"
msgstr ""

#: templatetags/humanize.py:108
#: templatetags/humanize.py:147
msgid "four"
msgstr ""

#: templatetags/humanize.py:108
#: templatetags/humanize.py:147
msgid "five"
msgstr ""

#: templatetags/humanize.py:108
#: templatetags/humanize.py:147
msgid "six"
msgstr ""

#: templatetags/humanize.py:108
#: templatetags/humanize.py:147
msgid "seven"
msgstr ""

#: templatetags/humanize.py:108
#: templatetags/humanize.py:147
msgid "eight"
msgstr ""

#: templatetags/humanize.py:108
#: templatetags/humanize.py:147
msgid "nine"
msgstr ""

#: templatetags/humanize.py:131
msgid "today"
msgstr ""

#: templatetags/humanize.py:133
msgid "tomorrow"
msgstr ""

#: templatetags/humanize.py:135
msgid "yesterday"
msgstr ""

#: templatetags/humanize.py:160
#: templatetags/humanize.py:199
#, python-format
msgctxt "naturaltime"
msgid "%(delta)s ago"
msgstr ""

#: templatetags/humanize.py:163 templatetags/humanize.py:185
#: templatetags/humanize.py:202 templatetags/humanize.py:224
msgid "now"
msgstr ""

#: templatetags/humanize.py:166
#: templatetags/humanize.py:205
#, python-format
msgid "a second ago"
msgid_plural "%(count)s seconds ago"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:171
#: templatetags/humanize.py:210
#, python-format
msgid "a minute ago"
msgid_plural "%(count)s minutes ago"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:176
#: templatetags/humanize.py:215
#, python-format
msgid "an hour ago"
msgid_plural "%(count)s hours ago"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:182
#: templatetags/humanize.py:221
#, python-format
msgctxt "naturaltime"
msgid "%(delta)s from now"
msgstr ""

#: templatetags/humanize.py:188
#: templatetags/humanize.py:227
#, python-format
msgid "a second from now"
msgid_plural "%(count)s seconds from now"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:193
#: templatetags/humanize.py:232
#, python-format
msgid "a minute from now"
msgid_plural "%(count)s minutes from now"
msgstr[0] ""
msgstr[1] ""

#: templatetags/humanize.py:198
#: templatetags/humanize.py:237
#, python-format
msgid "an hour from now"
msgid_plural "%(count)s hours from now"
+66 −27
Original line number Diff line number Diff line
@@ -4,7 +4,6 @@ from datetime import date, datetime, timedelta
from django import template
from django.conf import settings
from django.template import defaultfilters
from django.utils.datetime_safe import datetime, date
from django.utils.encoding import force_unicode
from django.utils.formats import number_format
from django.utils.translation import pgettext, ungettext, ugettext as _
@@ -13,6 +12,7 @@ from django.utils.tzinfo import LocalTimezone

register = template.Library()


def ordinal(value):
    """
    Converts an integer to its ordinal as a string. 1 is '1st', 2 is '2nd',
@@ -22,10 +22,10 @@ def ordinal(value):
        value = int(value)
    except (TypeError, ValueError):
        return value
    t = (_('th'), _('st'), _('nd'), _('rd'), _('th'), _('th'), _('th'), _('th'), _('th'), _('th'))
    suffixes = (_('th'), _('st'), _('nd'), _('rd'), _('th'), _('th'), _('th'), _('th'), _('th'), _('th'))
    if value % 100 in (11, 12, 13): # special case
        return u"%d%s" % (value, t[0])
    return u'%d%s' % (value, t[value % 10])
        return u"%d%s" % (value, suffixes[0])
    return u"%d%s" % (value, suffixes[value % 10])
ordinal.is_safe = True
register.filter(ordinal)

@@ -51,16 +51,65 @@ def intcomma(value, use_l10n=True):
intcomma.is_safe = True
register.filter(intcomma)

# A dictionary of standard large number to their converters
intword_converters = {
    6: lambda number: (
        ungettext('%(value).1f million', '%(value).1f million', number),
        ungettext('%(value)s million', '%(value)s million', number),
    ),
    9: lambda number: (
        ungettext('%(value).1f billion', '%(value).1f billion', number),
        ungettext('%(value)s billion', '%(value)s billion', number),
    ),
    12: lambda number: (
        ungettext('%(value).1f trillion', '%(value).1f trillion', number),
        ungettext('%(value)s trillion', '%(value)s trillion', number),
    ),
    15: lambda number: (
        ungettext('%(value).1f quadrillion', '%(value).1f quadrillion', number),
        ungettext('%(value)s quadrillion', '%(value)s quadrillion', number),
    ),
    18: lambda number: (
        ungettext('%(value).1f quintillion', '%(value).1f quintillion', number),
        ungettext('%(value)s quintillion', '%(value)s quintillion', number),
    ),
    21: lambda number: (
        ungettext('%(value).1f sextillion', '%(value).1f sextillion', number),
        ungettext('%(value)s sextillion', '%(value)s sextillion', number),
    ),
    24: lambda number: (
        ungettext('%(value).1f septillion', '%(value).1f septillion', number),
        ungettext('%(value)s septillion', '%(value)s septillion', number),
    ),
    27: lambda number: (
        ungettext('%(value).1f octillion', '%(value).1f octillion', number),
        ungettext('%(value)s octillion', '%(value)s octillion', number),
    ),
    30: lambda number: (
        ungettext('%(value).1f nonillion', '%(value).1f nonillion', number),
        ungettext('%(value)s nonillion', '%(value)s nonillion', number),
    ),
    33: lambda number: (
        ungettext('%(value).1f decillion', '%(value).1f decillion', number),
        ungettext('%(value)s decillion', '%(value)s decillion', number),
    ),
    100: lambda number: (
        ungettext('%(value).1f googol', '%(value).1f googol', number),
        ungettext('%(value)s googol', '%(value)s googol', number),
    ),
}

def intword(value):
    """
    Converts a large integer to a friendly text representation. Works best for
    numbers over 1 million. For example, 1000000 becomes '1.0 million', 1200000
    becomes '1.2 million' and '1200000000' becomes '1.2 billion'.
    Converts a large integer to a friendly text representation. Works best
    for numbers over 1 million. For example, 1000000 becomes '1.0 million',
    1200000 becomes '1.2 million' and '1200000000' becomes '1.2 billion'.
    """
    try:
        value = int(value)
    except (TypeError, ValueError):
        return value

    if value < 1000000:
        return value

@@ -69,27 +118,17 @@ def intword(value):
        Use the i18n enabled defaultfilters.floatformat if possible
        """
        if settings.USE_L10N:
            return defaultfilters.floatformat(value, 1), string_formatted
        return value, float_formatted
            value = defaultfilters.floatformat(value, 1)
            template = string_formatted
        else:
            template = float_formatted
        return template % {'value': value}

    if value < 1000000000:
        new_value = value / 1000000.0
        new_value, value_string = _check_for_i18n(new_value,
            ungettext('%(value).1f million', '%(value).1f million', new_value),
            ungettext('%(value)s million', '%(value)s million', new_value))
        return value_string % {'value': new_value}
    if value < 1000000000000:
        new_value = value / 1000000000.0
        new_value, value_string = _check_for_i18n(new_value,
            ungettext('%(value).1f billion', '%(value).1f billion', new_value),
            ungettext('%(value)s billion', '%(value)s billion', new_value))
        return value_string % {'value': new_value}
    if value < 1000000000000000:
        new_value = value / 1000000000000.0
        new_value, value_string = _check_for_i18n(new_value,
            ungettext('%(value).1f trillion', '%(value).1f trillion', new_value),
            ungettext('%(value)s trillion', '%(value)s trillion', new_value))
        return value_string % {'value': new_value}
    for exponent, converters in intword_converters.items():
        large_number = 10 ** exponent
        if value < large_number * 1000:
            new_value = value / float(large_number)
            return _check_for_i18n(new_value, *converters(new_value))
    return value
intword.is_safe = False
register.filter(intword)
+8 −6
Original line number Diff line number Diff line
from __future__ import with_statement
from datetime import timedelta, date, datetime, tzinfo
from datetime import timedelta, date, datetime

from django.template import Template, Context, add_to_builtins, defaultfilters
from django.test import TestCase
@@ -55,10 +55,12 @@ class HumanizeTests(TestCase):
    def test_intword(self):
        test_list = ('100', '1000000', '1200000', '1290000',
                     '1000000000', '2000000000', '6000000000000',
                     None)
                     '1300000000000000', '3500000000000000000000',
                     '8100000000000000000000000000000000', None)
        result_list = ('100', '1.0 million', '1.2 million', '1.3 million',
                       '1.0 billion', '2.0 billion', '6.0 trillion',
                       None)
                       '1.3 quadrillion', '3.5 sextillion',
                       '8.1 decillion', None)
        self.humanize_tester(test_list, result_list, 'intword')

    def test_i18n_intcomma(self):
+1 −1
Original line number Diff line number Diff line
@@ -65,7 +65,7 @@ Examples:
    * ``1200000`` becomes ``1.2 million``.
    * ``1200000000`` becomes ``1.2 billion``.

Values up to 1000000000000000 (one quadrillion) are supported.
Values up to 10^100 (Googol) are supported.

:ref:`Format localization <format-localization>` will be respected if enabled,
e.g. with the ``'de'`` language:
Loading