Fixed #6392 -- Made django.contrib.humanize template tags locale aware. Thanks, Dave McLain.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16168 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Jannis Leidel 2011-05-06 13:29:58 +00:00
parent 7dd72360a2
commit 8f3e1c1c63
7 changed files with 207 additions and 49 deletions

View File

@ -4,7 +4,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Django\n" "Project-Id-Version: Django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-03-15 13:18-0400\n" "POT-Creation-Date: 2011-05-06 14:14+0200\n"
"PO-Revision-Date: 2011-03-04 18:39+0000\n" "PO-Revision-Date: 2011-03-04 18:39+0000\n"
"Last-Translator: Jannis <jannis@leidel.info>\n" "Last-Translator: Jannis <jannis@leidel.info>\n"
"Language-Team: German <>\n" "Language-Team: German <>\n"
@ -14,87 +14,135 @@ msgstr ""
"Language: de\n" "Language: de\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: templatetags/humanize.py:19 #: templatetags/humanize.py:21
msgid "th" msgid "th"
msgstr "." msgstr "."
#: templatetags/humanize.py:19 #: templatetags/humanize.py:21
msgid "st" msgid "st"
msgstr "." msgstr "."
#: templatetags/humanize.py:19 #: templatetags/humanize.py:21
msgid "nd" msgid "nd"
msgstr "." msgstr "."
#: templatetags/humanize.py:19 #: templatetags/humanize.py:21
msgid "rd" msgid "rd"
msgstr "." msgstr "."
#: templatetags/humanize.py:54 #: templatetags/humanize.py:68
#, python-format #, python-format
msgid "%(value).1f million" msgid "%(value).1f million"
msgid_plural "%(value).1f million" msgid_plural "%(value).1f million"
msgstr[0] "%(value).1f Million" msgstr[0] "%(value).1f Million"
msgstr[1] "%(value).1f Millionen" msgstr[1] "%(value).1f Millionen"
#: templatetags/humanize.py:57 #: templatetags/humanize.py:69
#, python-format
msgid "%(value)s million"
msgid_plural "%(value)s million"
msgstr[0] "%(value)s Million"
msgstr[1] "%(value)s Millionen"
#: templatetags/humanize.py:74
#, python-format #, python-format
msgid "%(value).1f billion" msgid "%(value).1f billion"
msgid_plural "%(value).1f billion" msgid_plural "%(value).1f billion"
msgstr[0] "%(value).1f Milliarde" msgstr[0] "%(value).1f Milliarde"
msgstr[1] "%(value).1f Milliarden" msgstr[1] "%(value).1f Milliarden"
#: templatetags/humanize.py:60 #: templatetags/humanize.py:75
#, python-format
msgid "%(value)s billion"
msgid_plural "%(value)s billion"
msgstr[0] "%(value)s Milliarde"
msgstr[1] "%(value)s Milliarden"
#: templatetags/humanize.py:80
#, python-format #, python-format
msgid "%(value).1f trillion" msgid "%(value).1f trillion"
msgid_plural "%(value).1f trillion" msgid_plural "%(value).1f trillion"
msgstr[0] "%(value).1f Billion" msgstr[0] "%(value).1f Billion"
msgstr[1] "%(value).1f Billionen" msgstr[1] "%(value).1f Billionen"
#: templatetags/humanize.py:76 #: templatetags/humanize.py:81
#, python-format
msgid "%(value)s trillion"
msgid_plural "%(value)s trillion"
msgstr[0] "%(value)s Billion"
msgstr[1] "%(value)s Billionen"
#: templatetags/humanize.py:98
msgid "one" msgid "one"
msgstr "ein" msgstr "ein"
#: templatetags/humanize.py:76 #: templatetags/humanize.py:98
msgid "two" msgid "two"
msgstr "zwei" msgstr "zwei"
#: templatetags/humanize.py:76 #: templatetags/humanize.py:98
msgid "three" msgid "three"
msgstr "drei" msgstr "drei"
#: templatetags/humanize.py:76 #: templatetags/humanize.py:98
msgid "four" msgid "four"
msgstr "vier" msgstr "vier"
#: templatetags/humanize.py:76 #: templatetags/humanize.py:98
msgid "five" msgid "five"
msgstr "fünf" msgstr "fünf"
#: templatetags/humanize.py:76 #: templatetags/humanize.py:98
msgid "six" msgid "six"
msgstr "sechs" msgstr "sechs"
#: templatetags/humanize.py:76 #: templatetags/humanize.py:98
msgid "seven" msgid "seven"
msgstr "sieben" msgstr "sieben"
#: templatetags/humanize.py:76 #: templatetags/humanize.py:98
msgid "eight" msgid "eight"
msgstr "acht" msgstr "acht"
#: templatetags/humanize.py:76 #: templatetags/humanize.py:98
msgid "nine" msgid "nine"
msgstr "neun" msgstr "neun"
#: templatetags/humanize.py:96 #: templatetags/humanize.py:121
msgid "today" msgid "today"
msgstr "heute" msgstr "heute"
#: templatetags/humanize.py:98 #: templatetags/humanize.py:123
msgid "tomorrow" msgid "tomorrow"
msgstr "morgen" msgstr "morgen"
#: templatetags/humanize.py:100 #: templatetags/humanize.py:125
msgid "yesterday" msgid "yesterday"
msgstr "gestern" msgstr "gestern"
#: templatetags/humanize.py:147
msgid "now"
msgstr ""
#: templatetags/humanize.py:149
#, python-format
msgid "%s seconds ago"
msgstr ""
#: templatetags/humanize.py:151
msgid "a minute ago"
msgstr ""
#: templatetags/humanize.py:153
#, python-format
msgid "%s minutes ago"
msgstr ""
#: templatetags/humanize.py:155
msgid "an hour ago"
msgstr ""
#: templatetags/humanize.py:157
#, python-format
msgid "%s hours ago"
msgstr ""

