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