Fixed #26866 -- Added format_lazy function

Added format_lazy function to django.utils.text module.
Useful when dealing with relative complex lazy string concatenations
(e.g. in urls.py when translating urls in regular expressions).
This commit is contained in:
Mattias Loverot 2016-08-24 18:18:17 +02:00 committed by Claude Paroz
parent cf2cd4053f
commit 9aaeec337e
3 changed files with 55 additions and 2 deletions

View File

@ -7,7 +7,9 @@ from io import BytesIO
from django.utils import six
from django.utils.encoding import force_text
from django.utils.functional import SimpleLazyObject, keep_lazy, keep_lazy_text
from django.utils.functional import (
SimpleLazyObject, keep_lazy, keep_lazy_text, lazy,
)
from django.utils.safestring import SafeText, mark_safe
from django.utils.six.moves import html_entities
from django.utils.translation import pgettext, ugettext as _, ugettext_lazy
@ -434,3 +436,12 @@ def camel_case_to_spaces(value):
trailing whitespace.
"""
return re_camel_case.sub(r' \1', value).strip().lower()
def _format_lazy(format_string, *args, **kwargs):
"""
Apply str.format() on 'format_string' where format_string, args,
and/or kwargs might be lazy.
"""
return format_string.format(*args, **kwargs)
format_lazy = lazy(_format_lazy, six.text_type)

View File

@ -868,6 +868,26 @@ appropriate entities.
.. module:: django.utils.text
:synopsis: Text manipulation.
.. function:: format_lazy(format_string, *args, **kwargs)
.. versionadded:: 1.11
A version of :meth:`str.format` for when ``format_string``, ``args``,
and/or ``kwargs`` contain lazy objects. The first argument is the string to
be formatted. For example::
from django.utils.text import format_lazy
from django.utils.translation import pgettext_lazy
urlpatterns = [
url(format_lazy(r'{person}/(?P<pk>\d+)/$', person=pgettext_lazy('URL', 'person')),
PersonDetailView.as_view()),
]
This example allows translators to translate part of the URL. If "person"
is translated to "persona", the regular expression will match
``persona/(?P<pk>\d+)/$``, e.g. ``persona/5/``.
.. function:: slugify(allow_unicode=False)
Converts to ASCII if ``allow_unicode`` is ``False`` (default). Converts spaces to

View File

@ -6,7 +6,8 @@ import json
from django.test import SimpleTestCase
from django.utils import six, text
from django.utils.functional import lazystr
from django.utils.translation import override
from django.utils.text import format_lazy
from django.utils.translation import override, ugettext_lazy
IS_WIDE_BUILD = (len('\U0001F4A9') == 1)
@ -225,3 +226,24 @@ class TestUtilsText(SimpleTestCase):
out = text.compress_sequence(seq)
compressed_length = len(b''.join(out))
self.assertTrue(compressed_length < actual_length)
def test_format_lazy(self):
self.assertEqual('django/test', format_lazy('{}/{}', 'django', lazystr('test')))
self.assertEqual('django/test', format_lazy('{0}/{1}', *('django', 'test')))
self.assertEqual('django/test', format_lazy('{a}/{b}', **{'a': 'django', 'b': 'test'}))
self.assertEqual('django/test', format_lazy('{a[0]}/{a[1]}', a=('django', 'test')))
t = {}
s = format_lazy('{0[a]}-{p[a]}', t, p=t)
t['a'] = lazystr('django')
self.assertEqual('django-django', s)
t['a'] = 'update'
self.assertEqual('update-update', s)
# The format string can be lazy. (string comes from contrib.admin)
s = format_lazy(
ugettext_lazy("Added {name} \"{object}\"."),
name='article', object='My first try',
)
with override('fr'):
self.assertEqual('article «\xa0My first try\xa0» ajouté.', s)