View File

@ -4,7 +4,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Django\n" "Project-Id-Version: Django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-03-15 13:18-0400\n" "POT-Creation-Date: 2011-05-06 14:14+0200\n"
"PO-Revision-Date: 2010-05-13 15:35+0200\n" "PO-Revision-Date: 2010-05-13 15:35+0200\n"
"Last-Translator: Django team\n" "Last-Translator: Django team\n"
"Language-Team: English <en@li.org>\n" "Language-Team: English <en@li.org>\n"
@ -12,87 +12,135 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
#: templatetags/humanize.py:19 #: templatetags/humanize.py:21
msgid "th" msgid "th"
msgstr "" msgstr ""
#: templatetags/humanize.py:19 #: templatetags/humanize.py:21
msgid "st" msgid "st"
msgstr "" msgstr ""
#: templatetags/humanize.py:19 #: templatetags/humanize.py:21
msgid "nd" msgid "nd"
msgstr "" msgstr ""
#: templatetags/humanize.py:19 #: templatetags/humanize.py:21
msgid "rd" msgid "rd"
msgstr "" msgstr ""
#: templatetags/humanize.py:54 #: templatetags/humanize.py:68
#, python-format #, python-format
msgid "%(value).1f million" msgid "%(value).1f million"
msgid_plural "%(value).1f million" msgid_plural "%(value).1f million"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: templatetags/humanize.py:57 #: templatetags/humanize.py:69
#, python-format
msgid "%(value)s million"
msgid_plural "%(value)s million"
msgstr[0] ""
msgstr[1] ""
#: templatetags/humanize.py:74
#, python-format #, python-format
msgid "%(value).1f billion" msgid "%(value).1f billion"
msgid_plural "%(value).1f billion" msgid_plural "%(value).1f billion"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: templatetags/humanize.py:60 #: templatetags/humanize.py:75
#, python-format
msgid "%(value)s billion"
msgid_plural "%(value)s billion"
msgstr[0] ""
msgstr[1] ""
#: templatetags/humanize.py:80
#, python-format #, python-format
msgid "%(value).1f trillion" msgid "%(value).1f trillion"
msgid_plural "%(value).1f trillion" msgid_plural "%(value).1f trillion"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: templatetags/humanize.py:76 #: templatetags/humanize.py:81
#, python-format
msgid "%(value)s trillion"
msgid_plural "%(value)s trillion"
msgstr[0] ""
msgstr[1] ""
#: templatetags/humanize.py:98
msgid "one" msgid "one"
msgstr "" msgstr ""
#: templatetags/humanize.py:76 #: templatetags/humanize.py:98
msgid "two" msgid "two"
msgstr "" msgstr ""
#: templatetags/humanize.py:76 #: templatetags/humanize.py:98
msgid "three" msgid "three"
msgstr "" msgstr ""
#: templatetags/humanize.py:76 #: templatetags/humanize.py:98
msgid "four" msgid "four"
msgstr "" msgstr ""
#: templatetags/humanize.py:76 #: templatetags/humanize.py:98
msgid "five" msgid "five"
msgstr "" msgstr ""
#: templatetags/humanize.py:76 #: templatetags/humanize.py:98
msgid "six" msgid "six"
msgstr "" msgstr ""
#: templatetags/humanize.py:76 #: templatetags/humanize.py:98
msgid "seven" msgid "seven"
msgstr "" msgstr ""
#: templatetags/humanize.py:76 #: templatetags/humanize.py:98
msgid "eight" msgid "eight"
msgstr "" msgstr ""
#: templatetags/humanize.py:76 #: templatetags/humanize.py:98
msgid "nine" msgid "nine"
msgstr "" msgstr ""
#: templatetags/humanize.py:96 #: templatetags/humanize.py:121
msgid "today" msgid "today"
msgstr "" msgstr ""
#: templatetags/humanize.py:98 #: templatetags/humanize.py:123
msgid "tomorrow" msgid "tomorrow"
msgstr "" msgstr ""
#: templatetags/humanize.py:100 #: templatetags/humanize.py:125
msgid "yesterday" msgid "yesterday"
msgstr "" msgstr ""
#: templatetags/humanize.py:147
msgid "now"
msgstr ""
#: templatetags/humanize.py:149
#, python-format
msgid "%s seconds ago"
msgstr ""
#: templatetags/humanize.py:151
msgid "a minute ago"
msgstr ""
#: templatetags/humanize.py:153
#, python-format
msgid "%s minutes ago"
msgstr ""
#: templatetags/humanize.py:155
msgid "an hour ago"
msgstr ""
#: templatetags/humanize.py:157
#, python-format
msgid "%s hours ago"
msgstr ""

