close Warning: HTML preview using PatchRenderer failed (ValueError: not enough values to unpack (expected 2, got 1))

Ticket #14806: 14806.template-tags-pgettext.diff

File 14806.template-tags-pgettext.diff, 14.5 KB (added by Julien Phalip, 13 years ago)
Line 
1diff --git a/django/template/base.py b/django/template/base.py
2index 8001e93..3129886 100644
3--- a/django/template/base.py
4+++ b/django/template/base.py
5@@ -10,7 +10,7 @@ from django.utils.itercompat import is_iterable
6 from django.utils.text import (smart_split, unescape_string_literal,
7 get_text_list)
8 from django.utils.encoding import smart_unicode, force_unicode, smart_str
9-from django.utils.translation import ugettext_lazy
10+from django.utils.translation import ugettext_lazy, pgettext_lazy
11 from django.utils.safestring import (SafeData, EscapeData, mark_safe,
12 mark_for_escaping)
13 from django.utils.formats import localize
14@@ -673,6 +673,7 @@ class Variable(object):
15 self.literal = None
16 self.lookups = None
17 self.translate = False
18+ self.trans_context = None
19
20 try:
21 # First try to treat this variable as a number.
22@@ -720,7 +721,10 @@ class Variable(object):
23 # We're dealing with a literal, so it's already been "resolved"
24 value = self.literal
25 if self.translate:
26- return ugettext_lazy(value)
27+ if self.trans_context:
28+ return pgettext_lazy(self.trans_context, value)
29+ else:
30+ return ugettext_lazy(value)
31 return value
32
33 def __repr__(self):
34@@ -814,11 +818,10 @@ class NodeList(list):
35 bits = []
36 for node in self:
37 if isinstance(node, Node):
38- bit = self.render_node(node, context)
39+ bits.append(self.render_node(node, context))
40 else:
41- bit = node
42- bits.append(force_unicode(bit))
43- return mark_safe(u''.join(bits))
44+ bits.append(node)
45+ return mark_safe(''.join([force_unicode(b) for b in bits]))
46
47 def get_nodes_by_type(self, nodetype):
48 "Return a list of all nodes of the given type"
49diff --git a/django/templatetags/i18n.py b/django/templatetags/i18n.py
50index 669cdc9..4f64316 100644
51--- a/django/templatetags/i18n.py
52+++ b/django/templatetags/i18n.py
53@@ -70,15 +70,21 @@ class GetCurrentLanguageBidiNode(Node):
54
55
56 class TranslateNode(Node):
57- def __init__(self, filter_expression, noop, asvar=None):
58+ def __init__(self, filter_expression, noop, asvar=None,
59+ trans_context=None):
60 self.noop = noop
61 self.asvar = asvar
62+ self.trans_context = trans_context
63 self.filter_expression = filter_expression
64 if isinstance(self.filter_expression.var, basestring):
65- self.filter_expression.var = Variable(u"'%s'" % self.filter_expression.var)
66+ self.filter_expression.var = Variable(u"'%s'" %
67+ self.filter_expression.var)
68
69 def render(self, context):
70 self.filter_expression.var.translate = not self.noop
71+ if self.trans_context:
72+ self.filter_expression.var.trans_context = (
73+ self.trans_context.resolve(context))
74 output = self.filter_expression.resolve(context)
75 value = _render_value_in_context(output, context)
76 if self.asvar:
77@@ -90,12 +96,13 @@ class TranslateNode(Node):
78
79 class BlockTranslateNode(Node):
80 def __init__(self, extra_context, singular, plural=None, countervar=None,
81- counter=None):
82+ counter=None, trans_context=None):
83 self.extra_context = extra_context
84 self.singular = singular
85 self.plural = plural
86 self.countervar = countervar
87 self.counter = counter
88+ self.trans_context = trans_context
89
90 def render_token_list(self, tokens):
91 result = []
92@@ -109,6 +116,10 @@ class BlockTranslateNode(Node):
93 return ''.join(result), vars
94
95 def render(self, context):
96+ if self.trans_context:
97+ trans_context = self.trans_context.resolve(context)
98+ else:
99+ trans_context = None
100 tmp_context = {}
101 for var, val in self.extra_context.items():
102 tmp_context[var] = val.resolve(context)
103@@ -123,10 +134,17 @@ class BlockTranslateNode(Node):
104 context[self.countervar] = count
105 plural, plural_vars = self.render_token_list(self.plural)
106 plural = re.sub(u'%(?!\()', u'%%', plural)
107- result = translation.ungettext(singular, plural, count)
108+ if trans_context:
109+ result = translation.npgettext(trans_context, singular, plural,
110+ count)
111+ else:
112+ result = translation.ungettext(singular, plural, count)
113 vars.extend(plural_vars)
114 else:
115- result = translation.ugettext(singular)
116+ if trans_context:
117+ result = translation.pgettext(trans_context, singular)
118+ else:
119+ result = translation.ugettext(singular)
120 data = dict([(v, _render_value_in_context(context.get(v, ''), context)) for v in vars])
121 context.pop()
122 try:
123@@ -301,7 +319,6 @@ def do_translate(parser, token):
124 # backwards compatibility with existing uses of ``trans``
125 # where single quote use is supported.
126 if value[0] == "'":
127- pos = None
128 m = re.match("^'([^']+)'(\|.*$)", value)
129 if m:
130 value = '"%s"%s' % (m.group(1).replace('"','\\"'), m.group(2))
131@@ -310,19 +327,23 @@ def do_translate(parser, token):
132
133 noop = False
134 asvar = None
135+ trans_context = None
136
137 while self.more():
138 tag = self.tag()
139 if tag == 'noop':
140 noop = True
141+ elif tag == 'context':
142+ trans_context = parser.compile_filter(self.tag())
143 elif tag == 'as':
144 asvar = self.tag()
145 else:
146 raise TemplateSyntaxError(
147 "only options for 'trans' are 'noop' and 'as VAR.")
148- return (value, noop, asvar)
149- value, noop, asvar = TranslateParser(token.contents).top()
150- return TranslateNode(parser.compile_filter(value), noop, asvar)
151+ return value, noop, asvar, trans_context
152+ value, noop, asvar, trans_context = TranslateParser(token.contents).top()
153+ return TranslateNode(parser.compile_filter(value), noop, asvar,
154+ trans_context)
155
156 @register.tag("blocktrans")
157 def do_block_translate(parser, token):
158@@ -369,6 +390,13 @@ def do_block_translate(parser, token):
159 if len(value) != 1:
160 raise TemplateSyntaxError('"count" in %r tag expected exactly '
161 'one keyword argument.' % bits[0])
162+ elif option == "context":
163+ try:
164+ value = remaining_bits.pop(0)
165+ value = parser.compile_filter(value)
166+ except Exception:
167+ raise TemplateSyntaxError('"context" in %r tag expected '
168+ 'exactly one argument.' % bits[0])
169 else:
170 raise TemplateSyntaxError('Unknown argument for %r tag: %r.' %
171 (bits[0], option))
172@@ -378,7 +406,11 @@ def do_block_translate(parser, token):
173 countervar, counter = options['count'].items()[0]
174 else:
175 countervar, counter = None, None
176- extra_context = options.get('with', {})
177+ if 'context' in options:
178+ trans_context = options['context']
179+ else:
180+ trans_context = None
181+ extra_context = options.get('with', {})
182
183 singular = []
184 plural = []
185@@ -401,7 +433,7 @@ def do_block_translate(parser, token):
186 raise TemplateSyntaxError("'blocktrans' doesn't allow other block tags (seen %r) inside it" % token.contents)
187
188 return BlockTranslateNode(extra_context, singular, plural, countervar,
189- counter)
190+ counter, trans_context)
191
192 @register.tag
193 def language(parser, token):
194diff --git a/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.mo b/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.mo
195index a1a93c83296f0fb97d500466a8df30338fdb137e..9ab2f4672535fe38d864ec37cbd7815cac8db453 100644
196GIT binary patch
197delta 554
198zcmaKnu}T9$5QZnoX^dbBMbSj$5KofA(n@TMR$2%?fLxNr3&vG;bCt+7d4V7{zJ{F$
199z;zL;KD;Qru{5J70N_5$Ozq#4jf97uUkA>uQ*1HkbG+IV&G=m<HTYYqh-cbSVWQKJI
200z(Br!Wi%`QFyn<!;1h?S}oPy=7$T9I6bbj5O$dX7R&jc$Z-ryW8;z}s1a2Kw_MR*D~
201zVHdLHo&!IbKyFPAF*xZlXzB*eBlmO8)4h|Ra-mE^=}y%KLGPo~>#O9v6Di}{m>b`!
202z&@>`1sOb2tu1wW_<&Cm&yTkLbc`NC=rk_@(5qJMPFO0Xoi!$@s+IPQDH<eM^KXPsx
203jd*(#db<2)UG_3elVAb_yuCz5W_}>OUZ>*C2P;2=F0$+a)
204
205delta 225
206zcmdnbIg7pio)F7a1|Z-7Vi_Qg0b*_-o&&@nZ~}+}fcPX3a{{pxBSf7FkY)k$9f33-
207zkah#o(m*;CNQ2BO1k&+9Tm{4+{kNDH7$kwTHZuc*9FTSe(!xM(3@Jbc5HVB$2?-!w
208z1EfI)PX*FIy>I{$1DXK_Y(NsEhaHGPma$HJJ7MxcMw!jhOgv1Jb66x;y%Y2D7y!I`
209B6te&T
210
211diff --git a/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.po b/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.po
212index 7226ad1..9bf79ce 100644
213--- a/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.po
214+++ b/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.po
215@@ -52,3 +52,18 @@ msgid "%(percent)s%% represents %(num)s object"
216 msgid_plural "%(percent)s%% represents %(num)s objects"
217 msgstr[0] "%(percent)s%% stellt %(num)s Objekt dar"
218 msgstr[1] "%(percent)s%% stellt %(num)s Objekte dar"
219+
220+#: models.py:17
221+msgctxt "super search"
222+msgid "%(number)s super result"
223+msgid_plural "%(number)s super results"
224+msgstr[0] "%(number)s Super-Ergebnis"
225+msgstr[1] "%(number)s Super-Ergebnisse"
226+
227+#: models.py:19
228+msgctxt "other super search"
229+msgid "%(number)s super result"
230+msgid_plural "%(number)s super results"
231+msgstr[0] "%(number)s anderen Super-Ergebnis"
232+msgstr[1] "%(number)s andere Super-Ergebnisse"
233+
234diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py
235index fc69d9c..7b0e285 100644
236--- a/tests/regressiontests/i18n/tests.py
237+++ b/tests/regressiontests/i18n/tests.py
238@@ -9,6 +9,7 @@ from threading import local
239
240 from django.conf import settings
241 from django.template import Template, Context
242+from django.template.base import TemplateSyntaxError
243 from django.test import TestCase, RequestFactory
244 from django.test.utils import override_settings
245 from django.utils import translation
246@@ -87,6 +88,69 @@ class TranslationTests(TestCase):
247 self.assertEqual(pgettext("verb", "May"), u"Kann")
248 self.assertEqual(npgettext("search", "%d result", "%d results", 4) % 4, u"4 Resultate")
249
250+ def test_template_tags_pgettext(self):
251+ # Reset translation catalog to include other/locale/de
252+ extended_locale_paths = settings.LOCALE_PATHS + (
253+ os.path.join(here, 'other', 'locale'),
254+ )
255+ with self.settings(LOCALE_PATHS=extended_locale_paths):
256+ from django.utils.translation import trans_real
257+ trans_real._active = local()
258+ trans_real._translations = {}
259+ with translation.override('de'):
260+
261+ # Blocktrans ---------
262+
263+ # Inexisting context...
264+ t = Template('{% load i18n %}{% blocktrans context "unexisting" %}May{% endblocktrans %}')
265+ rendered = t.render(Context())
266+ self.assertEqual(rendered, 'May')
267+
268+ # Existing context...
269+ # Using a literal
270+ t = Template('{% load i18n %}{% blocktrans context "month name" %}May{% endblocktrans %}')
271+ rendered = t.render(Context())
272+ self.assertEqual(rendered, 'Mai')
273+ t = Template('{% load i18n %}{% blocktrans context "verb" %}May{% endblocktrans %}')
274+ rendered = t.render(Context())
275+ self.assertEqual(rendered, 'Kann')
276+
277+ # Using a variable
278+ t = Template('{% load i18n %}{% blocktrans context trans_context %}May{% endblocktrans %}')
279+ rendered = t.render(Context({'trans_context': 'month name'}))
280+ self.assertEqual(rendered, 'Mai')
281+ t = Template('{% load i18n %}{% blocktrans context trans_context %}May{% endblocktrans %}')
282+ rendered = t.render(Context({'trans_context': 'verb'}))
283+ self.assertEqual(rendered, 'Kann')
284+
285+ # Using a filter
286+ t = Template('{% load i18n %}{% blocktrans context trans_context|lower %}May{% endblocktrans %}')
287+ rendered = t.render(Context({'trans_context': 'MONTH NAME'}))
288+ self.assertEqual(rendered, 'Mai')
289+ t = Template('{% load i18n %}{% blocktrans context trans_context|lower %}May{% endblocktrans %}')
290+ rendered = t.render(Context({'trans_context': 'VERB'}))
291+ self.assertEqual(rendered, 'Kann')
292+
293+ # Using 'count'
294+ t = Template('{% load i18n %}{% blocktrans count number=1 context "super search" %}{{ number }} super result{% plural %}{{ number }} super results{% endblocktrans %}')
295+ rendered = t.render(Context())
296+ self.assertEqual(rendered, '1 Super-Ergebnis')
297+ t = Template('{% load i18n %}{% blocktrans count number=2 context "super search" %}{{ number }} super result{% plural %}{{ number }} super results{% endblocktrans %}')
298+ rendered = t.render(Context())
299+ self.assertEqual(rendered, '2 Super-Ergebnisse')
300+ t = Template('{% load i18n %}{% blocktrans count number=1 context "other super search" %}{{ number }} super result{% plural %}{{ number }} super results{% endblocktrans %}')
301+ rendered = t.render(Context())
302+ self.assertEqual(rendered, '1 anderen Super-Ergebnis')
303+ t = Template('{% load i18n %}{% blocktrans count number=2 context "other super search" %}{{ number }} super result{% plural %}{{ number }} super results{% endblocktrans %}')
304+ rendered = t.render(Context())
305+ self.assertEqual(rendered, '2 andere Super-Ergebnisse')
306+
307+ # Mis-uses
308+ self.assertRaises(TemplateSyntaxError, Template, '{% load i18n %}{% blocktrans context with month="May" %}{{ month }}{% endblocktrans %}')
309+ self.assertRaises(TemplateSyntaxError, Template, '{% load i18n %}{% blocktrans context %}{% endblocktrans %}')
310+ self.assertRaises(TemplateSyntaxError, Template, '{% load i18n %}{% blocktrans count number=2 context %}{{ number }} super result{% plural %}{{ number }} super results{% endblocktrans %}')
311+
312+
313 def test_string_concat(self):
314 """
315 unicode(string_concat(...)) should not raise a TypeError - #4796
Back to Top