From 8f3e1c1c63d3d3b36715afa9095e04142c4507e2 Mon Sep 17 00:00:00 2001 From: Jannis Leidel Date: Fri, 6 May 2011 13:29:58 +0000 Subject: [PATCH] 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 --- .../humanize/locale/de/LC_MESSAGES/django.mo | Bin 1222 -> 1505 bytes .../humanize/locale/de/LC_MESSAGES/django.po | 88 ++++++++++++++---- .../humanize/locale/en/LC_MESSAGES/django.po | 88 ++++++++++++++---- .../contrib/humanize/templatetags/humanize.py | 38 +++++++- docs/ref/contrib/humanize.txt | 13 +++ tests/regressiontests/humanize/tests.py | 28 +++++- tests/runtests.py | 1 + 7 files changed, 207 insertions(+), 49 deletions(-) diff --git a/django/contrib/humanize/locale/de/LC_MESSAGES/django.mo b/django/contrib/humanize/locale/de/LC_MESSAGES/django.mo index 1e2bcee3ed57aa108f9501498f0faf7e2ba6d773..1639f6ecbd0facb15b53fe959e901169a45bd439 100644 GIT binary patch literal 1505 zcmaiyyKfXR5XKFJM~?SfLLiI~kSN(>Hwh?g2ttGef;bUH2NHD7?cAQDJ#S?DE`*kr z5(*k<5EK-MjshVB1w}-chKB!v0?|>e;+&zKK6VAo`F9PZUujV9pE3&zaTc-v}H-}0I^vo4yW%1 z-T(G^{fO6(d7kjkx#wAM2jY7{Y<2-hCwK{bfZj*IUidH2gzI)N|L*k#a69}T zpuh6Pcy}l6{dU6KIsn@XbKhwfY-8Ya)j$ch8+Hg*fVp*K z3Al`|rpOx9U5u)HN@khN)qk~mo49tG)olVdh-O3GcFOwvhHq5bq+XForZvl|vPrC( zH#AcTQ&JJjVLD-knxvSK51Fyd*041Zvw0%saMp9J^I2wRb2dlDl6LZh&ZntjgYhJ| zN7~@xVt##Es5CE3(oC*xP%^1Zf@_V`1m!&Dg^4@mU__I!hz+g_OEK>YqbLY31mQ&< z4aCtvPuLfR2n;5vDP7K%xc(p<;L%{*f2k+LD%=*v24yXj$%M^y%x?*$q~Vv*26#0i znNU`gs+wOxuu2;urJzir9`hTd>q7C%R|=)^(&*|dM8&W$k}FFJspn?Uqos%T{7fdK z8se3j(1z^r-SSv4xEkkLsFDswRV7cPN@G4aCGASdm?u=2$QoK?!C0>ACgy5p(KW+; zLwxDyaF^nzhI!OoXc@qgn<1eSYOl6V>tgV_3HBO3@7h_v)@C%lwkFc>jpf&9t0}#> zru2%^l5Txj!&i%nikr}{A61n#C23Y^OJ5Vc&TOdl)!^+UOJ(VSp_zlfg;i zPl~$OIJXfOp)R(E(}4#bw;^M8{1c~UCwyq*GcR;t7x4wuVCMNN=QU*64Nmo2sQx?8 zKfrF{C#ZweQ$gy{L;kGHN4$*V0ail#1-*zl8%DArG=TKtLDYx-vwlzN;82Zfp&qru bN0gPDjbvslY0f3Hjj8GT%eb8jox;L5hK?w| diff --git a/django/contrib/humanize/locale/de/LC_MESSAGES/django.po b/django/contrib/humanize/locale/de/LC_MESSAGES/django.po index cf8bc220e3..8a7843bbc8 100644 --- a/django/contrib/humanize/locale/de/LC_MESSAGES/django.po +++ b/django/contrib/humanize/locale/de/LC_MESSAGES/django.po @@ -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 \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 "" diff --git a/django/contrib/humanize/locale/en/LC_MESSAGES/django.po b/django/contrib/humanize/locale/en/LC_MESSAGES/django.po index ca0bf76375..713f770520 100644 --- a/django/contrib/humanize/locale/en/LC_MESSAGES/django.po +++ b/django/contrib/humanize/locale/en/LC_MESSAGES/django.po @@ -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 \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 "" diff --git a/django/contrib/humanize/templatetags/humanize.py b/django/contrib/humanize/templatetags/humanize.py index eee2b4d4f9..a711145064 100644 --- a/django/contrib/humanize/templatetags/humanize.py +++ b/django/contrib/humanize/templatetags/humanize.py @@ -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) diff --git a/docs/ref/contrib/humanize.txt b/docs/ref/contrib/humanize.txt index 23b48dd5d3..aab6ff31b9 100644 --- a/docs/ref/contrib/humanize.txt +++ b/docs/ref/contrib/humanize.txt @@ -43,6 +43,12 @@ Examples: * ``450000`` becomes ``450,000``. * ``4500000`` becomes ``4,500,000``. +:ref:`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 ` 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 diff --git a/tests/regressiontests/humanize/tests.py b/tests/regressiontests/humanize/tests.py index ade0d1a4d4..b1f43bb90b 100644 --- a/tests/regressiontests/humanize/tests.py +++ b/tests/regressiontests/humanize/tests.py @@ -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) diff --git a/tests/runtests.py b/tests/runtests.py index 6b88c5d167..4253b05f2e 100755 --- a/tests/runtests.py +++ b/tests/runtests.py @@ -28,6 +28,7 @@ ALWAYS_INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.admindocs', 'django.contrib.staticfiles', + 'django.contrib.humanize', ] def geodjango(settings):