View File

@ -1,7 +1,9 @@
from django.utils.translation import ungettext, ugettext as _ from django.utils.translation import ungettext, ugettext as _
from django.utils.encoding import force_unicode from django.utils.encoding import force_unicode
from django.utils.formats import number_format
from django import template from django import template
from django.template import defaultfilters from django.template import defaultfilters
from django.conf import settings
from datetime import date, datetime from datetime import date, datetime
import re import re
@ -23,17 +25,25 @@ def ordinal(value):
ordinal.is_safe = True ordinal.is_safe = True
register.filter(ordinal) register.filter(ordinal)
def intcomma(value): def intcomma(value, use_l10n=True):
""" """
Converts an integer to a string containing commas every three digits. Converts an integer to a string containing commas every three digits.
For example, 3000 becomes '3,000' and 45000 becomes '45,000'. For example, 3000 becomes '3,000' and 45000 becomes '45,000'.
""" """
if settings.USE_L10N and use_l10n:
try:
if not isinstance(value, float):
value = int(value)
except (TypeError, ValueError):
return intcomma(value, False)
else:
return number_format(value)
orig = force_unicode(value) orig = force_unicode(value)
new = re.sub("^(-?\d+)(\d{3})", '\g<1>,\g<2>', orig) new = re.sub("^(-?\d+)(\d{3})", '\g<1>,\g<2>', orig)
if orig == new: if orig == new:
return new return new
else: else:
return intcomma(new) return intcomma(new, use_l10n)
intcomma.is_safe = True intcomma.is_safe = True
register.filter(intcomma) register.filter(intcomma)
@ -49,15 +59,33 @@ def intword(value):
return value return value
if value < 1000000: if value < 1000000:
return value return value
def _check_for_i18n(value, float_formatted, string_formatted):
"""
Use the i18n enabled defaultfilters.floatformat if possible
"""
if settings.USE_L10N:
return defaultfilters.floatformat(value, 1), string_formatted
return value, float_formatted
if value < 1000000000: if value < 1000000000:
new_value = value / 1000000.0 new_value = value / 1000000.0
return ungettext('%(value).1f million', '%(value).1f million', new_value) % {'value': new_value} 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: if value < 1000000000000:
new_value = value / 1000000000.0 new_value = value / 1000000000.0
return ungettext('%(value).1f billion', '%(value).1f billion', new_value) % {'value': new_value} 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: if value < 1000000000000000:
new_value = value / 1000000000000.0 new_value = value / 1000000000000.0
return ungettext('%(value).1f trillion', '%(value).1f trillion', new_value) % {'value': new_value} 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}
return value return value
intword.is_safe = False intword.is_safe = False
register.filter(intword) register.filter(intword)

View File

