1# -*- coding: utf-8 -*-
2import unittest
3
4import pytest
5
6from babel.messages import extract
7from babel._compat import BytesIO
8
9import django
10from enmerkar.extract import extract_django
11
12
13default_keys = extract.DEFAULT_KEYWORDS.keys()
14
15
16class ExtractDjangoTestCase(unittest.TestCase):
17    # TODO: translator comments are not yet supported!
18
19    def test_extract_no_tags(self):
20        buf = BytesIO(b'nothing')
21        messages = list(extract_django(buf, default_keys, [], {}))
22        self.assertEqual([], messages)
23
24    def test_extract_simple_double_quotes(self):
25        buf = BytesIO(b'{% trans "Bunny" %}')
26        messages = list(extract_django(buf, default_keys, [], {}))
27        self.assertEqual([(1, None, u'Bunny', [])], messages)
28
29    def test_extract_simple_single_quotes(self):
30        buf = BytesIO(b"{% trans 'Bunny' %}")
31        messages = list(extract_django(buf, default_keys, [], {}))
32        self.assertEqual([(1, None, u'Bunny', [])], messages)
33
34    def test_extract_simple_with_context_single_quotes(self):
35        buf = BytesIO(b"{% trans 'Bunny' context 'carrot' %}")
36        messages = list(extract_django(buf, default_keys, [], {}))
37        self.assertEqual([(1, 'pgettext',
38                           [u'carrot', u'Bunny'], [])], messages)
39
40    def test_extract_simple_with_context_double_quotes(self):
41        buf = BytesIO(b"{% trans 'Bunny' context \"carrot\" %}")
42        messages = list(extract_django(buf, default_keys, [], {}))
43        self.assertEqual([(1, 'pgettext',
44                           [u'carrot', u'Bunny'], [])], messages)
45
46    def test_extract_simple_with_context_with_single_quotes(self):
47        buf = BytesIO(b"{% trans 'Bunny' context \"'carrot'\" %}")
48        messages = list(extract_django(buf, default_keys, [], {}))
49        self.assertEqual([(1, 'pgettext',
50                           [u'\'carrot\'', u'Bunny'], [])], messages)
51
52    def test_extract_simple_with_context_with_double_quotes(self):
53        buf = BytesIO(b"{% trans 'Bunny' context '\"carrot\"' %}")
54        messages = list(extract_django(buf, default_keys, [], {}))
55        self.assertEqual([(1, 'pgettext',
56                           [u'"carrot"', u'Bunny'], [])], messages)
57
58    def test_extract_var(self):
59        buf = BytesIO(b'{% blocktrans %}{{ anton }}{% endblocktrans %}')
60        messages = list(extract_django(buf, default_keys, [], {}))
61        self.assertEqual([(1, None, u'%(anton)s', [])], messages)
62
63    def test_extract_filter_with_filter(self):
64        test_tmpl = (
65            b'{% blocktrans with berta=anton|lower %}'
66            b'{{ berta }}{% endblocktrans %}'
67        )
68        buf = BytesIO(test_tmpl)
69        messages = list(extract_django(buf, default_keys, [], {}))
70        self.assertEqual([(1, None, u'%(berta)s', [])], messages)
71
72    def test_extract_with_interpolation(self):
73        buf = BytesIO(b'{% blocktrans %}xxx{{ anton }}xxx{% endblocktrans %}')
74        messages = list(extract_django(buf, default_keys, [], {}))
75        self.assertEqual([(1, None, u'xxx%(anton)sxxx', [])], messages)
76
77    def test_extract_unicode(self):
78        buf = BytesIO(u'{% trans "@ſðæ314“ſſ¶ÐĐÞ→SÆ^ĸŁ" %}'.encode('utf8'))
79        messages = list(extract_django(buf, default_keys, [], {}))
80        self.assertEqual([(1, None, u'@ſðæ314“ſſ¶ÐĐÞ→SÆ^ĸŁ', [])], messages)
81
82    def test_extract_unicode_blocktrans(self):
83        test_tmpl = u'{% blocktrans %}@ſðæ314“ſſ¶ÐĐÞ→SÆ^ĸŁ{% endblocktrans %}'
84        buf = BytesIO(test_tmpl.encode('utf8'))
85        messages = list(extract_django(buf, default_keys, [], {}))
86        self.assertEqual([(1, None, u'@ſðæ314“ſſ¶ÐĐÞ→SÆ^ĸŁ', [])], messages)
87
88    # TODO: Yet expected to not extract the comments.
89    def test_extract_ignored_comment(self):
90        buf = BytesIO(
91            b'{# ignored comment #1 #}{% trans "Translatable literal #9a" %}',
92        )
93        messages = list(extract_django(buf, default_keys, [], {}))
94        self.assertEqual(
95            [(1, None, u'Translatable literal #9a', [])], messages
96        )
97
98    def test_extract_ignored_comment2(self):
99        test_tmpl = (
100            b'{# Translators: ignored i18n comment #1 #}'
101            b'{% trans "Translatable literal #9a" %}'
102        )
103        buf = BytesIO(test_tmpl)
104        messages = list(extract_django(buf, default_keys, [], {}))
105        self.assertEqual(
106            [(1, None, u'Translatable literal #9a', [])], messages
107        )
108
109    def test_extract_valid_comment(self):
110        test_tmpl = (
111            b'{# ignored comment #6 #}'
112            b'{% trans "Translatable literal #9h" %}'
113            b'{# Translators: valid i18n comment #7 #}'
114        )
115        buf = BytesIO(test_tmpl)
116        messages = list(extract_django(buf, default_keys, [], {}))
117        self.assertEqual(
118            [(1, None, u'Translatable literal #9h', [])], messages
119        )
120
121    def test_extract_singular_form(self):
122        test_tmpl = (
123            b'{% blocktrans count counter=number %}'
124            b'singular{% plural %}{{ counter }} plural'
125            b'{% endblocktrans %}'
126        )
127        buf = BytesIO(test_tmpl)
128        messages = list(extract_django(buf, default_keys, [], {}))
129        self.assertEqual(
130            [(1, 'ngettext', (u'singular', u'%(counter)s plural'), [])],
131            messages
132        )
133
134    def test_trans_blocks_must_not_include_other_block_tags(self):
135        buf = BytesIO(b'{% blocktrans %}{% other_tag %}{% endblocktrans %}')
136        gen = extract_django(buf, default_keys, [], {})
137        with pytest.raises(SyntaxError):
138            next(gen)
139
140    def test_extract_var_other(self):
141        buf = BytesIO(b'{{ book }}')
142        messages = list(extract_django(buf, default_keys, [], {}))
143        self.assertEqual([], messages)
144
145    def test_extract_filters_default_translatable(self):
146        buf = BytesIO(b'{{ book.author|default:_("Unknown") }}')
147        messages = list(extract_django(buf, default_keys, [], {}))
148        self.assertEqual([(1, None, u'Unknown', [])], messages)
149
150    def test_extract_filters_default_translatable_single_quotes(self):
151        buf = BytesIO(b"{{ book.author|default:_('Unknown') }}")
152        messages = list(extract_django(buf, default_keys, [], {}))
153        self.assertEqual([(1, None, u'Unknown', [])], messages)
154
155    def test_extract_constant_single_quotes(self):
156        buf = BytesIO(b"{{ _('constant') }}")
157        messages = list(extract_django(buf, default_keys, [], {}))
158        self.assertEqual([(1, None, u'constant', [])], messages)
159
160    def test_extract_constant_double_quotes(self):
161        buf = BytesIO(b'{{ _("constant") }}')
162        messages = list(extract_django(buf, default_keys, [], {}))
163        self.assertEqual([(1, None, u'constant', [])], messages)
164
165    def test_extract_constant_block(self):
166        buf = BytesIO(b'{% _("constant") %}')
167        messages = list(extract_django(buf, default_keys, [], {}))
168        self.assertEqual([(1, None, u'constant', [])], messages)
169
170    def test_extract_constant_in_block(self):
171        test_tmpl = (
172            b'{% blocktrans foo=_("constant") %}{{ foo }}{% endblocktrans %}'
173        )
174        buf = BytesIO(test_tmpl)
175        messages = list(extract_django(buf, default_keys, [], {}))
176        self.assertEqual(
177            [(1, None, u'constant', []), (1, None, u'%(foo)s', [])],
178            messages,
179        )
180
181    def test_extract_context_in_block(self):
182        test_tmpl = (
183            b'{% blocktrans context "banana" %}{{ foo }}{% endblocktrans %}'
184        )
185        buf = BytesIO(test_tmpl)
186        messages = list(extract_django(buf, default_keys, [], {}))
187        self.assertEqual(
188            [(1, 'pgettext', [u'banana', u'%(foo)s'], [])],
189            messages,
190        )
191
192    def test_extract_context_in_plural_block(self):
193        test_tmpl = (
194            b'{% blocktrans context "banana" %}{{ foo }}'
195            b'{% plural %}{{ bar }}{% endblocktrans %}'
196        )
197        buf = BytesIO(test_tmpl)
198        messages = list(extract_django(buf, default_keys, [], {}))
199        self.assertEqual(
200            [(1, 'npgettext', [u'banana', u'%(foo)s', u'%(bar)s'], [])],
201            messages,
202        )
203
204    def test_blocktrans_with_whitespace_not_trimmed(self):
205        test_tmpl = (
206            b'{% blocktrans %}\n\tfoo\n\tbar\n{% endblocktrans %}'
207        )
208        buf = BytesIO(test_tmpl)
209        messages = list(extract_django(buf, default_keys, [], {}))
210        self.assertEqual([(4, None, u'\n\tfoo\n\tbar\n', [])], messages)
211
212    @pytest.mark.skipif(django.VERSION < (1, 7),
213                        reason='Trimmed whitespace is a Django >= 1.7 feature')
214    def test_blocktrans_with_whitespace_trimmed(self):
215        test_tmpl = (
216            b'{% blocktrans trimmed %}\n\tfoo\n\tbar\n{% endblocktrans %}'
217        )
218        buf = BytesIO(test_tmpl)
219        messages = list(extract_django(buf, default_keys, [], {}))
220        self.assertEqual([(4, None, u'foo bar', [])], messages)
221