Index: django/templatetags/i18n.py
===================================================================
--- django/templatetags/i18n.py (revision 8255)
+++ django/templatetags/i18n.py (working copy)
@@ -3,6 +3,7 @@
from django.template import Node, Variable, VariableNode
from django.template import TemplateSyntaxError, TokenParser, Library
from django.template import TOKEN_TEXT, TOKEN_VAR
+from django.template.defaulttags import URLNode
from django.utils import translation
from django.utils.encoding import force_unicode
@@ -203,6 +204,12 @@
There are {{ count }} objects.
{% endblocktrans %}
+ In latest development version it supports url too::
+
+ {% blocktrans url path.to.some_view arg1,arg2,name1=value1 as myurl %}
+ This is a link.
+ {% endblocktrans %}
+
This is much like ngettext, only in template syntax.
"""
class BlockTranslateParser(TokenParser):
@@ -218,6 +225,24 @@
raise TemplateSyntaxError, "variable bindings in 'blocktrans' must be 'with value as variable'"
extra_context[self.tag()] = VariableNode(
parser.compile_filter(value))
+ elif tag == 'url':
+ args = []
+ kwargs = {}
+ value = self.value()
+ next_tag = self.tag()
+ if next_tag != 'as':
+ if self.tag() != 'as':
+ raise TemplateSyntaxError, "variable bindings in 'blocktrans' must be 'url path.to.some_view arg1,arg2,name1=value1 as variable'"
+ else:
+ # can't find way to do not duplicate code from url tag
+ for arg in next_tag.split(','):
+ if '=' in arg:
+ k, v = arg.split('=', 1)
+ k = k.strip()
+ kwargs[k] = parser.compile_filter(v)
+ else:
+ args.append(parser.compile_filter(arg))
+ extra_context[self.tag()] = URLNode(value, args, kwargs)
elif tag == 'count':
counter = parser.compile_filter(self.value())
if self.tag() != 'as':
Index: tests/regressiontests/templates/tests.py
===================================================================
--- tests/regressiontests/templates/tests.py (revision 8255)
+++ tests/regressiontests/templates/tests.py (working copy)
@@ -753,28 +753,52 @@
# translation of plural form
'i18n08': ('{% load i18n %}{% blocktrans count number as counter %}singular{% plural %}{{ counter }} plural{% endblocktrans %}', {'number': 2}, "2 plural"),
+ # translation with an url, success
+ 'i18n09': ('{% load i18n %}{% blocktrans url regressiontests.templates.views.client client.id as url %}link{% endblocktrans %}', {'client': {'id': 1}}, 'link'),
+ 'i18n10': ('{% load i18n %}{% blocktrans url regressiontests.templates.views.client_action client.id,action="update" as url %}link{% endblocktrans %}', {'client': {'id': 1}}, 'link'),
+ 'i18n11': ('{% load i18n %}{% blocktrans url regressiontests.templates.views.index as url %}link{% endblocktrans %}', {}, 'link'),
+ 'i18n12': ('{% load i18n %}{% blocktrans url named.client client.id as url %}link{% endblocktrans %}', {'client': {'id': 1}}, 'link'),
+ 'i18n13': (u'{% load i18n %}{% blocktrans url метка_оператора v as url %}link{% endblocktrans %}', {'v': u'Ω'},
+ 'link'),
+
+ # translation with an url, failure
+ 'i18n13': ('{% load i18n %}{% blocktrans url %}{% endblocktrans %}', {}, template.TemplateSyntaxError),
+ 'i18n14': ('{% load i18n %}{% blocktrans url no_such_view %}{% endblocktrans %}', {}, template.TemplateSyntaxError),
+ 'i18n15': ('{% load i18n %}{% blocktrans url no_such_view as no_such_view_url %}{% endblocktrans %}', {}, urlresolvers.NoReverseMatch),
+ 'i18n16': ('{% load i18n %}{% blocktrans url regressiontests.templates.views.client as client_url %}{% endblocktrans %}', {}, urlresolvers.NoReverseMatch),
+
+ # translation with combined arguments (with, count and/or url)
+ 'i18n17': ('{% load i18n %}{% blocktrans with anton|lower as berta count number as counter %}{{ berta }} singular{% plural %}{{ berta }} {{ counter }} plural{% endblocktrans %}', {'anton': '\xc3\x85', 'number': 1}, u'å singular'),
+ 'i18n18': ('{% load i18n %}{% blocktrans count number as counter with anton|lower as berta %}{{ berta }} singular{% plural %}{{ berta }} {{ counter }} plural{% endblocktrans %}', {'anton': '\xc3\x85', 'number': 2}, u'å 2 plural'),
+ 'i18n19': ('{% load i18n %}{% blocktrans with anton|lower as berta url regressiontests.templates.views.client client.id as url %}{{ berta }} link{% endblocktrans %}', {'client': {'id': 1}, 'anton': '\xc3\x85'}, u'å link'),
+ 'i18n20': ('{% load i18n %}{% blocktrans url regressiontests.templates.views.client client.id as url with anton|lower as berta %}{{ berta }} link{% endblocktrans %}', {'client': {'id': 1}, 'anton': '\xc3\x85'}, u'å link'),
+ 'i18n21': ('{% load i18n %}{% blocktrans count number as counter url regressiontests.templates.views.client client.id as url %}{{ url }} singular{% plural %}{{ url }} {{ counter }} plural{% endblocktrans %}', {'client': {'id': 1}, 'number': 1}, u'/url_tag/client/1/ singular'),
+ 'i18n22': ('{% load i18n %}{% blocktrans url regressiontests.templates.views.client client.id as url count number as counter %}{{ url }} singular{% plural %}{{ url }} {{ counter }} plural{% endblocktrans %}', {'client': {'id': 1}, 'number': 2}, u'/url_tag/client/1/ 2 plural'),
+ 'i18n23': ('{% load i18n %}{% blocktrans with anton|lower as berta and foo as bar count number as counter url regressiontests.templates.views.client client.id as url %}{{ berta }} {{ bar }} {{ url }} singular{% plural %}{{ berta }} {{ bar }} {{ url }} {{ counter }} plural{% endblocktrans %}', {'client': {'id': 1}, 'number': 1, 'anton': '\xc3\x85', 'foo': 'baz'}, u'å baz /url_tag/client/1/ singular'),
+ 'i18n24': ('{% load i18n %}{% blocktrans url regressiontests.templates.views.client client.id as url count number as counter with anton|lower as berta %}{{ berta }} {{ url }} singular{% plural %}{{ berta }} {{ url }} {{ counter }} plural{% endblocktrans %}', {'client': {'id': 1}, 'number': 2, 'anton': '\xc3\x85'}, u'å /url_tag/client/1/ 2 plural'),
+
# simple non-translation (only marking) of a string to german
- 'i18n09': ('{% load i18n %}{% trans "Page not found" noop %}', {'LANGUAGE_CODE': 'de'}, "Page not found"),
+ 'i18n25': ('{% load i18n %}{% trans "Page not found" noop %}', {'LANGUAGE_CODE': 'de'}, "Page not found"),
# translation of a variable with a translated filter
- 'i18n10': ('{{ bool|yesno:_("yes,no,maybe") }}', {'bool': True, 'LANGUAGE_CODE': 'de'}, 'Ja'),
+ 'i18n26': ('{{ bool|yesno:_("yes,no,maybe") }}', {'bool': True, 'LANGUAGE_CODE': 'de'}, 'Ja'),
# translation of a variable with a non-translated filter
- 'i18n11': ('{{ bool|yesno:"ja,nein" }}', {'bool': True}, 'ja'),
+ 'i18n27': ('{{ bool|yesno:"ja,nein" }}', {'bool': True}, 'ja'),
# usage of the get_available_languages tag
- 'i18n12': ('{% load i18n %}{% get_available_languages as langs %}{% for lang in langs %}{% ifequal lang.0 "de" %}{{ lang.0 }}{% endifequal %}{% endfor %}', {}, 'de'),
+ 'i18n28': ('{% load i18n %}{% get_available_languages as langs %}{% for lang in langs %}{% ifequal lang.0 "de" %}{{ lang.0 }}{% endifequal %}{% endfor %}', {}, 'de'),
# translation of constant strings
- 'i18n13': ('{{ _("Password") }}', {'LANGUAGE_CODE': 'de'}, 'Passwort'),
- 'i18n14': ('{% cycle "foo" _("Password") _(\'Password\') as c %} {% cycle c %} {% cycle c %}', {'LANGUAGE_CODE': 'de'}, 'foo Passwort Passwort'),
- 'i18n15': ('{{ absent|default:_("Password") }}', {'LANGUAGE_CODE': 'de', 'absent': ""}, 'Passwort'),
- 'i18n16': ('{{ _("<") }}', {'LANGUAGE_CODE': 'de'}, '<'),
+ 'i18n29': ('{{ _("Password") }}', {'LANGUAGE_CODE': 'de'}, 'Passwort'),
+ 'i18n30': ('{% cycle "foo" _("Password") _(\'Password\') as c %} {% cycle c %} {% cycle c %}', {'LANGUAGE_CODE': 'de'}, 'foo Passwort Passwort'),
+ 'i18n31': ('{{ absent|default:_("Password") }}', {'LANGUAGE_CODE': 'de', 'absent': ""}, 'Passwort'),
+ 'i18n32': ('{{ _("<") }}', {'LANGUAGE_CODE': 'de'}, '<'),
# Escaping inside blocktrans works as if it was directly in the
# template.
- 'i18n17': ('{% load i18n %}{% blocktrans with anton|escape as berta %}{{ berta }}{% endblocktrans %}', {'anton': 'α & β'}, u'α & β'),
- 'i18n18': ('{% load i18n %}{% blocktrans with anton|force_escape as berta %}{{ berta }}{% endblocktrans %}', {'anton': 'α & β'}, u'α & β'),
+ 'i18n33': ('{% load i18n %}{% blocktrans with anton|escape as berta %}{{ berta }}{% endblocktrans %}', {'anton': 'α & β'}, u'α & β'),
+ 'i18n34': ('{% load i18n %}{% blocktrans with anton|force_escape as berta %}{{ berta }}{% endblocktrans %}', {'anton': 'α & β'}, u'α & β'),
### HANDLING OF TEMPLATE_STRING_IF_INVALID ###################################
Index: AUTHORS
===================================================================
--- AUTHORS (revision 8255)
+++ AUTHORS (working copy)
@@ -239,6 +239,7 @@
Nick Lane
Stuart Langridge
Paul Lanier
+ David Larlet
Nicola Larosa
Lau Bech Lauritzen
Rune Rønde Laursen
Index: docs/i18n.txt
===================================================================
--- docs/i18n.txt (revision 8255)
+++ docs/i18n.txt (working copy)
@@ -260,6 +260,13 @@
There are {{ counter }} {{ name }} objects.
{% endblocktrans %}
+**New in development version:** If you need to use `url template tag`_, you
+can specify it within ``{% blocktrans %}``, as ``count`` above. Example::
+
+ {% blocktrans url path.to.some_view arg1,arg2,name1=value1 as myurl %}
+ This is a link.
+ {% endblocktrans %}
+
Internally, all block and inline translations use the appropriate
``ugettext`` / ``ungettext`` call.
@@ -302,6 +309,7 @@
(keeping the comma intact).
.. _Django templates: ../templates_python/
+.. _url template tag: ../templates/#url
Working with lazy translation objects
-------------------------------------