@ -43,6 +43,12 @@ Examples:
* ``450000`` becomes ``450,000``. * ``450000`` becomes ``450,000``.
* ``4500000`` becomes ``4,500,000``. * ``4500000`` becomes ``4,500,000``.
:ref:`Format localization <format-localization>` will be respected if enabled,
e.g. with the ``'de'`` language:
* ``45000`` becomes ``'45.000'``.
* ``450000`` becomes ``'450.000'``.
You can pass in either an integer or a string representation of an integer. You can pass in either an integer or a string representation of an integer.
.. templatefilter:: intword .. templatefilter:: intword
@ -61,6 +67,13 @@ Examples:
Values up to 1000000000000000 (one quadrillion) are supported. Values up to 1000000000000000 (one quadrillion) are supported.
:ref:`Format localization <format-localization>` will be respected if enabled,
e.g. with the ``'de'`` language:
* ``1000000`` becomes ``'1,0 Million'``.
* ``1200000`` becomes ``'1,2 Million'``.
* ``1200000000`` becomes ``'1,2 Milliarden'``.
You can pass in either an integer or a string representation of an integer. You can pass in either an integer or a string representation of an integer.
.. templatefilter:: naturalday .. templatefilter:: naturalday

View File

@ -1,10 +1,13 @@
from datetime import timedelta, date, datetime, tzinfo, timedelta from datetime import timedelta, date, datetime, tzinfo, timedelta
from django.conf import settings
from django.template import Template, Context, add_to_builtins from django.template import Template, Context, add_to_builtins
from django.utils import unittest from django.test import TestCase
from django.utils import translation
from django.utils.dateformat import DateFormat from django.utils.dateformat import DateFormat
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.utils.html import escape from django.utils.html import escape
from django.conf import settings
add_to_builtins('django.contrib.humanize.templatetags.humanize') add_to_builtins('django.contrib.humanize.templatetags.humanize')
@ -26,7 +29,7 @@ class FixedOffset(tzinfo):
return timedelta(0) return timedelta(0)
class HumanizeTests(unittest.TestCase): class HumanizeTests(TestCase):
def humanize_tester(self, test_list, result_list, method): def humanize_tester(self, test_list, result_list, method):
# Using max below ensures we go through both lists # Using max below ensures we go through both lists
@ -60,14 +63,31 @@ class HumanizeTests(unittest.TestCase):
def test_intword(self): def test_intword(self):
test_list = ('100', '1000000', '1200000', '1290000', test_list = ('100', '1000000', '1200000', '1290000',
'1000000000','2000000000','6000000000000', '1000000000', '2000000000', '6000000000000',
None) None)
result_list = ('100', '1.0 million', '1.2 million', '1.3 million', result_list = ('100', '1.0 million', '1.2 million', '1.3 million',
'1.0 billion', '2.0 billion', '6.0 trillion', '1.0 billion', '2.0 billion', '6.0 trillion',
None) None)
self.humanize_tester(test_list, result_list, 'intword') self.humanize_tester(test_list, result_list, 'intword')
def test_i18n_intcomma(self):
test_list = (100, 1000, 10123, 10311, 1000000, 1234567.25,
'100', '1000', '10123', '10311', '1000000', None)
result_list = ('100', '1.000', '10.123', '10.311', '1.000.000', '1.234.567,25',
'100', '1.000', '10.123', '10.311', '1.000.000', None)
with self.settings(USE_L10N=True, USE_THOUSAND_SEPARATOR=True):
with translation.override('de'):
self.humanize_tester(test_list, result_list, 'intcomma')
def test_i18n_intword(self):
test_list = ('100', '1000000', '1200000', '1290000',
'1000000000','2000000000','6000000000000')
result_list = ('100', '1,0 Million', '1,2 Millionen', '1,3 Millionen',
'1,0 Milliarde', '2,0 Milliarden', '6,0 Billionen')
with self.settings(USE_L10N=True, USE_THOUSAND_SEPARATOR=True):
with translation.override('de'):
self.humanize_tester(test_list, result_list, 'intword')
def test_apnumber(self): def test_apnumber(self):
test_list = [str(x) for x in range(1, 11)] test_list = [str(x) for x in range(1, 11)]
test_list.append(None) test_list.append(None)

View File

@ -28,6 +28,7 @@ ALWAYS_INSTALLED_APPS = [
'django.contrib.admin', 'django.contrib.admin',
'django.contrib.admindocs', 'django.contrib.admindocs',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'django.contrib.humanize',
] ]
def geodjango(settings): def geodjango(settings):