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 ""
"Project-Id-Version: Django\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"
"Last-Translator: Jannis <jannis@leidel.info>\n"
"Language-Team: German <>\n"
@ -14,87 +14,135 @@ msgstr ""
"Language: de\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: templatetags/humanize.py:19
#: templatetags/humanize.py:21
msgid "th"
msgstr "."
#: templatetags/humanize.py:19
#: templatetags/humanize.py:21
msgid "st"
msgstr "."
#: templatetags/humanize.py:19
#: templatetags/humanize.py:21
msgid "nd"
msgstr "."
#: templatetags/humanize.py:19
#: templatetags/humanize.py:21
msgid "rd"
msgstr "."
#: templatetags/humanize.py:54
#: templatetags/humanize.py:68
#, python-format
msgid "%(value).1f million"
msgid_plural "%(value).1f million"
msgstr[0] "%(value).1f Million"
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
msgid "%(value).1f billion"
msgid_plural "%(value).1f billion"
msgstr[0] "%(value).1f Milliarde"
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
msgid "%(value).1f trillion"
msgid_plural "%(value).1f trillion"
msgstr[0] "%(value).1f Billion"
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"
msgstr "ein"
#: templatetags/humanize.py:76
#: templatetags/humanize.py:98
msgid "two"
msgstr "zwei"
#: templatetags/humanize.py:76
#: templatetags/humanize.py:98
msgid "three"
msgstr "drei"
#: templatetags/humanize.py:76
#: templatetags/humanize.py:98
msgid "four"
msgstr "vier"
#: templatetags/humanize.py:76
#: templatetags/humanize.py:98
msgid "five"
msgstr "fünf"
#: templatetags/humanize.py:76
#: templatetags/humanize.py:98
msgid "six"
msgstr "sechs"
#: templatetags/humanize.py:76
#: templatetags/humanize.py:98
msgid "seven"
msgstr "sieben"
#: templatetags/humanize.py:76
#: templatetags/humanize.py:98
msgid "eight"
msgstr "acht"
#: templatetags/humanize.py:76
#: templatetags/humanize.py:98
msgid "nine"
msgstr "neun"
#: templatetags/humanize.py:96
#: templatetags/humanize.py:121
msgid "today"
msgstr "heute"
#: templatetags/humanize.py:98
#: templatetags/humanize.py:123
msgid "tomorrow"
msgstr "morgen"
#: templatetags/humanize.py:100
#: templatetags/humanize.py:125
msgid "yesterday"
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 ""
"Project-Id-Version: Django\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"
"Last-Translator: Django team\n"
"Language-Team: English <en@li.org>\n"
@ -12,87 +12,135 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: templatetags/humanize.py:19
#: templatetags/humanize.py:21
msgid "th"
msgstr ""
#: templatetags/humanize.py:19
#: templatetags/humanize.py:21
msgid "st"
msgstr ""
#: templatetags/humanize.py:19
#: templatetags/humanize.py:21
msgid "nd"
msgstr ""
#: templatetags/humanize.py:19
#: templatetags/humanize.py:21
msgid "rd"
msgstr ""
#: templatetags/humanize.py:54
#: templatetags/humanize.py:68
#, python-format
msgid "%(value).1f million"
msgid_plural "%(value).1f million"
msgstr[0] ""
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
msgid "%(value).1f billion"
msgid_plural "%(value).1f billion"
msgstr[0] ""
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
msgid "%(value).1f trillion"
msgid_plural "%(value).1f trillion"
msgstr[0] ""
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"
msgstr ""
#: templatetags/humanize.py:76
#: templatetags/humanize.py:98
msgid "two"
msgstr ""
#: templatetags/humanize.py:76
#: templatetags/humanize.py:98
msgid "three"
msgstr ""
#: templatetags/humanize.py:76
#: templatetags/humanize.py:98
msgid "four"
msgstr ""
#: templatetags/humanize.py:76
#: templatetags/humanize.py:98
msgid "five"
msgstr ""
#: templatetags/humanize.py:76
#: templatetags/humanize.py:98
msgid "six"
msgstr ""
#: templatetags/humanize.py:76
#: templatetags/humanize.py:98
msgid "seven"
msgstr ""
#: templatetags/humanize.py:76
#: templatetags/humanize.py:98
msgid "eight"
msgstr ""
#: templatetags/humanize.py:76
#: templatetags/humanize.py:98
msgid "nine"
msgstr ""
#: templatetags/humanize.py:96
#: templatetags/humanize.py:121
msgid "today"
msgstr ""
#: templatetags/humanize.py:98
#: templatetags/humanize.py:123
msgid "tomorrow"
msgstr ""
#: templatetags/humanize.py:100
#: templatetags/humanize.py:125
msgid "yesterday"
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.encoding import force_unicode
from django.utils.formats import number_format
from django import template
from django.template import defaultfilters
from django.conf import settings
from datetime import date, datetime
import re
@ -23,17 +25,25 @@ def ordinal(value):
ordinal.is_safe = True
register.filter(ordinal)
def intcomma(value):
def intcomma(value, use_l10n=True):
"""
Converts an integer to a string containing commas every three digits.
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)
new = re.sub("^(-?\d+)(\d{3})", '\g<1>,\g<2>', orig)
if orig == new:
return new
else:
return intcomma(new)
return intcomma(new, use_l10n)
intcomma.is_safe = True
register.filter(intcomma)
@ -49,15 +59,33 @@ def intword(value):
return value
if value < 1000000:
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:
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:
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:
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
intword.is_safe = False
register.filter(intword)

View File

@ -43,6 +43,12 @@ Examples:
* ``450000`` becomes ``450,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.
.. templatefilter:: intword
@ -61,6 +67,13 @@ Examples:
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.
.. templatefilter:: naturalday

View File

@ -1,10 +1,13 @@
from datetime import timedelta, date, datetime, tzinfo, timedelta
from django.conf import settings
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.translation import ugettext as _
from django.utils.html import escape
from django.conf import settings
add_to_builtins('django.contrib.humanize.templatetags.humanize')
@ -26,7 +29,7 @@ class FixedOffset(tzinfo):
return timedelta(0)
class HumanizeTests(unittest.TestCase):
class HumanizeTests(TestCase):
def humanize_tester(self, test_list, result_list, method):
# Using max below ensures we go through both lists
@ -60,14 +63,31 @@ class HumanizeTests(unittest.TestCase):
def test_intword(self):
test_list = ('100', '1000000', '1200000', '1290000',
'1000000000','2000000000','6000000000000',
'1000000000', '2000000000', '6000000000000',
None)
result_list = ('100', '1.0 million', '1.2 million', '1.3 million',
'1.0 billion', '2.0 billion', '6.0 trillion',
None)
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):
test_list = [str(x) for x in range(1, 11)]
test_list.append(None)

View File

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