Permalink
Browse files

Fixed #20246 -- Added non-breaking spaces between values an units

  • Loading branch information...
1 parent caf56ad commit 7d77e9786a118dd95a268872dd9d36664066b96a @EmilStenstrom EmilStenstrom committed with claudep May 18, 2013
View
@@ -536,6 +536,7 @@ answer newbie questions, and generally made Django that much better:
starrynight <cmorgh@gmail.com>
Vasiliy Stavenko <stavenko@gmail.com>
Thomas Steinacher <http://www.eggdrop.ch/>
+ Emil Stenström <em@kth.se>
Johan C. Stöver <johan@nilling.nl>
Nowell Strite <http://nowell.strite.org/>
Thomas Stromberg <tstromberg@google.com>
@@ -194,17 +194,20 @@ def naturaltime(value):
return _('now')
elif delta.seconds < 60:
return ungettext(
- 'a second ago', '%(count)s seconds ago', delta.seconds
+ # Translators: \\u00a0 is non-breaking space
+ 'a second ago', '%(count)s\u00a0seconds ago', delta.seconds
) % {'count': delta.seconds}
elif delta.seconds // 60 < 60:
count = delta.seconds // 60
return ungettext(
- 'a minute ago', '%(count)s minutes ago', count
+ # Translators: \\u00a0 is non-breaking space
+ 'a minute ago', '%(count)s\u00a0minutes ago', count
) % {'count': count}
else:
count = delta.seconds // 60 // 60
return ungettext(
- 'an hour ago', '%(count)s hours ago', count
+ # Translators: \\u00a0 is non-breaking space
+ 'an hour ago', '%(count)s\u00a0hours ago', count
) % {'count': count}
else:
delta = value - now
@@ -216,15 +219,18 @@ def naturaltime(value):
return _('now')
elif delta.seconds < 60:
return ungettext(
- 'a second from now', '%(count)s seconds from now', delta.seconds
+ # Translators: \\u00a0 is non-breaking space
+ 'a second from now', '%(count)s\u00a0seconds from now', delta.seconds
) % {'count': delta.seconds}
elif delta.seconds // 60 < 60:
count = delta.seconds // 60
return ungettext(
- 'a minute from now', '%(count)s minutes from now', count
+ # Translators: \\u00a0 is non-breaking space
+ 'a minute from now', '%(count)s\u00a0minutes from now', count
) % {'count': count}
else:
count = delta.seconds // 60 // 60
return ungettext(
- 'an hour from now', '%(count)s hours from now', count
+ # Translators: \\u00a0 is non-breaking space
+ 'an hour from now', '%(count)s\u00a0hours from now', count
) % {'count': count}
@@ -195,31 +195,31 @@ def utcoffset(self, dt):
result_list = [
'now',
'a second ago',
- '30 seconds ago',
+ '30\xa0seconds ago',
'a minute ago',
- '2 minutes ago',
+ '2\xa0minutes ago',
'an hour ago',
- '23 hours ago',
- '1 day ago',
- '1 year, 4 months ago',
+ '23\xa0hours ago',
+ '1\xa0day ago',
+ '1\xa0year, 4\xa0months ago',
'a second from now',
- '30 seconds from now',
+ '30\xa0seconds from now',
'a minute from now',
- '2 minutes from now',
+ '2\xa0minutes from now',
'an hour from now',
- '23 hours from now',
- '1 day from now',
- '2 days, 6 hours from now',
- '1 year, 4 months from now',
+ '23\xa0hours from now',
+ '1\xa0day from now',
+ '2\xa0days, 6\xa0hours from now',
+ '1\xa0year, 4\xa0months from now',
'now',
'now',
]
# Because of the DST change, 2 days and 6 hours after the chosen
# date in naive arithmetic is only 2 days and 5 hours after in
# aware arithmetic.
result_list_with_tz_support = result_list[:]
- assert result_list_with_tz_support[-4] == '2 days, 6 hours from now'
- result_list_with_tz_support[-4] == '2 days, 5 hours from now'
+ assert result_list_with_tz_support[-4] == '2\xa0days, 6\xa0hours from now'
+ result_list_with_tz_support[-4] == '2\xa0days, 5\xa0hours from now'
orig_humanize_datetime, humanize.datetime = humanize.datetime, MockDateTime
try:
@@ -14,7 +14,7 @@
from django.utils.dateformat import format, time_format
from django.utils.encoding import force_text, iri_to_uri
from django.utils.html import (conditional_escape, escapejs, fix_ampersands,
- escape, urlize as urlize_impl, linebreaks, strip_tags)
+ escape, urlize as urlize_impl, linebreaks, strip_tags, avoid_wrapping)
from django.utils.http import urlquote
from django.utils.text import Truncator, wrap, phone2numeric
from django.utils.safestring import mark_safe, SafeData, mark_for_escaping
@@ -810,7 +810,8 @@ def filesizeformat(bytes):
try:
bytes = float(bytes)
except (TypeError,ValueError,UnicodeDecodeError):
- return ungettext("%(size)d byte", "%(size)d bytes", 0) % {'size': 0}
+ value = ungettext("%(size)d byte", "%(size)d bytes", 0) % {'size': 0}
+ return avoid_wrapping(value)
filesize_number_format = lambda value: formats.number_format(round(value, 1), 1)
@@ -821,16 +822,19 @@ def filesizeformat(bytes):
PB = 1<<50
if bytes < KB:
- return ungettext("%(size)d byte", "%(size)d bytes", bytes) % {'size': bytes}
- if bytes < MB:
- return ugettext("%s KB") % filesize_number_format(bytes / KB)
- if bytes < GB:
- return ugettext("%s MB") % filesize_number_format(bytes / MB)
- if bytes < TB:
- return ugettext("%s GB") % filesize_number_format(bytes / GB)
- if bytes < PB:
- return ugettext("%s TB") % filesize_number_format(bytes / TB)
- return ugettext("%s PB") % filesize_number_format(bytes / PB)
+ value = ungettext("%(size)d byte", "%(size)d bytes", bytes) % {'size': bytes}
+ elif bytes < MB:
+ value = ugettext("%s KB") % filesize_number_format(bytes / KB)
+ elif bytes < GB:
+ value = ugettext("%s MB") % filesize_number_format(bytes / MB)
+ elif bytes < TB:
+ value = ugettext("%s GB") % filesize_number_format(bytes / GB)
+ elif bytes < PB:
+ value = ugettext("%s TB") % filesize_number_format(bytes / TB)
+ else:
+ value = ugettext("%s PB") % filesize_number_format(bytes / PB)
+
+ return avoid_wrapping(value)
@register.filter(is_safe=False)
def pluralize(value, arg='s'):
View
@@ -281,3 +281,10 @@ def replace_p_tags(match):
text = trailing_empty_content_re.sub('', text)
return text
clean_html = allow_lazy(clean_html, six.text_type)
+
+def avoid_wrapping(value):
+ """
+ Avoid text wrapping in the middle of a phrase by adding non-breaking
+ spaces where there previously were normal spaces.
+ """
+ return value.replace(" ", "\xa0")
@@ -2,6 +2,7 @@
import datetime
+from django.utils.html import avoid_wrapping
from django.utils.timezone import is_aware, utc
from django.utils.translation import ugettext, ungettext_lazy
@@ -40,18 +41,18 @@ def timesince(d, now=None, reversed=False):
since = delta.days * 24 * 60 * 60 + delta.seconds
if since <= 0:
# d is in the future compared to now, stop processing.
- return ugettext('0 minutes')
+ return avoid_wrapping(ugettext('0 minutes'))
for i, (seconds, name) in enumerate(chunks):
count = since // seconds
if count != 0:
break
- result = name % count
+ result = avoid_wrapping(name % count)
if i + 1 < len(chunks):
# Now get the second item
seconds2, name2 = chunks[i + 1]
count2 = (since - (seconds * count)) // seconds2
if count2 != 0:
- result += ugettext(', ') + name2 % count2
+ result += ugettext(', ') + avoid_wrapping(name2 % count2)
return result
def timeuntil(d, now=None):
@@ -527,24 +527,26 @@ def test_time(self):
def test_timesince(self):
# real testing is done in timesince.py, where we can provide our own 'now'
+ # NOTE: \xa0 avoids wrapping between value and unit
self.assertEqual(
timesince_filter(datetime.datetime.now() - datetime.timedelta(1)),
- '1 day')
+ '1\xa0day')
self.assertEqual(
timesince_filter(datetime.datetime(2005, 12, 29),
datetime.datetime(2005, 12, 30)),
- '1 day')
+ '1\xa0day')
def test_timeuntil(self):
+ # NOTE: \xa0 avoids wrapping between value and unit
self.assertEqual(
timeuntil_filter(datetime.datetime.now() + datetime.timedelta(1, 1)),
- '1 day')
+ '1\xa0day')
self.assertEqual(
timeuntil_filter(datetime.datetime(2005, 12, 30),
datetime.datetime(2005, 12, 29)),
- '1 day')
+ '1\xa0day')
def test_default(self):
self.assertEqual(default("val", "default"), 'val')
@@ -574,43 +576,45 @@ def test_yesno(self):
'get out of town')
def test_filesizeformat(self):
- self.assertEqual(filesizeformat(1023), '1023 bytes')
- self.assertEqual(filesizeformat(1024), '1.0 KB')
- self.assertEqual(filesizeformat(10*1024), '10.0 KB')
- self.assertEqual(filesizeformat(1024*1024-1), '1024.0 KB')
- self.assertEqual(filesizeformat(1024*1024), '1.0 MB')
- self.assertEqual(filesizeformat(1024*1024*50), '50.0 MB')
- self.assertEqual(filesizeformat(1024*1024*1024-1), '1024.0 MB')
- self.assertEqual(filesizeformat(1024*1024*1024), '1.0 GB')
- self.assertEqual(filesizeformat(1024*1024*1024*1024), '1.0 TB')
- self.assertEqual(filesizeformat(1024*1024*1024*1024*1024), '1.0 PB')
+ # NOTE: \xa0 avoids wrapping between value and unit
+ self.assertEqual(filesizeformat(1023), '1023\xa0bytes')
+ self.assertEqual(filesizeformat(1024), '1.0\xa0KB')
+ self.assertEqual(filesizeformat(10*1024), '10.0\xa0KB')
+ self.assertEqual(filesizeformat(1024*1024-1), '1024.0\xa0KB')
+ self.assertEqual(filesizeformat(1024*1024), '1.0\xa0MB')
+ self.assertEqual(filesizeformat(1024*1024*50), '50.0\xa0MB')
+ self.assertEqual(filesizeformat(1024*1024*1024-1), '1024.0\xa0MB')
+ self.assertEqual(filesizeformat(1024*1024*1024), '1.0\xa0GB')
+ self.assertEqual(filesizeformat(1024*1024*1024*1024), '1.0\xa0TB')
+ self.assertEqual(filesizeformat(1024*1024*1024*1024*1024), '1.0\xa0PB')
self.assertEqual(filesizeformat(1024*1024*1024*1024*1024*2000),
- '2000.0 PB')
- self.assertEqual(filesizeformat(complex(1,-1)), '0 bytes')
- self.assertEqual(filesizeformat(""), '0 bytes')
+ '2000.0\xa0PB')
+ self.assertEqual(filesizeformat(complex(1,-1)), '0\xa0bytes')
+ self.assertEqual(filesizeformat(""), '0\xa0bytes')
self.assertEqual(filesizeformat("\N{GREEK SMALL LETTER ALPHA}"),
- '0 bytes')
+ '0\xa0bytes')
def test_localized_filesizeformat(self):
+ # NOTE: \xa0 avoids wrapping between value and unit
with self.settings(USE_L10N=True):
with translation.override('de', deactivate=True):
- self.assertEqual(filesizeformat(1023), '1023 Bytes')
- self.assertEqual(filesizeformat(1024), '1,0 KB')
- self.assertEqual(filesizeformat(10*1024), '10,0 KB')
- self.assertEqual(filesizeformat(1024*1024-1), '1024,0 KB')
- self.assertEqual(filesizeformat(1024*1024), '1,0 MB')
- self.assertEqual(filesizeformat(1024*1024*50), '50,0 MB')
- self.assertEqual(filesizeformat(1024*1024*1024-1), '1024,0 MB')
- self.assertEqual(filesizeformat(1024*1024*1024), '1,0 GB')
- self.assertEqual(filesizeformat(1024*1024*1024*1024), '1,0 TB')
+ self.assertEqual(filesizeformat(1023), '1023\xa0Bytes')
+ self.assertEqual(filesizeformat(1024), '1,0\xa0KB')
+ self.assertEqual(filesizeformat(10*1024), '10,0\xa0KB')
+ self.assertEqual(filesizeformat(1024*1024-1), '1024,0\xa0KB')
+ self.assertEqual(filesizeformat(1024*1024), '1,0\xa0MB')
+ self.assertEqual(filesizeformat(1024*1024*50), '50,0\xa0MB')
+ self.assertEqual(filesizeformat(1024*1024*1024-1), '1024,0\xa0MB')
+ self.assertEqual(filesizeformat(1024*1024*1024), '1,0\xa0GB')
+ self.assertEqual(filesizeformat(1024*1024*1024*1024), '1,0\xa0TB')
self.assertEqual(filesizeformat(1024*1024*1024*1024*1024),
- '1,0 PB')
+ '1,0\xa0PB')
self.assertEqual(filesizeformat(1024*1024*1024*1024*1024*2000),
- '2000,0 PB')
- self.assertEqual(filesizeformat(complex(1,-1)), '0 Bytes')
- self.assertEqual(filesizeformat(""), '0 Bytes')
+ '2000,0\xa0PB')
+ self.assertEqual(filesizeformat(complex(1,-1)), '0\xa0Bytes')
+ self.assertEqual(filesizeformat(""), '0\xa0Bytes')
self.assertEqual(filesizeformat("\N{GREEK SMALL LETTER ALPHA}"),
- '0 Bytes')
+ '0\xa0Bytes')
def test_pluralize(self):
self.assertEqual(pluralize(1), '')
Oops, something went wrong.

0 comments on commit 7d77e97

Please sign in to comment.