Mercurial > genshi > genshi-test
comparison genshi/filters/tests/i18n.py @ 902:09cc3627654c experimental-inline
Sync `experimental/inline` branch with [source:trunk@1126].
author | cmlenz |
---|---|
date | Fri, 23 Apr 2010 21:08:26 +0000 |
parents | 1837f39efd6f |
children |
comparison
equal
deleted
inserted
replaced
830:de82830f8816 | 902:09cc3627654c |
---|---|
1 # -*- coding: utf-8 -*- | 1 # -*- coding: utf-8 -*- |
2 # | 2 # |
3 # Copyright (C) 2007-2008 Edgewall Software | 3 # Copyright (C) 2007-2010 Edgewall Software |
4 # All rights reserved. | 4 # All rights reserved. |
5 # | 5 # |
6 # This software is licensed as described in the file COPYING, which | 6 # This software is licensed as described in the file COPYING, which |
7 # you should have received as part of this distribution. The terms | 7 # you should have received as part of this distribution. The terms |
8 # are also available at http://genshi.edgewall.org/wiki/License. | 8 # are also available at http://genshi.edgewall.org/wiki/License. |
16 from gettext import NullTranslations | 16 from gettext import NullTranslations |
17 from StringIO import StringIO | 17 from StringIO import StringIO |
18 import unittest | 18 import unittest |
19 | 19 |
20 from genshi.core import Attrs | 20 from genshi.core import Attrs |
21 from genshi.template import MarkupTemplate | 21 from genshi.template import MarkupTemplate, Context |
22 from genshi.filters.i18n import Translator, extract | 22 from genshi.filters.i18n import Translator, extract |
23 from genshi.input import HTML | 23 from genshi.input import HTML |
24 | 24 |
25 | 25 |
26 class DummyTranslations(NullTranslations): | 26 class DummyTranslations(NullTranslations): |
27 | 27 _domains = {} |
28 def __init__(self, catalog): | 28 |
29 def __init__(self, catalog=()): | |
29 NullTranslations.__init__(self) | 30 NullTranslations.__init__(self) |
30 self._catalog = catalog | 31 self._catalog = catalog or {} |
32 self.plural = lambda n: n != 1 | |
33 | |
34 def add_domain(self, domain, catalog): | |
35 translation = DummyTranslations(catalog) | |
36 translation.add_fallback(self) | |
37 self._domains[domain] = translation | |
38 | |
39 def _domain_call(self, func, domain, *args, **kwargs): | |
40 return getattr(self._domains.get(domain, self), func)(*args, **kwargs) | |
31 | 41 |
32 def ugettext(self, message): | 42 def ugettext(self, message): |
33 missing = object() | 43 missing = object() |
34 tmsg = self._catalog.get(message, missing) | 44 tmsg = self._catalog.get(message, missing) |
35 if tmsg is missing: | 45 if tmsg is missing: |
36 if self._fallback: | 46 if self._fallback: |
37 return self._fallback.ugettext(message) | 47 return self._fallback.ugettext(message) |
38 return unicode(message) | 48 return unicode(message) |
39 return tmsg | 49 return tmsg |
40 | 50 |
51 def dugettext(self, domain, message): | |
52 return self._domain_call('ugettext', domain, message) | |
53 | |
54 def ungettext(self, msgid1, msgid2, n): | |
55 try: | |
56 return self._catalog[(msgid1, self.plural(n))] | |
57 except KeyError: | |
58 if self._fallback: | |
59 return self._fallback.ngettext(msgid1, msgid2, n) | |
60 if n == 1: | |
61 return msgid1 | |
62 else: | |
63 return msgid2 | |
64 | |
65 def dungettext(self, domain, singular, plural, numeral): | |
66 return self._domain_call('ungettext', domain, singular, plural, numeral) | |
67 | |
41 | 68 |
42 class TranslatorTestCase(unittest.TestCase): | 69 class TranslatorTestCase(unittest.TestCase): |
43 | 70 |
44 def test_translate_included_attribute_text(self): | 71 def test_translate_included_attribute_text(self): |
45 """ | 72 """ |
59 ${ngettext("Singular", "Plural", num)} | 86 ${ngettext("Singular", "Plural", num)} |
60 </html>""") | 87 </html>""") |
61 translator = Translator(extract_text=False) | 88 translator = Translator(extract_text=False) |
62 messages = list(translator.extract(tmpl.stream)) | 89 messages = list(translator.extract(tmpl.stream)) |
63 self.assertEqual(1, len(messages)) | 90 self.assertEqual(1, len(messages)) |
64 self.assertEqual((3, 'ngettext', (u'Singular', u'Plural', None), []), | 91 self.assertEqual((3, 'ngettext', ('Singular', 'Plural', None), []), |
65 messages[0]) | 92 messages[0]) |
66 | 93 |
67 def test_extract_plural_form(self): | 94 def test_extract_plural_form(self): |
68 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> | 95 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> |
69 ${ngettext("Singular", "Plural", num)} | 96 ${ngettext("Singular", "Plural", num)} |
70 </html>""") | 97 </html>""") |
71 translator = Translator() | 98 translator = Translator() |
72 messages = list(translator.extract(tmpl.stream)) | 99 messages = list(translator.extract(tmpl.stream)) |
73 self.assertEqual(1, len(messages)) | 100 self.assertEqual(1, len(messages)) |
74 self.assertEqual((2, 'ngettext', (u'Singular', u'Plural', None), []), | 101 self.assertEqual((2, 'ngettext', ('Singular', 'Plural', None), []), |
75 messages[0]) | 102 messages[0]) |
76 | 103 |
77 def test_extract_funky_plural_form(self): | 104 def test_extract_funky_plural_form(self): |
78 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> | 105 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> |
79 ${ngettext(len(items), *widget.display_names)} | 106 ${ngettext(len(items), *widget.display_names)} |
97 <span title="Foo"></span> | 124 <span title="Foo"></span> |
98 </html>""") | 125 </html>""") |
99 translator = Translator() | 126 translator = Translator() |
100 messages = list(translator.extract(tmpl.stream)) | 127 messages = list(translator.extract(tmpl.stream)) |
101 self.assertEqual(1, len(messages)) | 128 self.assertEqual(1, len(messages)) |
102 self.assertEqual((2, None, u'Foo', []), messages[0]) | 129 self.assertEqual((2, None, 'Foo', []), messages[0]) |
103 | 130 |
104 def test_extract_attribute_expr(self): | 131 def test_extract_attribute_expr(self): |
105 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> | 132 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> |
106 <input type="submit" value="${_('Save')}" /> | 133 <input type="submit" value="${_('Save')}" /> |
107 </html>""") | 134 </html>""") |
108 translator = Translator() | 135 translator = Translator() |
109 messages = list(translator.extract(tmpl.stream)) | 136 messages = list(translator.extract(tmpl.stream)) |
110 self.assertEqual(1, len(messages)) | 137 self.assertEqual(1, len(messages)) |
111 self.assertEqual((2, '_', u'Save', []), messages[0]) | 138 self.assertEqual((2, '_', 'Save', []), messages[0]) |
112 | 139 |
113 def test_extract_non_included_attribute_interpolated(self): | 140 def test_extract_non_included_attribute_interpolated(self): |
114 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> | 141 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> |
115 <a href="#anchor_${num}">Foo</a> | 142 <a href="#anchor_${num}">Foo</a> |
116 </html>""") | 143 </html>""") |
117 translator = Translator() | 144 translator = Translator() |
118 messages = list(translator.extract(tmpl.stream)) | 145 messages = list(translator.extract(tmpl.stream)) |
119 self.assertEqual(1, len(messages)) | 146 self.assertEqual(1, len(messages)) |
120 self.assertEqual((2, None, u'Foo', []), messages[0]) | 147 self.assertEqual((2, None, 'Foo', []), messages[0]) |
121 | 148 |
122 def test_extract_text_from_sub(self): | 149 def test_extract_text_from_sub(self): |
123 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> | 150 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> |
124 <py:if test="foo">Foo</py:if> | 151 <py:if test="foo">Foo</py:if> |
125 </html>""") | 152 </html>""") |
126 translator = Translator() | 153 translator = Translator() |
127 messages = list(translator.extract(tmpl.stream)) | 154 messages = list(translator.extract(tmpl.stream)) |
128 self.assertEqual(1, len(messages)) | 155 self.assertEqual(1, len(messages)) |
129 self.assertEqual((2, None, u'Foo', []), messages[0]) | 156 self.assertEqual((2, None, 'Foo', []), messages[0]) |
130 | 157 |
131 def test_ignore_tag_with_fixed_xml_lang(self): | 158 def test_ignore_tag_with_fixed_xml_lang(self): |
132 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> | 159 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> |
133 <p xml:lang="en">(c) 2007 Edgewall Software</p> | 160 <p xml:lang="en">(c) 2007 Edgewall Software</p> |
134 </html>""") | 161 </html>""") |
141 <p xml:lang="${lang}">(c) 2007 Edgewall Software</p> | 168 <p xml:lang="${lang}">(c) 2007 Edgewall Software</p> |
142 </html>""") | 169 </html>""") |
143 translator = Translator() | 170 translator = Translator() |
144 messages = list(translator.extract(tmpl.stream)) | 171 messages = list(translator.extract(tmpl.stream)) |
145 self.assertEqual(1, len(messages)) | 172 self.assertEqual(1, len(messages)) |
146 self.assertEqual((2, None, u'(c) 2007 Edgewall Software', []), | 173 self.assertEqual((2, None, '(c) 2007 Edgewall Software', []), |
147 messages[0]) | 174 messages[0]) |
148 | 175 |
149 def test_ignore_attribute_with_expression(self): | 176 def test_ignore_attribute_with_expression(self): |
150 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> | 177 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> |
151 <input type="submit" value="Reply" title="Reply to comment $num" /> | 178 <input type="submit" value="Reply" title="Reply to comment $num" /> |
152 </html>""") | 179 </html>""") |
153 translator = Translator() | 180 translator = Translator() |
154 messages = list(translator.extract(tmpl.stream)) | 181 messages = list(translator.extract(tmpl.stream)) |
155 self.assertEqual(0, len(messages)) | 182 self.assertEqual(0, len(messages)) |
156 | 183 |
184 def test_translate_with_translations_object(self): | |
185 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
186 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
187 <p i18n:msg="" i18n:comment="As in foo bar">Foo</p> | |
188 </html>""") | |
189 translator = Translator(DummyTranslations({'Foo': 'Voh'})) | |
190 translator.setup(tmpl) | |
191 self.assertEqual("""<html> | |
192 <p>Voh</p> | |
193 </html>""", tmpl.generate().render()) | |
194 | |
195 | |
196 class MsgDirectiveTestCase(unittest.TestCase): | |
197 | |
157 def test_extract_i18n_msg(self): | 198 def test_extract_i18n_msg(self): |
158 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | 199 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" |
159 xmlns:i18n="http://genshi.edgewall.org/i18n"> | 200 xmlns:i18n="http://genshi.edgewall.org/i18n"> |
160 <p i18n:msg=""> | 201 <p i18n:msg=""> |
161 Please see <a href="help.html">Help</a> for details. | 202 Please see <a href="help.html">Help</a> for details. |
162 </p> | 203 </p> |
163 </html>""") | 204 </html>""") |
164 translator = Translator() | 205 translator = Translator() |
206 tmpl.add_directives(Translator.NAMESPACE, translator) | |
165 messages = list(translator.extract(tmpl.stream)) | 207 messages = list(translator.extract(tmpl.stream)) |
166 self.assertEqual(1, len(messages)) | 208 self.assertEqual(1, len(messages)) |
167 self.assertEqual('Please see [1:Help] for details.', messages[0][2]) | 209 self.assertEqual('Please see [1:Help] for details.', messages[0][2]) |
168 | 210 |
169 def test_translate_i18n_msg(self): | 211 def test_translate_i18n_msg(self): |
173 Please see <a href="help.html">Help</a> for details. | 215 Please see <a href="help.html">Help</a> for details. |
174 </p> | 216 </p> |
175 </html>""") | 217 </html>""") |
176 gettext = lambda s: u"Für Details siehe bitte [1:Hilfe]." | 218 gettext = lambda s: u"Für Details siehe bitte [1:Hilfe]." |
177 translator = Translator(gettext) | 219 translator = Translator(gettext) |
178 tmpl.filters.insert(0, translator) | 220 translator.setup(tmpl) |
179 tmpl.add_directives(Translator.NAMESPACE, translator) | |
180 self.assertEqual("""<html> | 221 self.assertEqual("""<html> |
181 <p>Für Details siehe bitte <a href="help.html">Hilfe</a>.</p> | 222 <p>Für Details siehe bitte <a href="help.html">Hilfe</a>.</p> |
182 </html>""", tmpl.generate().render()) | 223 </html>""", tmpl.generate().render()) |
224 | |
225 def test_extract_i18n_msg_nonewline(self): | |
226 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
227 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
228 <p i18n:msg="">Please see <a href="help.html">Help</a></p> | |
229 </html>""") | |
230 translator = Translator() | |
231 tmpl.add_directives(Translator.NAMESPACE, translator) | |
232 messages = list(translator.extract(tmpl.stream)) | |
233 self.assertEqual(1, len(messages)) | |
234 self.assertEqual('Please see [1:Help]', messages[0][2]) | |
235 | |
236 def test_translate_i18n_msg_nonewline(self): | |
237 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
238 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
239 <p i18n:msg="">Please see <a href="help.html">Help</a></p> | |
240 </html>""") | |
241 gettext = lambda s: u"Für Details siehe bitte [1:Hilfe]" | |
242 translator = Translator(gettext) | |
243 translator.setup(tmpl) | |
244 self.assertEqual("""<html> | |
245 <p>Für Details siehe bitte <a href="help.html">Hilfe</a></p> | |
246 </html>""", tmpl.generate().render()) | |
247 | |
248 def test_extract_i18n_msg_elt_nonewline(self): | |
249 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
250 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
251 <i18n:msg>Please see <a href="help.html">Help</a></i18n:msg> | |
252 </html>""") | |
253 translator = Translator() | |
254 tmpl.add_directives(Translator.NAMESPACE, translator) | |
255 messages = list(translator.extract(tmpl.stream)) | |
256 self.assertEqual(1, len(messages)) | |
257 self.assertEqual('Please see [1:Help]', messages[0][2]) | |
258 | |
259 def test_translate_i18n_msg_elt_nonewline(self): | |
260 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
261 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
262 <i18n:msg>Please see <a href="help.html">Help</a></i18n:msg> | |
263 </html>""") | |
264 gettext = lambda s: u"Für Details siehe bitte [1:Hilfe]" | |
265 translator = Translator(gettext) | |
266 translator.setup(tmpl) | |
267 self.assertEqual("""<html> | |
268 Für Details siehe bitte <a href="help.html">Hilfe</a> | |
269 </html>""", tmpl.generate().render()) | |
270 | |
271 def test_extract_i18n_msg_with_attributes(self): | |
272 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
273 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
274 <p i18n:msg="" title="A helpful paragraph"> | |
275 Please see <a href="help.html" title="Click for help">Help</a> | |
276 </p> | |
277 </html>""") | |
278 translator = Translator() | |
279 translator.setup(tmpl) | |
280 messages = list(translator.extract(tmpl.stream)) | |
281 self.assertEqual(3, len(messages)) | |
282 self.assertEqual('A helpful paragraph', messages[0][2]) | |
283 self.assertEqual(3, messages[0][0]) | |
284 self.assertEqual('Click for help', messages[1][2]) | |
285 self.assertEqual(4, messages[1][0]) | |
286 self.assertEqual('Please see [1:Help]', messages[2][2]) | |
287 self.assertEqual(3, messages[2][0]) | |
288 | |
289 def test_translate_i18n_msg_with_attributes(self): | |
290 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
291 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
292 <p i18n:msg="" title="A helpful paragraph"> | |
293 Please see <a href="help.html" title="Click for help">Help</a> | |
294 </p> | |
295 </html>""") | |
296 translator = Translator(lambda msgid: { | |
297 'A helpful paragraph': 'Ein hilfreicher Absatz', | |
298 'Click for help': u'Klicken für Hilfe', | |
299 'Please see [1:Help]': u'Siehe bitte [1:Hilfe]' | |
300 }[msgid]) | |
301 translator.setup(tmpl) | |
302 self.assertEqual(u"""<html> | |
303 <p title="Ein hilfreicher Absatz">Siehe bitte <a href="help.html" title="Klicken für Hilfe">Hilfe</a></p> | |
304 </html>""", tmpl.generate().render(encoding=None)) | |
305 | |
306 def test_extract_i18n_msg_with_dynamic_attributes(self): | |
307 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
308 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
309 <p i18n:msg="" title="${_('A helpful paragraph')}"> | |
310 Please see <a href="help.html" title="${_('Click for help')}">Help</a> | |
311 </p> | |
312 </html>""") | |
313 translator = Translator() | |
314 translator.setup(tmpl) | |
315 messages = list(translator.extract(tmpl.stream)) | |
316 self.assertEqual(3, len(messages)) | |
317 self.assertEqual('A helpful paragraph', messages[0][2]) | |
318 self.assertEqual(3, messages[0][0]) | |
319 self.assertEqual('Click for help', messages[1][2]) | |
320 self.assertEqual(4, messages[1][0]) | |
321 self.assertEqual('Please see [1:Help]', messages[2][2]) | |
322 self.assertEqual(3, messages[2][0]) | |
323 | |
324 def test_translate_i18n_msg_with_dynamic_attributes(self): | |
325 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
326 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
327 <p i18n:msg="" title="${_('A helpful paragraph')}"> | |
328 Please see <a href="help.html" title="${_('Click for help')}">Help</a> | |
329 </p> | |
330 </html>""") | |
331 translator = Translator(lambda msgid: { | |
332 'A helpful paragraph': 'Ein hilfreicher Absatz', | |
333 'Click for help': u'Klicken für Hilfe', | |
334 'Please see [1:Help]': u'Siehe bitte [1:Hilfe]' | |
335 }[msgid]) | |
336 translator.setup(tmpl) | |
337 self.assertEqual(u"""<html> | |
338 <p title="Ein hilfreicher Absatz">Siehe bitte <a href="help.html" title="Klicken für Hilfe">Hilfe</a></p> | |
339 </html>""", tmpl.generate(_=translator.translate).render(encoding=None)) | |
340 | |
341 def test_extract_i18n_msg_as_element_with_attributes(self): | |
342 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
343 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
344 <i18n:msg params=""> | |
345 Please see <a href="help.html" title="Click for help">Help</a> | |
346 </i18n:msg> | |
347 </html>""") | |
348 translator = Translator() | |
349 translator.setup(tmpl) | |
350 messages = list(translator.extract(tmpl.stream)) | |
351 self.assertEqual(2, len(messages)) | |
352 self.assertEqual('Click for help', messages[0][2]) | |
353 self.assertEqual(4, messages[0][0]) | |
354 self.assertEqual('Please see [1:Help]', messages[1][2]) | |
355 self.assertEqual(3, messages[1][0]) | |
356 | |
357 def test_translate_i18n_msg_as_element_with_attributes(self): | |
358 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
359 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
360 <i18n:msg params=""> | |
361 Please see <a href="help.html" title="Click for help">Help</a> | |
362 </i18n:msg> | |
363 </html>""") | |
364 translator = Translator(lambda msgid: { | |
365 'Click for help': u'Klicken für Hilfe', | |
366 'Please see [1:Help]': u'Siehe bitte [1:Hilfe]' | |
367 }[msgid]) | |
368 translator.setup(tmpl) | |
369 self.assertEqual(u"""<html> | |
370 Siehe bitte <a href="help.html" title="Klicken für Hilfe">Hilfe</a> | |
371 </html>""", tmpl.generate().render(encoding=None)) | |
183 | 372 |
184 def test_extract_i18n_msg_nested(self): | 373 def test_extract_i18n_msg_nested(self): |
185 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | 374 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" |
186 xmlns:i18n="http://genshi.edgewall.org/i18n"> | 375 xmlns:i18n="http://genshi.edgewall.org/i18n"> |
187 <p i18n:msg=""> | 376 <p i18n:msg=""> |
188 Please see <a href="help.html"><em>Help</em> page</a> for details. | 377 Please see <a href="help.html"><em>Help</em> page</a> for details. |
189 </p> | 378 </p> |
190 </html>""") | 379 </html>""") |
191 translator = Translator() | 380 translator = Translator() |
381 tmpl.add_directives(Translator.NAMESPACE, translator) | |
192 messages = list(translator.extract(tmpl.stream)) | 382 messages = list(translator.extract(tmpl.stream)) |
193 self.assertEqual(1, len(messages)) | 383 self.assertEqual(1, len(messages)) |
194 self.assertEqual('Please see [1:[2:Help] page] for details.', | 384 self.assertEqual('Please see [1:[2:Help] page] for details.', |
195 messages[0][2]) | 385 messages[0][2]) |
196 | 386 |
201 Please see <a href="help.html"><em>Help</em> page</a> for details. | 391 Please see <a href="help.html"><em>Help</em> page</a> for details. |
202 </p> | 392 </p> |
203 </html>""") | 393 </html>""") |
204 gettext = lambda s: u"Für Details siehe bitte [1:[2:Hilfeseite]]." | 394 gettext = lambda s: u"Für Details siehe bitte [1:[2:Hilfeseite]]." |
205 translator = Translator(gettext) | 395 translator = Translator(gettext) |
206 tmpl.filters.insert(0, translator) | 396 translator.setup(tmpl) |
207 tmpl.add_directives(Translator.NAMESPACE, translator) | |
208 self.assertEqual("""<html> | 397 self.assertEqual("""<html> |
209 <p>Für Details siehe bitte <a href="help.html"><em>Hilfeseite</em></a>.</p> | 398 <p>Für Details siehe bitte <a href="help.html"><em>Hilfeseite</em></a>.</p> |
399 </html>""", tmpl.generate().render()) | |
400 | |
401 def test_extract_i18n_msg_label_with_nested_input(self): | |
402 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
403 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
404 <div i18n:msg=""> | |
405 <label><input type="text" size="3" name="daysback" value="30" /> days back</label> | |
406 </div> | |
407 </html>""") | |
408 translator = Translator() | |
409 tmpl.add_directives(Translator.NAMESPACE, translator) | |
410 messages = list(translator.extract(tmpl.stream)) | |
411 self.assertEqual(1, len(messages)) | |
412 self.assertEqual('[1:[2:] days back]', | |
413 messages[0][2]) | |
414 | |
415 def test_translate_i18n_msg_label_with_nested_input(self): | |
416 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
417 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
418 <div i18n:msg=""> | |
419 <label><input type="text" size="3" name="daysback" value="30" /> foo bar</label> | |
420 </div> | |
421 </html>""") | |
422 gettext = lambda s: "[1:[2:] foo bar]" | |
423 translator = Translator(gettext) | |
424 translator.setup(tmpl) | |
425 self.assertEqual("""<html> | |
426 <div><label><input type="text" size="3" name="daysback" value="30"/> foo bar</label></div> | |
210 </html>""", tmpl.generate().render()) | 427 </html>""", tmpl.generate().render()) |
211 | 428 |
212 def test_extract_i18n_msg_empty(self): | 429 def test_extract_i18n_msg_empty(self): |
213 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | 430 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" |
214 xmlns:i18n="http://genshi.edgewall.org/i18n"> | 431 xmlns:i18n="http://genshi.edgewall.org/i18n"> |
215 <p i18n:msg=""> | 432 <p i18n:msg=""> |
216 Show me <input type="text" name="num" /> entries per page. | 433 Show me <input type="text" name="num" /> entries per page. |
217 </p> | 434 </p> |
218 </html>""") | 435 </html>""") |
219 translator = Translator() | 436 translator = Translator() |
437 tmpl.add_directives(Translator.NAMESPACE, translator) | |
220 messages = list(translator.extract(tmpl.stream)) | 438 messages = list(translator.extract(tmpl.stream)) |
221 self.assertEqual(1, len(messages)) | 439 self.assertEqual(1, len(messages)) |
222 self.assertEqual('Show me [1:] entries per page.', messages[0][2]) | 440 self.assertEqual('Show me [1:] entries per page.', messages[0][2]) |
223 | 441 |
224 def test_translate_i18n_msg_empty(self): | 442 def test_translate_i18n_msg_empty(self): |
228 Show me <input type="text" name="num" /> entries per page. | 446 Show me <input type="text" name="num" /> entries per page. |
229 </p> | 447 </p> |
230 </html>""") | 448 </html>""") |
231 gettext = lambda s: u"[1:] Einträge pro Seite anzeigen." | 449 gettext = lambda s: u"[1:] Einträge pro Seite anzeigen." |
232 translator = Translator(gettext) | 450 translator = Translator(gettext) |
233 tmpl.filters.insert(0, translator) | 451 translator.setup(tmpl) |
234 tmpl.add_directives(Translator.NAMESPACE, translator) | |
235 self.assertEqual("""<html> | 452 self.assertEqual("""<html> |
236 <p><input type="text" name="num"/> Einträge pro Seite anzeigen.</p> | 453 <p><input type="text" name="num"/> Einträge pro Seite anzeigen.</p> |
237 </html>""", tmpl.generate().render()) | 454 </html>""", tmpl.generate().render()) |
238 | 455 |
239 def test_extract_i18n_msg_multiple(self): | 456 def test_extract_i18n_msg_multiple(self): |
242 <p i18n:msg=""> | 459 <p i18n:msg=""> |
243 Please see <a href="help.html">Help</a> for <em>details</em>. | 460 Please see <a href="help.html">Help</a> for <em>details</em>. |
244 </p> | 461 </p> |
245 </html>""") | 462 </html>""") |
246 translator = Translator() | 463 translator = Translator() |
464 tmpl.add_directives(Translator.NAMESPACE, translator) | |
247 messages = list(translator.extract(tmpl.stream)) | 465 messages = list(translator.extract(tmpl.stream)) |
248 self.assertEqual(1, len(messages)) | 466 self.assertEqual(1, len(messages)) |
249 self.assertEqual('Please see [1:Help] for [2:details].', messages[0][2]) | 467 self.assertEqual('Please see [1:Help] for [2:details].', messages[0][2]) |
250 | 468 |
251 def test_translate_i18n_msg_multiple(self): | 469 def test_translate_i18n_msg_multiple(self): |
255 Please see <a href="help.html">Help</a> for <em>details</em>. | 473 Please see <a href="help.html">Help</a> for <em>details</em>. |
256 </p> | 474 </p> |
257 </html>""") | 475 </html>""") |
258 gettext = lambda s: u"Für [2:Details] siehe bitte [1:Hilfe]." | 476 gettext = lambda s: u"Für [2:Details] siehe bitte [1:Hilfe]." |
259 translator = Translator(gettext) | 477 translator = Translator(gettext) |
260 tmpl.filters.insert(0, translator) | 478 translator.setup(tmpl) |
261 tmpl.add_directives(Translator.NAMESPACE, translator) | |
262 self.assertEqual("""<html> | 479 self.assertEqual("""<html> |
263 <p>Für <em>Details</em> siehe bitte <a href="help.html">Hilfe</a>.</p> | 480 <p>Für <em>Details</em> siehe bitte <a href="help.html">Hilfe</a>.</p> |
264 </html>""", tmpl.generate().render()) | 481 </html>""", tmpl.generate().render()) |
265 | 482 |
266 def test_extract_i18n_msg_multiple_empty(self): | 483 def test_extract_i18n_msg_multiple_empty(self): |
269 <p i18n:msg=""> | 486 <p i18n:msg=""> |
270 Show me <input type="text" name="num" /> entries per page, starting at page <input type="text" name="num" />. | 487 Show me <input type="text" name="num" /> entries per page, starting at page <input type="text" name="num" />. |
271 </p> | 488 </p> |
272 </html>""") | 489 </html>""") |
273 translator = Translator() | 490 translator = Translator() |
491 tmpl.add_directives(Translator.NAMESPACE, translator) | |
274 messages = list(translator.extract(tmpl.stream)) | 492 messages = list(translator.extract(tmpl.stream)) |
275 self.assertEqual(1, len(messages)) | 493 self.assertEqual(1, len(messages)) |
276 self.assertEqual('Show me [1:] entries per page, starting at page [2:].', | 494 self.assertEqual('Show me [1:] entries per page, starting at page [2:].', |
277 messages[0][2]) | 495 messages[0][2]) |
278 | 496 |
283 Show me <input type="text" name="num" /> entries per page, starting at page <input type="text" name="num" />. | 501 Show me <input type="text" name="num" /> entries per page, starting at page <input type="text" name="num" />. |
284 </p> | 502 </p> |
285 </html>""") | 503 </html>""") |
286 gettext = lambda s: u"[1:] Einträge pro Seite, beginnend auf Seite [2:]." | 504 gettext = lambda s: u"[1:] Einträge pro Seite, beginnend auf Seite [2:]." |
287 translator = Translator(gettext) | 505 translator = Translator(gettext) |
288 tmpl.filters.insert(0, translator) | 506 translator.setup(tmpl) |
289 tmpl.add_directives(Translator.NAMESPACE, translator) | |
290 self.assertEqual("""<html> | 507 self.assertEqual("""<html> |
291 <p><input type="text" name="num"/> Eintr\xc3\xa4ge pro Seite, beginnend auf Seite <input type="text" name="num"/>.</p> | 508 <p><input type="text" name="num"/> Eintr\xc3\xa4ge pro Seite, beginnend auf Seite <input type="text" name="num"/>.</p> |
292 </html>""", tmpl.generate().render()) | 509 </html>""", tmpl.generate().render()) |
293 | 510 |
294 def test_extract_i18n_msg_with_param(self): | 511 def test_extract_i18n_msg_with_param(self): |
297 <p i18n:msg="name"> | 514 <p i18n:msg="name"> |
298 Hello, ${user.name}! | 515 Hello, ${user.name}! |
299 </p> | 516 </p> |
300 </html>""") | 517 </html>""") |
301 translator = Translator() | 518 translator = Translator() |
519 tmpl.add_directives(Translator.NAMESPACE, translator) | |
302 messages = list(translator.extract(tmpl.stream)) | 520 messages = list(translator.extract(tmpl.stream)) |
303 self.assertEqual(1, len(messages)) | 521 self.assertEqual(1, len(messages)) |
304 self.assertEqual('Hello, %(name)s!', messages[0][2]) | 522 self.assertEqual('Hello, %(name)s!', messages[0][2]) |
305 | 523 |
306 def test_translate_i18n_msg_with_param(self): | 524 def test_translate_i18n_msg_with_param(self): |
310 Hello, ${user.name}! | 528 Hello, ${user.name}! |
311 </p> | 529 </p> |
312 </html>""") | 530 </html>""") |
313 gettext = lambda s: u"Hallo, %(name)s!" | 531 gettext = lambda s: u"Hallo, %(name)s!" |
314 translator = Translator(gettext) | 532 translator = Translator(gettext) |
315 tmpl.filters.insert(0, translator) | 533 translator.setup(tmpl) |
316 tmpl.add_directives(Translator.NAMESPACE, translator) | |
317 self.assertEqual("""<html> | 534 self.assertEqual("""<html> |
318 <p>Hallo, Jim!</p> | 535 <p>Hallo, Jim!</p> |
319 </html>""", tmpl.generate(user=dict(name='Jim')).render()) | 536 </html>""", tmpl.generate(user=dict(name='Jim')).render()) |
320 | 537 |
321 def test_translate_i18n_msg_with_param_reordered(self): | 538 def test_translate_i18n_msg_with_param_reordered(self): |
325 Hello, ${user.name}! | 542 Hello, ${user.name}! |
326 </p> | 543 </p> |
327 </html>""") | 544 </html>""") |
328 gettext = lambda s: u"%(name)s, sei gegrüßt!" | 545 gettext = lambda s: u"%(name)s, sei gegrüßt!" |
329 translator = Translator(gettext) | 546 translator = Translator(gettext) |
330 tmpl.filters.insert(0, translator) | 547 translator.setup(tmpl) |
331 tmpl.add_directives(Translator.NAMESPACE, translator) | |
332 self.assertEqual("""<html> | 548 self.assertEqual("""<html> |
333 <p>Jim, sei gegrüßt!</p> | 549 <p>Jim, sei gegrüßt!</p> |
334 </html>""", tmpl.generate(user=dict(name='Jim')).render()) | 550 </html>""", tmpl.generate(user=dict(name='Jim')).render()) |
335 | 551 |
336 def test_translate_i18n_msg_with_attribute_param(self): | 552 def test_translate_i18n_msg_with_attribute_param(self): |
340 Hello, <a href="#${anchor}">dude</a>! | 556 Hello, <a href="#${anchor}">dude</a>! |
341 </p> | 557 </p> |
342 </html>""") | 558 </html>""") |
343 gettext = lambda s: u"Sei gegrüßt, [1:Alter]!" | 559 gettext = lambda s: u"Sei gegrüßt, [1:Alter]!" |
344 translator = Translator(gettext) | 560 translator = Translator(gettext) |
345 tmpl.filters.insert(0, translator) | 561 translator.setup(tmpl) |
346 tmpl.add_directives(Translator.NAMESPACE, translator) | |
347 self.assertEqual("""<html> | 562 self.assertEqual("""<html> |
348 <p>Sei gegrüßt, <a href="#42">Alter</a>!</p> | 563 <p>Sei gegrüßt, <a href="#42">Alter</a>!</p> |
349 </html>""", tmpl.generate(anchor='42').render()) | 564 </html>""", tmpl.generate(anchor='42').render()) |
350 | 565 |
351 def test_extract_i18n_msg_with_two_params(self): | 566 def test_extract_i18n_msg_with_two_params(self): |
354 <p i18n:msg="name, time"> | 569 <p i18n:msg="name, time"> |
355 Posted by ${post.author} at ${entry.time.strftime('%H:%m')} | 570 Posted by ${post.author} at ${entry.time.strftime('%H:%m')} |
356 </p> | 571 </p> |
357 </html>""") | 572 </html>""") |
358 translator = Translator() | 573 translator = Translator() |
574 tmpl.add_directives(Translator.NAMESPACE, translator) | |
359 messages = list(translator.extract(tmpl.stream)) | 575 messages = list(translator.extract(tmpl.stream)) |
360 self.assertEqual(1, len(messages)) | 576 self.assertEqual(1, len(messages)) |
361 self.assertEqual('Posted by %(name)s at %(time)s', messages[0][2]) | 577 self.assertEqual('Posted by %(name)s at %(time)s', messages[0][2]) |
362 | 578 |
363 def test_translate_i18n_msg_with_two_params(self): | 579 def test_translate_i18n_msg_with_two_params(self): |
367 Written by ${entry.author} at ${entry.time.strftime('%H:%M')} | 583 Written by ${entry.author} at ${entry.time.strftime('%H:%M')} |
368 </p> | 584 </p> |
369 </html>""") | 585 </html>""") |
370 gettext = lambda s: u"%(name)s schrieb dies um %(time)s" | 586 gettext = lambda s: u"%(name)s schrieb dies um %(time)s" |
371 translator = Translator(gettext) | 587 translator = Translator(gettext) |
372 tmpl.filters.insert(0, translator) | 588 translator.setup(tmpl) |
373 tmpl.add_directives(Translator.NAMESPACE, translator) | |
374 entry = { | 589 entry = { |
375 'author': 'Jim', | 590 'author': 'Jim', |
376 'time': datetime(2008, 4, 1, 14, 30) | 591 'time': datetime(2008, 4, 1, 14, 30) |
377 } | 592 } |
378 self.assertEqual("""<html> | 593 self.assertEqual("""<html> |
385 <p i18n:msg=""> | 600 <p i18n:msg=""> |
386 Show me <input type="text" name="num" py:attrs="{'value': x}" /> entries per page. | 601 Show me <input type="text" name="num" py:attrs="{'value': x}" /> entries per page. |
387 </p> | 602 </p> |
388 </html>""") | 603 </html>""") |
389 translator = Translator() | 604 translator = Translator() |
605 tmpl.add_directives(Translator.NAMESPACE, translator) | |
390 messages = list(translator.extract(tmpl.stream)) | 606 messages = list(translator.extract(tmpl.stream)) |
391 self.assertEqual(1, len(messages)) | 607 self.assertEqual(1, len(messages)) |
392 self.assertEqual('Show me [1:] entries per page.', messages[0][2]) | 608 self.assertEqual('Show me [1:] entries per page.', messages[0][2]) |
393 | 609 |
394 # FIXME: this currently fails :-/ | 610 def test_translate_i18n_msg_with_directive(self): |
395 # def test_translate_i18n_msg_with_directive(self): | 611 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" |
396 # tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | 612 xmlns:i18n="http://genshi.edgewall.org/i18n"> |
397 # xmlns:i18n="http://genshi.edgewall.org/i18n"> | 613 <p i18n:msg=""> |
398 # <p i18n:msg=""> | 614 Show me <input type="text" name="num" py:attrs="{'value': 'x'}" /> entries per page. |
399 # Show me <input type="text" name="num" py:attrs="{'value': x}" /> entries per page. | 615 </p> |
400 # </p> | 616 </html>""") |
401 # </html>""") | 617 gettext = lambda s: u"[1:] Einträge pro Seite anzeigen." |
402 # gettext = lambda s: u"[1:] Einträge pro Seite anzeigen." | 618 translator = Translator(gettext) |
403 # tmpl.filters.insert(0, Translator(gettext)) | 619 translator.setup(tmpl) |
404 # self.assertEqual("""<html> | 620 self.assertEqual("""<html> |
405 # <p><input type="text" name="num" value="x"/> Einträge pro Seite anzeigen.</p> | 621 <p><input type="text" name="num" value="x"/> Einträge pro Seite anzeigen.</p> |
406 # </html>""", tmpl.generate().render()) | 622 </html>""", tmpl.generate().render()) |
407 | 623 |
408 def test_extract_i18n_msg_with_comment(self): | 624 def test_extract_i18n_msg_with_comment(self): |
409 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | 625 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" |
410 xmlns:i18n="http://genshi.edgewall.org/i18n"> | 626 xmlns:i18n="http://genshi.edgewall.org/i18n"> |
627 <p i18n:comment="As in foo bar" i18n:msg="">Foo</p> | |
628 </html>""") | |
629 translator = Translator() | |
630 tmpl.add_directives(Translator.NAMESPACE, translator) | |
631 messages = list(translator.extract(tmpl.stream)) | |
632 self.assertEqual(1, len(messages)) | |
633 self.assertEqual((3, None, 'Foo', ['As in foo bar']), messages[0]) | |
634 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
635 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
411 <p i18n:msg="" i18n:comment="As in foo bar">Foo</p> | 636 <p i18n:msg="" i18n:comment="As in foo bar">Foo</p> |
412 </html>""") | 637 </html>""") |
413 translator = Translator() | 638 translator = Translator() |
414 messages = list(translator.extract(tmpl.stream)) | 639 tmpl.add_directives(Translator.NAMESPACE, translator) |
415 self.assertEqual(1, len(messages)) | 640 messages = list(translator.extract(tmpl.stream)) |
416 self.assertEqual((3, None, u'Foo', ['As in foo bar']), messages[0]) | 641 self.assertEqual(1, len(messages)) |
642 self.assertEqual((3, None, 'Foo', ['As in foo bar']), messages[0]) | |
417 | 643 |
418 def test_translate_i18n_msg_with_comment(self): | 644 def test_translate_i18n_msg_with_comment(self): |
419 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | 645 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" |
420 xmlns:i18n="http://genshi.edgewall.org/i18n"> | 646 xmlns:i18n="http://genshi.edgewall.org/i18n"> |
421 <p i18n:msg="" i18n:comment="As in foo bar">Foo</p> | 647 <p i18n:msg="" i18n:comment="As in foo bar">Foo</p> |
422 </html>""") | 648 </html>""") |
423 gettext = lambda s: u"Voh" | 649 gettext = lambda s: u"Voh" |
424 translator = Translator(gettext) | 650 translator = Translator(gettext) |
425 tmpl.filters.insert(0, translator) | 651 translator.setup(tmpl) |
426 tmpl.add_directives(Translator.NAMESPACE, translator) | |
427 self.assertEqual("""<html> | 652 self.assertEqual("""<html> |
428 <p>Voh</p> | 653 <p>Voh</p> |
429 </html>""", tmpl.generate().render()) | 654 </html>""", tmpl.generate().render()) |
430 | 655 |
431 def test_extract_i18n_msg_with_attr(self): | 656 def test_extract_i18n_msg_with_attr(self): |
434 <p i18n:msg="" title="Foo bar">Foo</p> | 659 <p i18n:msg="" title="Foo bar">Foo</p> |
435 </html>""") | 660 </html>""") |
436 translator = Translator() | 661 translator = Translator() |
437 messages = list(translator.extract(tmpl.stream)) | 662 messages = list(translator.extract(tmpl.stream)) |
438 self.assertEqual(2, len(messages)) | 663 self.assertEqual(2, len(messages)) |
439 self.assertEqual((3, None, u'Foo bar', []), messages[0]) | 664 self.assertEqual((3, None, 'Foo bar', []), messages[0]) |
440 self.assertEqual((3, None, u'Foo', []), messages[1]) | 665 self.assertEqual((3, None, 'Foo', []), messages[1]) |
441 | 666 |
442 def test_translate_i18n_msg_with_attr(self): | 667 def test_translate_i18n_msg_with_attr(self): |
443 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | 668 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" |
444 xmlns:i18n="http://genshi.edgewall.org/i18n"> | 669 xmlns:i18n="http://genshi.edgewall.org/i18n"> |
445 <p i18n:msg="" title="Foo bar">Foo</p> | 670 <p i18n:msg="" title="Foo bar">Foo</p> |
446 </html>""") | 671 </html>""") |
447 gettext = lambda s: u"Voh" | 672 gettext = lambda s: u"Voh" |
448 translator = Translator(DummyTranslations({ | 673 translator = Translator(DummyTranslations({ |
449 'Foo': u'Voh', | 674 'Foo': 'Voh', |
450 'Foo bar': u'Voh bär' | 675 'Foo bar': u'Voh bär' |
451 })) | 676 })) |
452 tmpl.filters.insert(0, translator) | 677 tmpl.filters.insert(0, translator) |
453 tmpl.add_directives(Translator.NAMESPACE, translator) | 678 tmpl.add_directives(Translator.NAMESPACE, translator) |
454 self.assertEqual("""<html> | 679 self.assertEqual("""<html> |
455 <p title="Voh bär">Voh</p> | 680 <p title="Voh bär">Voh</p> |
456 </html>""", tmpl.generate().render()) | 681 </html>""", tmpl.generate().render()) |
457 | 682 |
458 def test_translate_with_translations_object(self): | 683 def test_translate_i18n_msg_and_py_strip_directives(self): |
459 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | 684 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" |
460 xmlns:i18n="http://genshi.edgewall.org/i18n"> | 685 xmlns:i18n="http://genshi.edgewall.org/i18n"> |
461 <p i18n:msg="" i18n:comment="As in foo bar">Foo</p> | 686 <p i18n:msg="" py:strip="">Foo</p> |
687 <p py:strip="" i18n:msg="">Foo</p> | |
462 </html>""") | 688 </html>""") |
463 translator = Translator(DummyTranslations({'Foo': 'Voh'})) | 689 translator = Translator(DummyTranslations({'Foo': 'Voh'})) |
464 tmpl.filters.insert(0, translator) | 690 translator.setup(tmpl) |
465 tmpl.add_directives(Translator.NAMESPACE, translator) | 691 self.assertEqual("""<html> |
692 Voh | |
693 Voh | |
694 </html>""", tmpl.generate().render()) | |
695 | |
696 def test_i18n_msg_ticket_300_extract(self): | |
697 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
698 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
699 <i18n:msg params="date, author"> | |
700 Changed ${ '10/12/2008' } ago by ${ 'me, the author' } | |
701 </i18n:msg> | |
702 </html>""") | |
703 translator = Translator() | |
704 tmpl.add_directives(Translator.NAMESPACE, translator) | |
705 messages = list(translator.extract(tmpl.stream)) | |
706 self.assertEqual(1, len(messages)) | |
707 self.assertEqual( | |
708 (3, None, 'Changed %(date)s ago by %(author)s', []), messages[0] | |
709 ) | |
710 | |
711 def test_i18n_msg_ticket_300_translate(self): | |
712 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
713 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
714 <i18n:msg params="date, author"> | |
715 Changed ${ date } ago by ${ author } | |
716 </i18n:msg> | |
717 </html>""") | |
718 translations = DummyTranslations({ | |
719 'Changed %(date)s ago by %(author)s': u'Modificado à %(date)s por %(author)s' | |
720 }) | |
721 translator = Translator(translations) | |
722 translator.setup(tmpl) | |
723 self.assertEqual("""<html> | |
724 Modificado à um dia por Pedro | |
725 </html>""", tmpl.generate(date='um dia', author="Pedro").render()) | |
726 | |
727 | |
728 def test_i18n_msg_ticket_251_extract(self): | |
729 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
730 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
731 <p i18n:msg=""><tt><b>Translation[ 0 ]</b>: <em>One coin</em></tt></p> | |
732 </html>""") | |
733 translator = Translator() | |
734 tmpl.add_directives(Translator.NAMESPACE, translator) | |
735 messages = list(translator.extract(tmpl.stream)) | |
736 self.assertEqual(1, len(messages)) | |
737 self.assertEqual( | |
738 (3, None, u'[1:[2:Translation\\[\xa00\xa0\\]]: [3:One coin]]', []), messages[0] | |
739 ) | |
740 | |
741 def test_i18n_msg_ticket_251_translate(self): | |
742 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
743 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
744 <p i18n:msg=""><tt><b>Translation[ 0 ]</b>: <em>One coin</em></tt></p> | |
745 </html>""") | |
746 translations = DummyTranslations({ | |
747 u'[1:[2:Translation\\[\xa00\xa0\\]]: [3:One coin]]': | |
748 u'[1:[2:Trandução\\[\xa00\xa0\\]]: [3:Uma moeda]]' | |
749 }) | |
750 translator = Translator(translations) | |
751 translator.setup(tmpl) | |
752 self.assertEqual("""<html> | |
753 <p><tt><b>Trandução[ 0 ]</b>: <em>Uma moeda</em></tt></p> | |
754 </html>""", tmpl.generate().render()) | |
755 | |
756 def test_extract_i18n_msg_with_other_directives_nested(self): | |
757 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
758 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
759 <p i18n:msg="" py:with="q = quote_plus(message[:80])">Before you do that, though, please first try | |
760 <strong><a href="${trac.homepage}search?ticket=yes&noquickjump=1&q=$q">searching</a> | |
761 for similar issues</strong>, as it is quite likely that this problem | |
762 has been reported before. For questions about installation | |
763 and configuration of Trac, please try the | |
764 <a href="${trac.homepage}wiki/MailingList">mailing list</a> | |
765 instead of filing a ticket. | |
766 </p> | |
767 </html>""") | |
768 translator = Translator() | |
769 translator.setup(tmpl) | |
770 messages = list(translator.extract(tmpl.stream)) | |
771 self.assertEqual(1, len(messages)) | |
772 self.assertEqual( | |
773 'Before you do that, though, please first try\n ' | |
774 '[1:[2:searching]\n for similar issues], as it is ' | |
775 'quite likely that this problem\n has been reported ' | |
776 'before. For questions about installation\n and ' | |
777 'configuration of Trac, please try the\n ' | |
778 '[3:mailing list]\n instead of filing a ticket.', | |
779 messages[0][2] | |
780 ) | |
781 | |
782 def test_translate_i18n_msg_with_other_directives_nested(self): | |
783 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
784 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
785 <p i18n:msg="">Before you do that, though, please first try | |
786 <strong><a href="${trac.homepage}search?ticket=yes&noquickjump=1&q=q">searching</a> | |
787 for similar issues</strong>, as it is quite likely that this problem | |
788 has been reported before. For questions about installation | |
789 and configuration of Trac, please try the | |
790 <a href="${trac.homepage}wiki/MailingList">mailing list</a> | |
791 instead of filing a ticket. | |
792 </p> | |
793 </html>""") | |
794 translations = DummyTranslations({ | |
795 'Before you do that, though, please first try\n ' | |
796 '[1:[2:searching]\n for similar issues], as it is ' | |
797 'quite likely that this problem\n has been reported ' | |
798 'before. For questions about installation\n and ' | |
799 'configuration of Trac, please try the\n ' | |
800 '[3:mailing list]\n instead of filing a ticket.': | |
801 u'Antes de o fazer, porém,\n ' | |
802 u'[1:por favor tente [2:procurar]\n por problemas semelhantes], uma vez que ' | |
803 u'é muito provável que este problema\n já tenha sido reportado ' | |
804 u'anteriormente. Para questões relativas à instalação\n e ' | |
805 u'configuração do Trac, por favor tente a\n ' | |
806 u'[3:mailing list]\n em vez de criar um assunto.' | |
807 }) | |
808 translator = Translator(translations) | |
809 translator.setup(tmpl) | |
810 messages = list(translator.extract(tmpl.stream)) | |
811 self.assertEqual(1, len(messages)) | |
812 ctx = Context() | |
813 ctx.push({'trac': {'homepage': 'http://trac.edgewall.org/'}}) | |
814 self.assertEqual("""<html> | |
815 <p>Antes de o fazer, porém, | |
816 <strong>por favor tente <a href="http://trac.edgewall.org/search?ticket=yes&noquickjump=1&q=q">procurar</a> | |
817 por problemas semelhantes</strong>, uma vez que é muito provável que este problema | |
818 já tenha sido reportado anteriormente. Para questões relativas à instalação | |
819 e configuração do Trac, por favor tente a | |
820 <a href="http://trac.edgewall.org/wiki/MailingList">mailing list</a> | |
821 em vez de criar um assunto.</p> | |
822 </html>""", tmpl.generate(ctx).render()) | |
823 | |
824 def test_i18n_msg_with_other_nested_directives_with_reordered_content(self): | |
825 # See: http://genshi.edgewall.org/ticket/300#comment:10 | |
826 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
827 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
828 <p py:if="not editable" class="hint" i18n:msg=""> | |
829 <strong>Note:</strong> This repository is defined in | |
830 <code><a href="${ 'href.wiki(TracIni)' }">trac.ini</a></code> | |
831 and cannot be edited on this page. | |
832 </p> | |
833 </html>""") | |
834 translations = DummyTranslations({ | |
835 '[1:Note:] This repository is defined in\n ' | |
836 '[2:[3:trac.ini]]\n and cannot be edited on this page.': | |
837 u'[1:Nota:] Este repositório está definido em \n ' | |
838 u'[2:[3:trac.ini]]\n e não pode ser editado nesta página.', | |
839 }) | |
840 translator = Translator(translations) | |
841 translator.setup(tmpl) | |
842 messages = list(translator.extract(tmpl.stream)) | |
843 self.assertEqual(1, len(messages)) | |
844 self.assertEqual( | |
845 '[1:Note:] This repository is defined in\n ' | |
846 '[2:[3:trac.ini]]\n and cannot be edited on this page.', | |
847 messages[0][2] | |
848 ) | |
849 self.assertEqual("""<html> | |
850 <p class="hint"><strong>Nota:</strong> Este repositório está definido em | |
851 <code><a href="href.wiki(TracIni)">trac.ini</a></code> | |
852 e não pode ser editado nesta página.</p> | |
853 </html>""", tmpl.generate(editable=False).render()) | |
854 | |
855 def test_extract_i18n_msg_with_py_strip(self): | |
856 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
857 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
858 <p i18n:msg="" py:strip=""> | |
859 Please see <a href="help.html">Help</a> for details. | |
860 </p> | |
861 </html>""") | |
862 translator = Translator() | |
863 tmpl.add_directives(Translator.NAMESPACE, translator) | |
864 messages = list(translator.extract(tmpl.stream)) | |
865 self.assertEqual(1, len(messages)) | |
866 self.assertEqual((3, None, 'Please see [1:Help] for details.', []), | |
867 messages[0]) | |
868 | |
869 def test_extract_i18n_msg_with_py_strip_and_comment(self): | |
870 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
871 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
872 <p i18n:msg="" py:strip="" i18n:comment="Foo"> | |
873 Please see <a href="help.html">Help</a> for details. | |
874 </p> | |
875 </html>""") | |
876 translator = Translator() | |
877 tmpl.add_directives(Translator.NAMESPACE, translator) | |
878 messages = list(translator.extract(tmpl.stream)) | |
879 self.assertEqual(1, len(messages)) | |
880 self.assertEqual((3, None, 'Please see [1:Help] for details.', | |
881 ['Foo']), messages[0]) | |
882 | |
883 def test_translate_i18n_msg_and_comment_with_py_strip_directives(self): | |
884 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
885 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
886 <p i18n:msg="" i18n:comment="As in foo bar" py:strip="">Foo</p> | |
887 <p py:strip="" i18n:msg="" i18n:comment="As in foo bar">Foo</p> | |
888 </html>""") | |
889 translator = Translator(DummyTranslations({'Foo': 'Voh'})) | |
890 translator.setup(tmpl) | |
891 self.assertEqual("""<html> | |
892 Voh | |
893 Voh | |
894 </html>""", tmpl.generate().render()) | |
895 | |
896 | |
897 class ChooseDirectiveTestCase(unittest.TestCase): | |
898 | |
899 def test_translate_i18n_choose_as_attribute(self): | |
900 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
901 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
902 <div i18n:choose="one"> | |
903 <p i18n:singular="">FooBar</p> | |
904 <p i18n:plural="">FooBars</p> | |
905 </div> | |
906 <div i18n:choose="two"> | |
907 <p i18n:singular="">FooBar</p> | |
908 <p i18n:plural="">FooBars</p> | |
909 </div> | |
910 </html>""") | |
911 translations = DummyTranslations() | |
912 translator = Translator(translations) | |
913 translator.setup(tmpl) | |
914 self.assertEqual("""<html> | |
915 <div> | |
916 <p>FooBar</p> | |
917 </div> | |
918 <div> | |
919 <p>FooBars</p> | |
920 </div> | |
921 </html>""", tmpl.generate(one=1, two=2).render()) | |
922 | |
923 def test_translate_i18n_choose_as_directive(self): | |
924 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
925 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
926 <i18n:choose numeral="two"> | |
927 <p i18n:singular="">FooBar</p> | |
928 <p i18n:plural="">FooBars</p> | |
929 </i18n:choose> | |
930 <i18n:choose numeral="one"> | |
931 <p i18n:singular="">FooBar</p> | |
932 <p i18n:plural="">FooBars</p> | |
933 </i18n:choose> | |
934 </html>""") | |
935 translations = DummyTranslations() | |
936 translator = Translator(translations) | |
937 translator.setup(tmpl) | |
938 self.assertEqual("""<html> | |
939 <p>FooBars</p> | |
940 <p>FooBar</p> | |
941 </html>""", tmpl.generate(one=1, two=2).render()) | |
942 | |
943 def test_translate_i18n_choose_as_directive_singular_and_plural_with_strip(self): | |
944 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
945 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
946 <i18n:choose numeral="two"> | |
947 <p i18n:singular="" py:strip="">FooBar Singular with Strip</p> | |
948 <p i18n:plural="">FooBars Plural without Strip</p> | |
949 </i18n:choose> | |
950 <i18n:choose numeral="two"> | |
951 <p i18n:singular="">FooBar singular without strip</p> | |
952 <p i18n:plural="" py:strip="">FooBars plural with strip</p> | |
953 </i18n:choose> | |
954 <i18n:choose numeral="one"> | |
955 <p i18n:singular="">FooBar singular without strip</p> | |
956 <p i18n:plural="" py:strip="">FooBars plural with strip</p> | |
957 </i18n:choose> | |
958 <i18n:choose numeral="one"> | |
959 <p i18n:singular="" py:strip="">FooBar singular with strip</p> | |
960 <p i18n:plural="">FooBars plural without strip</p> | |
961 </i18n:choose> | |
962 </html>""") | |
963 translations = DummyTranslations() | |
964 translator = Translator(translations) | |
965 translator.setup(tmpl) | |
966 self.assertEqual("""<html> | |
967 <p>FooBars Plural without Strip</p> | |
968 FooBars plural with strip | |
969 <p>FooBar singular without strip</p> | |
970 FooBar singular with strip | |
971 </html>""", tmpl.generate(one=1, two=2).render()) | |
972 | |
973 def test_translate_i18n_choose_plural_singular_as_directive(self): | |
974 # Ticket 371 | |
975 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
976 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
977 <i18n:choose numeral="two"> | |
978 <i18n:singular>FooBar</i18n:singular> | |
979 <i18n:plural>FooBars</i18n:plural> | |
980 </i18n:choose> | |
981 <i18n:choose numeral="one"> | |
982 <i18n:singular>FooBar</i18n:singular> | |
983 <i18n:plural>FooBars</i18n:plural> | |
984 </i18n:choose> | |
985 </html>""") | |
986 translations = DummyTranslations({ | |
987 ('FooBar', 0): 'FuBar', | |
988 ('FooBars', 1): 'FuBars', | |
989 'FooBar': 'FuBar', | |
990 'FooBars': 'FuBars', | |
991 }) | |
992 translator = Translator(translations) | |
993 translator.setup(tmpl) | |
994 self.assertEqual("""<html> | |
995 FuBars | |
996 FuBar | |
997 </html>""", tmpl.generate(one=1, two=2).render()) | |
998 | |
999 def test_translate_i18n_choose_as_attribute_with_params(self): | |
1000 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1001 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1002 <div i18n:choose="two; fname, lname"> | |
1003 <p i18n:singular="">Foo $fname $lname</p> | |
1004 <p i18n:plural="">Foos $fname $lname</p> | |
1005 </div> | |
1006 </html>""") | |
1007 translations = DummyTranslations({ | |
1008 ('Foo %(fname)s %(lname)s', 0): 'Voh %(fname)s %(lname)s', | |
1009 ('Foo %(fname)s %(lname)s', 1): 'Vohs %(fname)s %(lname)s', | |
1010 'Foo %(fname)s %(lname)s': 'Voh %(fname)s %(lname)s', | |
1011 'Foos %(fname)s %(lname)s': 'Vohs %(fname)s %(lname)s', | |
1012 }) | |
1013 translator = Translator(translations) | |
1014 translator.setup(tmpl) | |
1015 self.assertEqual("""<html> | |
1016 <div> | |
1017 <p>Vohs John Doe</p> | |
1018 </div> | |
1019 </html>""", tmpl.generate(two=2, fname='John', lname='Doe').render()) | |
1020 | |
1021 def test_translate_i18n_choose_as_attribute_with_params_and_domain_as_param(self): | |
1022 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1023 xmlns:i18n="http://genshi.edgewall.org/i18n" | |
1024 i18n:domain="foo"> | |
1025 <div i18n:choose="two; fname, lname"> | |
1026 <p i18n:singular="">Foo $fname $lname</p> | |
1027 <p i18n:plural="">Foos $fname $lname</p> | |
1028 </div> | |
1029 </html>""") | |
1030 translations = DummyTranslations() | |
1031 translations.add_domain('foo', { | |
1032 ('Foo %(fname)s %(lname)s', 0): 'Voh %(fname)s %(lname)s', | |
1033 ('Foo %(fname)s %(lname)s', 1): 'Vohs %(fname)s %(lname)s', | |
1034 'Foo %(fname)s %(lname)s': 'Voh %(fname)s %(lname)s', | |
1035 'Foos %(fname)s %(lname)s': 'Vohs %(fname)s %(lname)s', | |
1036 }) | |
1037 translator = Translator(translations) | |
1038 translator.setup(tmpl) | |
1039 self.assertEqual("""<html> | |
1040 <div> | |
1041 <p>Vohs John Doe</p> | |
1042 </div> | |
1043 </html>""", tmpl.generate(two=2, fname='John', lname='Doe').render()) | |
1044 | |
1045 def test_translate_i18n_choose_as_directive_with_params(self): | |
1046 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1047 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1048 <i18n:choose numeral="two" params="fname, lname"> | |
1049 <p i18n:singular="">Foo ${fname} ${lname}</p> | |
1050 <p i18n:plural="">Foos ${fname} ${lname}</p> | |
1051 </i18n:choose> | |
1052 <i18n:choose numeral="one" params="fname, lname"> | |
1053 <p i18n:singular="">Foo ${fname} ${lname}</p> | |
1054 <p i18n:plural="">Foos ${fname} ${lname}</p> | |
1055 </i18n:choose> | |
1056 </html>""") | |
1057 translations = DummyTranslations({ | |
1058 ('Foo %(fname)s %(lname)s', 0): 'Voh %(fname)s %(lname)s', | |
1059 ('Foo %(fname)s %(lname)s', 1): 'Vohs %(fname)s %(lname)s', | |
1060 'Foo %(fname)s %(lname)s': 'Voh %(fname)s %(lname)s', | |
1061 'Foos %(fname)s %(lname)s': 'Vohs %(fname)s %(lname)s', | |
1062 }) | |
1063 translator = Translator(translations) | |
1064 translator.setup(tmpl) | |
1065 self.assertEqual("""<html> | |
1066 <p>Vohs John Doe</p> | |
1067 <p>Voh John Doe</p> | |
1068 </html>""", tmpl.generate(one=1, two=2, | |
1069 fname='John', lname='Doe').render()) | |
1070 | |
1071 def test_translate_i18n_choose_as_directive_with_params_and_domain_as_directive(self): | |
1072 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1073 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1074 <i18n:domain name="foo"> | |
1075 <i18n:choose numeral="two" params="fname, lname"> | |
1076 <p i18n:singular="">Foo ${fname} ${lname}</p> | |
1077 <p i18n:plural="">Foos ${fname} ${lname}</p> | |
1078 </i18n:choose> | |
1079 </i18n:domain> | |
1080 <i18n:choose numeral="one" params="fname, lname"> | |
1081 <p i18n:singular="">Foo ${fname} ${lname}</p> | |
1082 <p i18n:plural="">Foos ${fname} ${lname}</p> | |
1083 </i18n:choose> | |
1084 </html>""") | |
1085 translations = DummyTranslations() | |
1086 translations.add_domain('foo', { | |
1087 ('Foo %(fname)s %(lname)s', 0): 'Voh %(fname)s %(lname)s', | |
1088 ('Foo %(fname)s %(lname)s', 1): 'Vohs %(fname)s %(lname)s', | |
1089 'Foo %(fname)s %(lname)s': 'Voh %(fname)s %(lname)s', | |
1090 'Foos %(fname)s %(lname)s': 'Vohs %(fname)s %(lname)s', | |
1091 }) | |
1092 translator = Translator(translations) | |
1093 translator.setup(tmpl) | |
1094 self.assertEqual("""<html> | |
1095 <p>Vohs John Doe</p> | |
1096 <p>Foo John Doe</p> | |
1097 </html>""", tmpl.generate(one=1, two=2, | |
1098 fname='John', lname='Doe').render()) | |
1099 | |
1100 def test_extract_i18n_choose_as_attribute(self): | |
1101 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1102 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1103 <div i18n:choose="one"> | |
1104 <p i18n:singular="">FooBar</p> | |
1105 <p i18n:plural="">FooBars</p> | |
1106 </div> | |
1107 <div i18n:choose="two"> | |
1108 <p i18n:singular="">FooBar</p> | |
1109 <p i18n:plural="">FooBars</p> | |
1110 </div> | |
1111 </html>""") | |
1112 translator = Translator() | |
1113 tmpl.add_directives(Translator.NAMESPACE, translator) | |
1114 messages = list(translator.extract(tmpl.stream)) | |
1115 self.assertEqual(2, len(messages)) | |
1116 self.assertEqual((3, 'ngettext', ('FooBar', 'FooBars'), []), messages[0]) | |
1117 self.assertEqual((7, 'ngettext', ('FooBar', 'FooBars'), []), messages[1]) | |
1118 | |
1119 def test_extract_i18n_choose_as_directive(self): | |
1120 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1121 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1122 <i18n:choose numeral="two"> | |
1123 <p i18n:singular="">FooBar</p> | |
1124 <p i18n:plural="">FooBars</p> | |
1125 </i18n:choose> | |
1126 <i18n:choose numeral="one"> | |
1127 <p i18n:singular="">FooBar</p> | |
1128 <p i18n:plural="">FooBars</p> | |
1129 </i18n:choose> | |
1130 </html>""") | |
1131 translator = Translator() | |
1132 tmpl.add_directives(Translator.NAMESPACE, translator) | |
1133 messages = list(translator.extract(tmpl.stream)) | |
1134 self.assertEqual(2, len(messages)) | |
1135 self.assertEqual((3, 'ngettext', ('FooBar', 'FooBars'), []), messages[0]) | |
1136 self.assertEqual((7, 'ngettext', ('FooBar', 'FooBars'), []), messages[1]) | |
1137 | |
1138 def test_extract_i18n_choose_as_attribute_with_params(self): | |
1139 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1140 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1141 <div i18n:choose="two; fname, lname"> | |
1142 <p i18n:singular="">Foo $fname $lname</p> | |
1143 <p i18n:plural="">Foos $fname $lname</p> | |
1144 </div> | |
1145 </html>""") | |
1146 translator = Translator() | |
1147 tmpl.add_directives(Translator.NAMESPACE, translator) | |
1148 messages = list(translator.extract(tmpl.stream)) | |
1149 self.assertEqual(1, len(messages)) | |
1150 self.assertEqual((3, 'ngettext', ('Foo %(fname)s %(lname)s', | |
1151 'Foos %(fname)s %(lname)s'), []), | |
1152 messages[0]) | |
1153 | |
1154 def test_extract_i18n_choose_as_attribute_with_params_and_domain_as_param(self): | |
1155 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1156 xmlns:i18n="http://genshi.edgewall.org/i18n" | |
1157 i18n:domain="foo"> | |
1158 <div i18n:choose="two; fname, lname"> | |
1159 <p i18n:singular="">Foo $fname $lname</p> | |
1160 <p i18n:plural="">Foos $fname $lname</p> | |
1161 </div> | |
1162 </html>""") | |
1163 translator = Translator() | |
1164 tmpl.add_directives(Translator.NAMESPACE, translator) | |
1165 messages = list(translator.extract(tmpl.stream)) | |
1166 self.assertEqual(1, len(messages)) | |
1167 self.assertEqual((4, 'ngettext', ('Foo %(fname)s %(lname)s', | |
1168 'Foos %(fname)s %(lname)s'), []), | |
1169 messages[0]) | |
1170 | |
1171 def test_extract_i18n_choose_as_directive_with_params(self): | |
1172 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1173 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1174 <i18n:choose numeral="two" params="fname, lname"> | |
1175 <p i18n:singular="">Foo ${fname} ${lname}</p> | |
1176 <p i18n:plural="">Foos ${fname} ${lname}</p> | |
1177 </i18n:choose> | |
1178 <i18n:choose numeral="one" params="fname, lname"> | |
1179 <p i18n:singular="">Foo ${fname} ${lname}</p> | |
1180 <p i18n:plural="">Foos ${fname} ${lname}</p> | |
1181 </i18n:choose> | |
1182 </html>""") | |
1183 translator = Translator() | |
1184 tmpl.add_directives(Translator.NAMESPACE, translator) | |
1185 messages = list(translator.extract(tmpl.stream)) | |
1186 self.assertEqual(2, len(messages)) | |
1187 self.assertEqual((3, 'ngettext', ('Foo %(fname)s %(lname)s', | |
1188 'Foos %(fname)s %(lname)s'), []), | |
1189 messages[0]) | |
1190 self.assertEqual((7, 'ngettext', ('Foo %(fname)s %(lname)s', | |
1191 'Foos %(fname)s %(lname)s'), []), | |
1192 messages[1]) | |
1193 | |
1194 def test_extract_i18n_choose_as_directive_with_params_and_domain_as_directive(self): | |
1195 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1196 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1197 <i18n:domain name="foo"> | |
1198 <i18n:choose numeral="two" params="fname, lname"> | |
1199 <p i18n:singular="">Foo ${fname} ${lname}</p> | |
1200 <p i18n:plural="">Foos ${fname} ${lname}</p> | |
1201 </i18n:choose> | |
1202 </i18n:domain> | |
1203 <i18n:choose numeral="one" params="fname, lname"> | |
1204 <p i18n:singular="">Foo ${fname} ${lname}</p> | |
1205 <p i18n:plural="">Foos ${fname} ${lname}</p> | |
1206 </i18n:choose> | |
1207 </html>""") | |
1208 translator = Translator() | |
1209 tmpl.add_directives(Translator.NAMESPACE, translator) | |
1210 messages = list(translator.extract(tmpl.stream)) | |
1211 self.assertEqual(2, len(messages)) | |
1212 self.assertEqual((4, 'ngettext', ('Foo %(fname)s %(lname)s', | |
1213 'Foos %(fname)s %(lname)s'), []), | |
1214 messages[0]) | |
1215 self.assertEqual((9, 'ngettext', ('Foo %(fname)s %(lname)s', | |
1216 'Foos %(fname)s %(lname)s'), []), | |
1217 messages[1]) | |
1218 | |
1219 def test_extract_i18n_choose_as_attribute_with_params_and_comment(self): | |
1220 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1221 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1222 <div i18n:choose="two; fname, lname" i18n:comment="As in Foo Bar"> | |
1223 <p i18n:singular="">Foo $fname $lname</p> | |
1224 <p i18n:plural="">Foos $fname $lname</p> | |
1225 </div> | |
1226 </html>""") | |
1227 translator = Translator() | |
1228 tmpl.add_directives(Translator.NAMESPACE, translator) | |
1229 messages = list(translator.extract(tmpl.stream)) | |
1230 self.assertEqual(1, len(messages)) | |
1231 self.assertEqual((3, 'ngettext', ('Foo %(fname)s %(lname)s', | |
1232 'Foos %(fname)s %(lname)s'), | |
1233 ['As in Foo Bar']), | |
1234 messages[0]) | |
1235 | |
1236 def test_extract_i18n_choose_as_directive_with_params_and_comment(self): | |
1237 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1238 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1239 <i18n:choose numeral="two" params="fname, lname" i18n:comment="As in Foo Bar"> | |
1240 <p i18n:singular="">Foo ${fname} ${lname}</p> | |
1241 <p i18n:plural="">Foos ${fname} ${lname}</p> | |
1242 </i18n:choose> | |
1243 </html>""") | |
1244 translator = Translator() | |
1245 tmpl.add_directives(Translator.NAMESPACE, translator) | |
1246 messages = list(translator.extract(tmpl.stream)) | |
1247 self.assertEqual(1, len(messages)) | |
1248 self.assertEqual((3, 'ngettext', ('Foo %(fname)s %(lname)s', | |
1249 'Foos %(fname)s %(lname)s'), | |
1250 ['As in Foo Bar']), | |
1251 messages[0]) | |
1252 | |
1253 def test_extract_i18n_choose_with_attributes(self): | |
1254 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1255 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1256 <p i18n:choose="num; num" title="Things"> | |
1257 <i18n:singular> | |
1258 There is <a href="$link" title="View thing">${num} thing</a>. | |
1259 </i18n:singular> | |
1260 <i18n:plural> | |
1261 There are <a href="$link" title="View things">${num} things</a>. | |
1262 </i18n:plural> | |
1263 </p> | |
1264 </html>""") | |
1265 translator = Translator() | |
1266 translator.setup(tmpl) | |
1267 messages = list(translator.extract(tmpl.stream)) | |
1268 self.assertEqual(4, len(messages)) | |
1269 self.assertEqual((3, None, 'Things', []), messages[0]) | |
1270 self.assertEqual((5, None, 'View thing', []), messages[1]) | |
1271 self.assertEqual((8, None, 'View things', []), messages[2]) | |
1272 self.assertEqual( | |
1273 (3, 'ngettext', ('There is [1:%(num)s thing].', | |
1274 'There are [1:%(num)s things].'), []), | |
1275 messages[3]) | |
1276 | |
1277 def test_translate_i18n_choose_with_attributes(self): | |
1278 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1279 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1280 <p i18n:choose="num; num" title="Things"> | |
1281 <i18n:singular> | |
1282 There is <a href="$link" title="View thing">${num} thing</a>. | |
1283 </i18n:singular> | |
1284 <i18n:plural> | |
1285 There are <a href="$link" title="View things">${num} things</a>. | |
1286 </i18n:plural> | |
1287 </p> | |
1288 </html>""") | |
1289 translations = DummyTranslations({ | |
1290 'Things': 'Sachen', | |
1291 'View thing': 'Sache betrachten', | |
1292 'View things': 'Sachen betrachten', | |
1293 ('There is [1:%(num)s thing].', 0): 'Da ist [1:%(num)s Sache].', | |
1294 ('There is [1:%(num)s thing].', 1): 'Da sind [1:%(num)s Sachen].' | |
1295 }) | |
1296 translator = Translator(translations) | |
1297 translator.setup(tmpl) | |
1298 self.assertEqual(u"""<html> | |
1299 <p title="Sachen"> | |
1300 Da ist <a href="/things" title="Sache betrachten">1 Sache</a>. | |
1301 </p> | |
1302 </html>""", tmpl.generate(link="/things", num=1).render(encoding=None)) | |
1303 self.assertEqual(u"""<html> | |
1304 <p title="Sachen"> | |
1305 Da sind <a href="/things" title="Sachen betrachten">3 Sachen</a>. | |
1306 </p> | |
1307 </html>""", tmpl.generate(link="/things", num=3).render(encoding=None)) | |
1308 | |
1309 def test_extract_i18n_choose_as_element_with_attributes(self): | |
1310 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1311 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1312 <i18n:choose numeral="num" params="num"> | |
1313 <p i18n:singular="" title="Things"> | |
1314 There is <a href="$link" title="View thing">${num} thing</a>. | |
1315 </p> | |
1316 <p i18n:plural="" title="Things"> | |
1317 There are <a href="$link" title="View things">${num} things</a>. | |
1318 </p> | |
1319 </i18n:choose> | |
1320 </html>""") | |
1321 translator = Translator() | |
1322 translator.setup(tmpl) | |
1323 messages = list(translator.extract(tmpl.stream)) | |
1324 self.assertEqual(5, len(messages)) | |
1325 self.assertEqual((4, None, 'Things', []), messages[0]) | |
1326 self.assertEqual((5, None, 'View thing', []), messages[1]) | |
1327 self.assertEqual((7, None, 'Things', []), messages[2]) | |
1328 self.assertEqual((8, None, 'View things', []), messages[3]) | |
1329 self.assertEqual( | |
1330 (3, 'ngettext', ('There is [1:%(num)s thing].', | |
1331 'There are [1:%(num)s things].'), []), | |
1332 messages[4]) | |
1333 | |
1334 def test_translate_i18n_choose_as_element_with_attributes(self): | |
1335 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1336 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1337 <i18n:choose numeral="num" params="num"> | |
1338 <p i18n:singular="" title="Things"> | |
1339 There is <a href="$link" title="View thing">${num} thing</a>. | |
1340 </p> | |
1341 <p i18n:plural="" title="Things"> | |
1342 There are <a href="$link" title="View things">${num} things</a>. | |
1343 </p> | |
1344 </i18n:choose> | |
1345 </html>""") | |
1346 translations = DummyTranslations({ | |
1347 'Things': 'Sachen', | |
1348 'View thing': 'Sache betrachten', | |
1349 'View things': 'Sachen betrachten', | |
1350 ('There is [1:%(num)s thing].', 0): 'Da ist [1:%(num)s Sache].', | |
1351 ('There is [1:%(num)s thing].', 1): 'Da sind [1:%(num)s Sachen].' | |
1352 }) | |
1353 translator = Translator(translations) | |
1354 translator.setup(tmpl) | |
1355 self.assertEqual(u"""<html> | |
1356 <p title="Sachen">Da ist <a href="/things" title="Sache betrachten">1 Sache</a>.</p> | |
1357 </html>""", tmpl.generate(link="/things", num=1).render(encoding=None)) | |
1358 self.assertEqual(u"""<html> | |
1359 <p title="Sachen">Da sind <a href="/things" title="Sachen betrachten">3 Sachen</a>.</p> | |
1360 </html>""", tmpl.generate(link="/things", num=3).render(encoding=None)) | |
1361 | |
1362 def test_translate_i18n_choose_and_py_strip(self): | |
1363 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1364 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1365 <div i18n:choose="two; fname, lname"> | |
1366 <p i18n:singular="">Foo $fname $lname</p> | |
1367 <p i18n:plural="">Foos $fname $lname</p> | |
1368 </div> | |
1369 </html>""") | |
1370 translations = DummyTranslations({ | |
1371 ('Foo %(fname)s %(lname)s', 0): 'Voh %(fname)s %(lname)s', | |
1372 ('Foo %(fname)s %(lname)s', 1): 'Vohs %(fname)s %(lname)s', | |
1373 'Foo %(fname)s %(lname)s': 'Voh %(fname)s %(lname)s', | |
1374 'Foos %(fname)s %(lname)s': 'Vohs %(fname)s %(lname)s', | |
1375 }) | |
1376 translator = Translator(translations) | |
1377 translator.setup(tmpl) | |
1378 self.assertEqual("""<html> | |
1379 <div> | |
1380 <p>Vohs John Doe</p> | |
1381 </div> | |
1382 </html>""", tmpl.generate(two=2, fname='John', lname='Doe').render()) | |
1383 | |
1384 def test_translate_i18n_choose_and_domain_and_py_strip(self): | |
1385 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1386 xmlns:i18n="http://genshi.edgewall.org/i18n" | |
1387 i18n:domain="foo"> | |
1388 <div i18n:choose="two; fname, lname"> | |
1389 <p i18n:singular="">Foo $fname $lname</p> | |
1390 <p i18n:plural="">Foos $fname $lname</p> | |
1391 </div> | |
1392 </html>""") | |
1393 translations = DummyTranslations() | |
1394 translations.add_domain('foo', { | |
1395 ('Foo %(fname)s %(lname)s', 0): 'Voh %(fname)s %(lname)s', | |
1396 ('Foo %(fname)s %(lname)s', 1): 'Vohs %(fname)s %(lname)s', | |
1397 'Foo %(fname)s %(lname)s': 'Voh %(fname)s %(lname)s', | |
1398 'Foos %(fname)s %(lname)s': 'Vohs %(fname)s %(lname)s', | |
1399 }) | |
1400 translator = Translator(translations) | |
1401 translator.setup(tmpl) | |
1402 self.assertEqual("""<html> | |
1403 <div> | |
1404 <p>Vohs John Doe</p> | |
1405 </div> | |
1406 </html>""", tmpl.generate(two=2, fname='John', lname='Doe').render()) | |
1407 | |
1408 def test_translate_i18n_choose_and_singular_with_py_strip(self): | |
1409 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1410 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1411 <div i18n:choose="two; fname, lname"> | |
1412 <p i18n:singular="" py:strip="">Foo $fname $lname</p> | |
1413 <p i18n:plural="">Foos $fname $lname</p> | |
1414 </div> | |
1415 <div i18n:choose="one; fname, lname"> | |
1416 <p i18n:singular="" py:strip="">Foo $fname $lname</p> | |
1417 <p i18n:plural="">Foos $fname $lname</p> | |
1418 </div> | |
1419 </html>""") | |
1420 translations = DummyTranslations({ | |
1421 ('Foo %(fname)s %(lname)s', 0): 'Voh %(fname)s %(lname)s', | |
1422 ('Foo %(fname)s %(lname)s', 1): 'Vohs %(fname)s %(lname)s', | |
1423 'Foo %(fname)s %(lname)s': 'Voh %(fname)s %(lname)s', | |
1424 'Foos %(fname)s %(lname)s': 'Vohs %(fname)s %(lname)s', | |
1425 }) | |
1426 translator = Translator(translations) | |
1427 translator.setup(tmpl) | |
1428 self.assertEqual("""<html> | |
1429 <div> | |
1430 <p>Vohs John Doe</p> | |
1431 </div> | |
1432 <div> | |
1433 Voh John Doe | |
1434 </div> | |
1435 </html>""", tmpl.generate( | |
1436 one=1, two=2, fname='John',lname='Doe').render()) | |
1437 | |
1438 def test_translate_i18n_choose_and_plural_with_py_strip(self): | |
1439 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1440 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1441 <div i18n:choose="two; fname, lname"> | |
1442 <p i18n:singular="" py:strip="">Foo $fname $lname</p> | |
1443 <p i18n:plural="">Foos $fname $lname</p> | |
1444 </div> | |
1445 </html>""") | |
1446 translations = DummyTranslations({ | |
1447 ('Foo %(fname)s %(lname)s', 0): 'Voh %(fname)s %(lname)s', | |
1448 ('Foo %(fname)s %(lname)s', 1): 'Vohs %(fname)s %(lname)s', | |
1449 'Foo %(fname)s %(lname)s': 'Voh %(fname)s %(lname)s', | |
1450 'Foos %(fname)s %(lname)s': 'Vohs %(fname)s %(lname)s', | |
1451 }) | |
1452 translator = Translator(translations) | |
1453 translator.setup(tmpl) | |
1454 self.assertEqual("""<html> | |
1455 <div> | |
1456 Voh John Doe | |
1457 </div> | |
1458 </html>""", tmpl.generate(two=1, fname='John', lname='Doe').render()) | |
1459 | |
1460 def test_extract_i18n_choose_as_attribute_and_py_strip(self): | |
1461 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1462 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1463 <div i18n:choose="one" py:strip=""> | |
1464 <p i18n:singular="" py:strip="">FooBar</p> | |
1465 <p i18n:plural="" py:strip="">FooBars</p> | |
1466 </div> | |
1467 </html>""") | |
1468 translator = Translator() | |
1469 tmpl.add_directives(Translator.NAMESPACE, translator) | |
1470 messages = list(translator.extract(tmpl.stream)) | |
1471 self.assertEqual(1, len(messages)) | |
1472 self.assertEqual((3, 'ngettext', ('FooBar', 'FooBars'), []), messages[0]) | |
1473 | |
1474 | |
1475 class DomainDirectiveTestCase(unittest.TestCase): | |
1476 | |
1477 def test_translate_i18n_domain_with_msg_directives(self): | |
1478 #"""translate with i18n:domain and nested i18n:msg directives """ | |
1479 | |
1480 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1481 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1482 <div i18n:domain="foo"> | |
1483 <p i18n:msg="">FooBar</p> | |
1484 <p i18n:msg="">Bar</p> | |
1485 </div> | |
1486 </html>""") | |
1487 translations = DummyTranslations({'Bar': 'Voh'}) | |
1488 translations.add_domain('foo', {'FooBar': 'BarFoo', 'Bar': 'PT_Foo'}) | |
1489 translator = Translator(translations) | |
1490 translator.setup(tmpl) | |
1491 self.assertEqual("""<html> | |
1492 <div> | |
1493 <p>BarFoo</p> | |
1494 <p>PT_Foo</p> | |
1495 </div> | |
1496 </html>""", tmpl.generate().render()) | |
1497 | |
1498 def test_translate_i18n_domain_with_inline_directives(self): | |
1499 #"""translate with inlined i18n:domain and i18n:msg directives""" | |
1500 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1501 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1502 <p i18n:msg="" i18n:domain="foo">FooBar</p> | |
1503 </html>""") | |
1504 translations = DummyTranslations({'Bar': 'Voh'}) | |
1505 translations.add_domain('foo', {'FooBar': 'BarFoo'}) | |
1506 translator = Translator(translations) | |
1507 translator.setup(tmpl) | |
1508 self.assertEqual("""<html> | |
1509 <p>BarFoo</p> | |
1510 </html>""", tmpl.generate().render()) | |
1511 | |
1512 def test_translate_i18n_domain_without_msg_directives(self): | |
1513 #"""translate domain call without i18n:msg directives still uses current domain""" | |
1514 | |
1515 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1516 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1517 <p i18n:msg="">Bar</p> | |
1518 <div i18n:domain="foo"> | |
1519 <p i18n:msg="">FooBar</p> | |
1520 <p i18n:msg="">Bar</p> | |
1521 <p>Bar</p> | |
1522 </div> | |
1523 <p>Bar</p> | |
1524 </html>""") | |
1525 translations = DummyTranslations({'Bar': 'Voh'}) | |
1526 translations.add_domain('foo', {'FooBar': 'BarFoo', 'Bar': 'PT_Foo'}) | |
1527 translator = Translator(translations) | |
1528 translator.setup(tmpl) | |
466 self.assertEqual("""<html> | 1529 self.assertEqual("""<html> |
467 <p>Voh</p> | 1530 <p>Voh</p> |
468 </html>""", tmpl.generate().render()) | 1531 <div> |
1532 <p>BarFoo</p> | |
1533 <p>PT_Foo</p> | |
1534 <p>PT_Foo</p> | |
1535 </div> | |
1536 <p>Voh</p> | |
1537 </html>""", tmpl.generate().render()) | |
1538 | |
1539 def test_translate_i18n_domain_as_directive_not_attribute(self): | |
1540 #"""translate with domain as directive""" | |
1541 | |
1542 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1543 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1544 <i18n:domain name="foo"> | |
1545 <p i18n:msg="">FooBar</p> | |
1546 <p i18n:msg="">Bar</p> | |
1547 <p>Bar</p> | |
1548 </i18n:domain> | |
1549 <p>Bar</p> | |
1550 </html>""") | |
1551 translations = DummyTranslations({'Bar': 'Voh'}) | |
1552 translations.add_domain('foo', {'FooBar': 'BarFoo', 'Bar': 'PT_Foo'}) | |
1553 translator = Translator(translations) | |
1554 translator.setup(tmpl) | |
1555 self.assertEqual("""<html> | |
1556 <p>BarFoo</p> | |
1557 <p>PT_Foo</p> | |
1558 <p>PT_Foo</p> | |
1559 <p>Voh</p> | |
1560 </html>""", tmpl.generate().render()) | |
1561 | |
1562 def test_translate_i18n_domain_nested_directives(self): | |
1563 #"""translate with nested i18n:domain directives""" | |
1564 | |
1565 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1566 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1567 <p i18n:msg="">Bar</p> | |
1568 <div i18n:domain="foo"> | |
1569 <p i18n:msg="">FooBar</p> | |
1570 <p i18n:domain="bar" i18n:msg="">Bar</p> | |
1571 <p>Bar</p> | |
1572 </div> | |
1573 <p>Bar</p> | |
1574 </html>""") | |
1575 translations = DummyTranslations({'Bar': 'Voh'}) | |
1576 translations.add_domain('foo', {'FooBar': 'BarFoo', 'Bar': 'foo_Bar'}) | |
1577 translations.add_domain('bar', {'Bar': 'bar_Bar'}) | |
1578 translator = Translator(translations) | |
1579 translator.setup(tmpl) | |
1580 self.assertEqual("""<html> | |
1581 <p>Voh</p> | |
1582 <div> | |
1583 <p>BarFoo</p> | |
1584 <p>bar_Bar</p> | |
1585 <p>foo_Bar</p> | |
1586 </div> | |
1587 <p>Voh</p> | |
1588 </html>""", tmpl.generate().render()) | |
1589 | |
1590 def test_translate_i18n_domain_with_empty_nested_domain_directive(self): | |
1591 #"""translate with empty nested i18n:domain directive does not use dngettext""" | |
1592 | |
1593 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1594 xmlns:i18n="http://genshi.edgewall.org/i18n"> | |
1595 <p i18n:msg="">Bar</p> | |
1596 <div i18n:domain="foo"> | |
1597 <p i18n:msg="">FooBar</p> | |
1598 <p i18n:domain="" i18n:msg="">Bar</p> | |
1599 <p>Bar</p> | |
1600 </div> | |
1601 <p>Bar</p> | |
1602 </html>""") | |
1603 translations = DummyTranslations({'Bar': 'Voh'}) | |
1604 translations.add_domain('foo', {'FooBar': 'BarFoo', 'Bar': 'foo_Bar'}) | |
1605 translations.add_domain('bar', {'Bar': 'bar_Bar'}) | |
1606 translator = Translator(translations) | |
1607 translator.setup(tmpl) | |
1608 self.assertEqual("""<html> | |
1609 <p>Voh</p> | |
1610 <div> | |
1611 <p>BarFoo</p> | |
1612 <p>Voh</p> | |
1613 <p>foo_Bar</p> | |
1614 </div> | |
1615 <p>Voh</p> | |
1616 </html>""", tmpl.generate().render()) | |
1617 | |
1618 def test_translate_i18n_domain_with_inline_directive_on_START_NS(self): | |
1619 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1620 xmlns:i18n="http://genshi.edgewall.org/i18n" i18n:domain="foo"> | |
1621 <p i18n:msg="">FooBar</p> | |
1622 </html>""") | |
1623 translations = DummyTranslations({'Bar': 'Voh'}) | |
1624 translations.add_domain('foo', {'FooBar': 'BarFoo'}) | |
1625 translator = Translator(translations) | |
1626 translator.setup(tmpl) | |
1627 self.assertEqual("""<html> | |
1628 <p>BarFoo</p> | |
1629 </html>""", tmpl.generate().render()) | |
1630 | |
1631 def test_translate_i18n_domain_with_inline_directive_on_START_NS_with_py_strip(self): | |
1632 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" | |
1633 xmlns:i18n="http://genshi.edgewall.org/i18n" | |
1634 i18n:domain="foo" py:strip=""> | |
1635 <p i18n:msg="">FooBar</p> | |
1636 </html>""") | |
1637 translations = DummyTranslations({'Bar': 'Voh'}) | |
1638 translations.add_domain('foo', {'FooBar': 'BarFoo'}) | |
1639 translator = Translator(translations) | |
1640 translator.setup(tmpl) | |
1641 self.assertEqual(""" | |
1642 <p>BarFoo</p> | |
1643 """, tmpl.generate().render()) | |
1644 | |
1645 def test_translate_i18n_domain_with_nested_includes(self): | |
1646 import os, shutil, tempfile | |
1647 from genshi.template.loader import TemplateLoader | |
1648 dirname = tempfile.mkdtemp(suffix='genshi_test') | |
1649 try: | |
1650 for idx in range(7): | |
1651 file1 = open(os.path.join(dirname, 'tmpl%d.html' % idx), 'w') | |
1652 try: | |
1653 file1.write("""<html xmlns:xi="http://www.w3.org/2001/XInclude" | |
1654 xmlns:py="http://genshi.edgewall.org/" | |
1655 xmlns:i18n="http://genshi.edgewall.org/i18n" py:strip=""> | |
1656 <div>Included tmpl$idx</div> | |
1657 <p i18n:msg="idx">Bar $idx</p> | |
1658 <p i18n:domain="bar">Bar</p> | |
1659 <p i18n:msg="idx" i18n:domain="">Bar $idx</p> | |
1660 <p i18n:domain="" i18n:msg="idx">Bar $idx</p> | |
1661 <py:if test="idx < 6"> | |
1662 <xi:include href="tmpl${idx}.html" py:with="idx = idx+1"/> | |
1663 </py:if> | |
1664 </html>""") | |
1665 finally: | |
1666 file1.close() | |
1667 | |
1668 file2 = open(os.path.join(dirname, 'tmpl10.html'), 'w') | |
1669 try: | |
1670 file2.write("""<html xmlns:xi="http://www.w3.org/2001/XInclude" | |
1671 xmlns:py="http://genshi.edgewall.org/" | |
1672 xmlns:i18n="http://genshi.edgewall.org/i18n" | |
1673 i18n:domain="foo"> | |
1674 <xi:include href="tmpl${idx}.html" py:with="idx = idx+1"/> | |
1675 </html>""") | |
1676 finally: | |
1677 file2.close() | |
1678 | |
1679 def callback(template): | |
1680 translations = DummyTranslations({'Bar %(idx)s': 'Voh %(idx)s'}) | |
1681 translations.add_domain('foo', {'Bar %(idx)s': 'foo_Bar %(idx)s'}) | |
1682 translations.add_domain('bar', {'Bar': 'bar_Bar'}) | |
1683 translator = Translator(translations) | |
1684 translator.setup(template) | |
1685 loader = TemplateLoader([dirname], callback=callback) | |
1686 tmpl = loader.load('tmpl10.html') | |
1687 | |
1688 self.assertEqual("""<html> | |
1689 <div>Included tmpl0</div> | |
1690 <p>foo_Bar 0</p> | |
1691 <p>bar_Bar</p> | |
1692 <p>Voh 0</p> | |
1693 <p>Voh 0</p> | |
1694 <div>Included tmpl1</div> | |
1695 <p>foo_Bar 1</p> | |
1696 <p>bar_Bar</p> | |
1697 <p>Voh 1</p> | |
1698 <p>Voh 1</p> | |
1699 <div>Included tmpl2</div> | |
1700 <p>foo_Bar 2</p> | |
1701 <p>bar_Bar</p> | |
1702 <p>Voh 2</p> | |
1703 <p>Voh 2</p> | |
1704 <div>Included tmpl3</div> | |
1705 <p>foo_Bar 3</p> | |
1706 <p>bar_Bar</p> | |
1707 <p>Voh 3</p> | |
1708 <p>Voh 3</p> | |
1709 <div>Included tmpl4</div> | |
1710 <p>foo_Bar 4</p> | |
1711 <p>bar_Bar</p> | |
1712 <p>Voh 4</p> | |
1713 <p>Voh 4</p> | |
1714 <div>Included tmpl5</div> | |
1715 <p>foo_Bar 5</p> | |
1716 <p>bar_Bar</p> | |
1717 <p>Voh 5</p> | |
1718 <p>Voh 5</p> | |
1719 <div>Included tmpl6</div> | |
1720 <p>foo_Bar 6</p> | |
1721 <p>bar_Bar</p> | |
1722 <p>Voh 6</p> | |
1723 <p>Voh 6</p> | |
1724 </html>""", tmpl.generate(idx=-1).render()) | |
1725 finally: | |
1726 shutil.rmtree(dirname) | |
1727 | |
1728 def test_translate_i18n_domain_with_nested_includes_with_translatable_attrs(self): | |
1729 import os, shutil, tempfile | |
1730 from genshi.template.loader import TemplateLoader | |
1731 dirname = tempfile.mkdtemp(suffix='genshi_test') | |
1732 try: | |
1733 for idx in range(4): | |
1734 file1 = open(os.path.join(dirname, 'tmpl%d.html' % idx), 'w') | |
1735 try: | |
1736 file1.write("""<html xmlns:xi="http://www.w3.org/2001/XInclude" | |
1737 xmlns:py="http://genshi.edgewall.org/" | |
1738 xmlns:i18n="http://genshi.edgewall.org/i18n" py:strip=""> | |
1739 <div>Included tmpl$idx</div> | |
1740 <p title="${dg('foo', 'Bar %(idx)s') % dict(idx=idx)}" i18n:msg="idx">Bar $idx</p> | |
1741 <p title="Bar" i18n:domain="bar">Bar</p> | |
1742 <p title="Bar" i18n:msg="idx" i18n:domain="">Bar $idx</p> | |
1743 <p i18n:msg="idx" i18n:domain="" title="Bar">Bar $idx</p> | |
1744 <p i18n:domain="" i18n:msg="idx" title="Bar">Bar $idx</p> | |
1745 <py:if test="idx < 3"> | |
1746 <xi:include href="tmpl${idx}.html" py:with="idx = idx+1"/> | |
1747 </py:if> | |
1748 </html>""") | |
1749 finally: | |
1750 file1.close() | |
1751 | |
1752 file2 = open(os.path.join(dirname, 'tmpl10.html'), 'w') | |
1753 try: | |
1754 file2.write("""<html xmlns:xi="http://www.w3.org/2001/XInclude" | |
1755 xmlns:py="http://genshi.edgewall.org/" | |
1756 xmlns:i18n="http://genshi.edgewall.org/i18n" | |
1757 i18n:domain="foo"> | |
1758 <xi:include href="tmpl${idx}.html" py:with="idx = idx+1"/> | |
1759 </html>""") | |
1760 finally: | |
1761 file2.close() | |
1762 | |
1763 translations = DummyTranslations({'Bar %(idx)s': 'Voh %(idx)s', | |
1764 'Bar': 'Voh'}) | |
1765 translations.add_domain('foo', {'Bar %(idx)s': 'foo_Bar %(idx)s'}) | |
1766 translations.add_domain('bar', {'Bar': 'bar_Bar'}) | |
1767 translator = Translator(translations) | |
1768 | |
1769 def callback(template): | |
1770 translator.setup(template) | |
1771 loader = TemplateLoader([dirname], callback=callback) | |
1772 tmpl = loader.load('tmpl10.html') | |
1773 | |
1774 self.assertEqual("""<html> | |
1775 <div>Included tmpl0</div> | |
1776 <p title="foo_Bar 0">foo_Bar 0</p> | |
1777 <p title="bar_Bar">bar_Bar</p> | |
1778 <p title="Voh">Voh 0</p> | |
1779 <p title="Voh">Voh 0</p> | |
1780 <p title="Voh">Voh 0</p> | |
1781 <div>Included tmpl1</div> | |
1782 <p title="foo_Bar 1">foo_Bar 1</p> | |
1783 <p title="bar_Bar">bar_Bar</p> | |
1784 <p title="Voh">Voh 1</p> | |
1785 <p title="Voh">Voh 1</p> | |
1786 <p title="Voh">Voh 1</p> | |
1787 <div>Included tmpl2</div> | |
1788 <p title="foo_Bar 2">foo_Bar 2</p> | |
1789 <p title="bar_Bar">bar_Bar</p> | |
1790 <p title="Voh">Voh 2</p> | |
1791 <p title="Voh">Voh 2</p> | |
1792 <p title="Voh">Voh 2</p> | |
1793 <div>Included tmpl3</div> | |
1794 <p title="foo_Bar 3">foo_Bar 3</p> | |
1795 <p title="bar_Bar">bar_Bar</p> | |
1796 <p title="Voh">Voh 3</p> | |
1797 <p title="Voh">Voh 3</p> | |
1798 <p title="Voh">Voh 3</p> | |
1799 </html>""", tmpl.generate(idx=-1, | |
1800 dg=translations.dugettext).render()) | |
1801 finally: | |
1802 shutil.rmtree(dirname) | |
469 | 1803 |
470 | 1804 |
471 class ExtractTestCase(unittest.TestCase): | 1805 class ExtractTestCase(unittest.TestCase): |
472 | 1806 |
473 def test_markup_template_extraction(self): | 1807 def test_markup_template_extraction(self): |
481 <p>${ngettext("You have %d item", "You have %d items", num)}</p> | 1815 <p>${ngettext("You have %d item", "You have %d items", num)}</p> |
482 </body> | 1816 </body> |
483 </html>""") | 1817 </html>""") |
484 results = list(extract(buf, ['_', 'ngettext'], [], {})) | 1818 results = list(extract(buf, ['_', 'ngettext'], [], {})) |
485 self.assertEqual([ | 1819 self.assertEqual([ |
486 (3, None, u'Example', []), | 1820 (3, None, 'Example', []), |
487 (6, None, u'Example', []), | 1821 (6, None, 'Example', []), |
488 (7, '_', u'Hello, %(name)s', []), | 1822 (7, '_', 'Hello, %(name)s', []), |
489 (8, 'ngettext', (u'You have %d item', u'You have %d items', None), | 1823 (8, 'ngettext', ('You have %d item', 'You have %d items', None), |
490 []), | 1824 []), |
491 ], results) | 1825 ], results) |
492 | 1826 |
493 def test_extraction_without_text(self): | 1827 def test_extraction_without_text(self): |
494 buf = StringIO("""<html xmlns:py="http://genshi.edgewall.org/"> | 1828 buf = StringIO("""<html xmlns:py="http://genshi.edgewall.org/"> |
497 </html>""") | 1831 </html>""") |
498 results = list(extract(buf, ['_', 'ngettext'], [], { | 1832 results = list(extract(buf, ['_', 'ngettext'], [], { |
499 'extract_text': 'no' | 1833 'extract_text': 'no' |
500 })) | 1834 })) |
501 self.assertEqual([ | 1835 self.assertEqual([ |
502 (3, 'ngettext', (u'Singular', u'Plural', None), []), | 1836 (3, 'ngettext', ('Singular', 'Plural', None), []), |
503 ], results) | 1837 ], results) |
504 | 1838 |
505 def test_text_template_extraction(self): | 1839 def test_text_template_extraction(self): |
506 buf = StringIO("""${_("Dear %(name)s") % {'name': name}}, | 1840 buf = StringIO("""${_("Dear %(name)s") % {'name': name}}, |
507 | 1841 |
508 ${ngettext("Your item:", "Your items", len(items))} | 1842 ${ngettext("Your item:", "Your items", len(items))} |
509 #for item in items | 1843 #for item in items |
510 * $item | 1844 * $item |
511 #end | 1845 #end |
512 | 1846 |
513 All the best, | 1847 All the best, |
514 Foobar""") | 1848 Foobar""") |
515 results = list(extract(buf, ['_', 'ngettext'], [], { | 1849 results = list(extract(buf, ['_', 'ngettext'], [], { |
516 'template_class': 'genshi.template:TextTemplate' | 1850 'template_class': 'genshi.template:TextTemplate' |
517 })) | 1851 })) |
518 self.assertEqual([ | 1852 self.assertEqual([ |
519 (1, '_', u'Dear %(name)s', []), | 1853 (1, '_', 'Dear %(name)s', []), |
520 (3, 'ngettext', (u'Your item:', u'Your items', None), []), | 1854 (3, 'ngettext', ('Your item:', 'Your items', None), []), |
521 (7, None, u'All the best,\n Foobar', []) | 1855 (7, None, 'All the best,\n Foobar', []) |
522 ], results) | 1856 ], results) |
523 | 1857 |
524 def test_extraction_with_keyword_arg(self): | 1858 def test_extraction_with_keyword_arg(self): |
525 buf = StringIO("""<html xmlns:py="http://genshi.edgewall.org/"> | 1859 buf = StringIO("""<html xmlns:py="http://genshi.edgewall.org/"> |
526 ${gettext('Foobar', foo='bar')} | 1860 ${gettext('Foobar', foo='bar')} |
527 </html>""") | 1861 </html>""") |
528 results = list(extract(buf, ['gettext'], [], {})) | 1862 results = list(extract(buf, ['gettext'], [], {})) |
529 self.assertEqual([ | 1863 self.assertEqual([ |
530 (2, 'gettext', (u'Foobar'), []), | 1864 (2, 'gettext', ('Foobar'), []), |
531 ], results) | 1865 ], results) |
532 | 1866 |
533 def test_extraction_with_nonstring_arg(self): | 1867 def test_extraction_with_nonstring_arg(self): |
534 buf = StringIO("""<html xmlns:py="http://genshi.edgewall.org/"> | 1868 buf = StringIO("""<html xmlns:py="http://genshi.edgewall.org/"> |
535 ${dgettext(curdomain, 'Foobar')} | 1869 ${dgettext(curdomain, 'Foobar')} |
536 </html>""") | 1870 </html>""") |
537 results = list(extract(buf, ['dgettext'], [], {})) | 1871 results = list(extract(buf, ['dgettext'], [], {})) |
538 self.assertEqual([ | 1872 self.assertEqual([ |
539 (2, 'dgettext', (None, u'Foobar'), []), | 1873 (2, 'dgettext', (None, 'Foobar'), []), |
540 ], results) | 1874 ], results) |
541 | 1875 |
542 def test_extraction_inside_ignored_tags(self): | 1876 def test_extraction_inside_ignored_tags(self): |
543 buf = StringIO("""<html xmlns:py="http://genshi.edgewall.org/"> | 1877 buf = StringIO("""<html xmlns:py="http://genshi.edgewall.org/"> |
544 <script type="text/javascript"> | 1878 <script type="text/javascript"> |
548 }); | 1882 }); |
549 </script> | 1883 </script> |
550 </html>""") | 1884 </html>""") |
551 results = list(extract(buf, ['_'], [], {})) | 1885 results = list(extract(buf, ['_'], [], {})) |
552 self.assertEqual([ | 1886 self.assertEqual([ |
553 (5, '_', u'Please wait...', []), | 1887 (5, '_', 'Please wait...', []), |
554 ], results) | 1888 ], results) |
555 | 1889 |
556 def test_extraction_inside_ignored_tags_with_directives(self): | 1890 def test_extraction_inside_ignored_tags_with_directives(self): |
557 buf = StringIO("""<html xmlns:py="http://genshi.edgewall.org/"> | 1891 buf = StringIO("""<html xmlns:py="http://genshi.edgewall.org/"> |
558 <script type="text/javascript"> | 1892 <script type="text/javascript"> |
561 </py:if> | 1895 </py:if> |
562 </script> | 1896 </script> |
563 </html>""") | 1897 </html>""") |
564 self.assertEqual([], list(extract(buf, ['_'], [], {}))) | 1898 self.assertEqual([], list(extract(buf, ['_'], [], {}))) |
565 | 1899 |
1900 def test_extract_py_def_directive_with_py_strip(self): | |
1901 # Failed extraction from Trac | |
1902 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" py:strip=""> | |
1903 <py:def function="diff_options_fields(diff)"> | |
1904 <label for="style">View differences</label> | |
1905 <select id="style" name="style"> | |
1906 <option selected="${diff.style == 'inline' or None}" | |
1907 value="inline">inline</option> | |
1908 <option selected="${diff.style == 'sidebyside' or None}" | |
1909 value="sidebyside">side by side</option> | |
1910 </select> | |
1911 <div class="field"> | |
1912 Show <input type="text" name="contextlines" id="contextlines" size="2" | |
1913 maxlength="3" value="${diff.options.contextlines < 0 and 'all' or diff.options.contextlines}" /> | |
1914 <label for="contextlines">lines around each change</label> | |
1915 </div> | |
1916 <fieldset id="ignore" py:with="options = diff.options"> | |
1917 <legend>Ignore:</legend> | |
1918 <div class="field"> | |
1919 <input type="checkbox" id="ignoreblanklines" name="ignoreblanklines" | |
1920 checked="${options.ignoreblanklines or None}" /> | |
1921 <label for="ignoreblanklines">Blank lines</label> | |
1922 </div> | |
1923 <div class="field"> | |
1924 <input type="checkbox" id="ignorecase" name="ignorecase" | |
1925 checked="${options.ignorecase or None}" /> | |
1926 <label for="ignorecase">Case changes</label> | |
1927 </div> | |
1928 <div class="field"> | |
1929 <input type="checkbox" id="ignorewhitespace" name="ignorewhitespace" | |
1930 checked="${options.ignorewhitespace or None}" /> | |
1931 <label for="ignorewhitespace">White space changes</label> | |
1932 </div> | |
1933 </fieldset> | |
1934 <div class="buttons"> | |
1935 <input type="submit" name="update" value="${_('Update')}" /> | |
1936 </div> | |
1937 </py:def></html>""") | |
1938 translator = Translator() | |
1939 tmpl.add_directives(Translator.NAMESPACE, translator) | |
1940 messages = list(translator.extract(tmpl.stream)) | |
1941 self.assertEqual(10, len(messages)) | |
1942 self.assertEqual([ | |
1943 (3, None, 'View differences', []), | |
1944 (6, None, 'inline', []), | |
1945 (8, None, 'side by side', []), | |
1946 (10, None, 'Show', []), | |
1947 (13, None, 'lines around each change', []), | |
1948 (16, None, 'Ignore:', []), | |
1949 (20, None, 'Blank lines', []), | |
1950 (25, None, 'Case changes',[]), | |
1951 (30, None, 'White space changes', []), | |
1952 (34, '_', 'Update', [])], messages) | |
1953 | |
566 | 1954 |
567 def suite(): | 1955 def suite(): |
568 suite = unittest.TestSuite() | 1956 suite = unittest.TestSuite() |
569 suite.addTest(doctest.DocTestSuite(Translator.__module__)) | 1957 suite.addTest(doctest.DocTestSuite(Translator.__module__)) |
570 suite.addTest(unittest.makeSuite(TranslatorTestCase, 'test')) | 1958 suite.addTest(unittest.makeSuite(TranslatorTestCase, 'test')) |
1959 suite.addTest(unittest.makeSuite(MsgDirectiveTestCase, 'test')) | |
1960 suite.addTest(unittest.makeSuite(ChooseDirectiveTestCase, 'test')) | |
1961 suite.addTest(unittest.makeSuite(DomainDirectiveTestCase, 'test')) | |
571 suite.addTest(unittest.makeSuite(ExtractTestCase, 'test')) | 1962 suite.addTest(unittest.makeSuite(ExtractTestCase, 'test')) |
572 return suite | 1963 return suite |
573 | 1964 |
574 if __name__ == '__main__': | 1965 if __name__ == '__main__': |
575 unittest.main(defaultTest='suite') | 1966 unittest.main(defaultTest='suite') |