1from io import BytesIO 2 3from pytest import mark, raises 4 5from translate.convert import po2php, test_convert 6from translate.storage import po 7 8 9class TestPO2Php: 10 def po2php(self, posource): 11 """helper that converts po source to .php source without requiring files""" 12 inputfile = BytesIO(posource.encode()) 13 inputpo = po.pofile(inputfile) 14 convertor = po2php.po2php() 15 return convertor.convertstore(inputpo) 16 17 def merge2php(self, phpsource, posource): 18 """helper that merges po translations to .php source without requiring files""" 19 inputfile = BytesIO(posource.encode()) 20 inputpo = po.pofile(inputfile) 21 templatefile = BytesIO(phpsource.encode()) 22 # templatephp = php.phpfile(templatefile) 23 convertor = po2php.rephp(templatefile, inputpo) 24 outputphp = convertor.convertstore().decode() 25 print(outputphp) 26 return outputphp 27 28 def test_convertphp(self): 29 """test convertphp helper""" 30 posource = """#: $lang['name'] 31msgid "value" 32msgstr "waarde" 33""" 34 phptemplate = """$lang['name'] = 'value'; 35""" 36 phpexpected = b"""<?php 37$lang['name'] = 'waarde'; 38""" 39 inputfile = BytesIO(posource.encode()) 40 templatefile = BytesIO(phptemplate.encode()) 41 outputfile = BytesIO() 42 assert po2php.convertphp(inputfile, outputfile, templatefile) == 1 43 assert outputfile.getvalue() == phpexpected 44 45 def test_convertphp_notemplate(self): 46 """test convertphp helper without template""" 47 posource = """#: $lang['name'] 48msgid "value" 49msgstr "waarde" 50""" 51 inputfile = BytesIO(posource.encode()) 52 outputfile = BytesIO() 53 with raises(ValueError): 54 po2php.convertphp(inputfile, outputfile, None) 55 56 def test_convertphp_empty_template(self): 57 """test convertphp helper with empty translation""" 58 posource = """#: $lang['name'] 59msgid "value" 60msgstr "" 61""" 62 inputfile = BytesIO(posource.encode()) 63 templatefile = BytesIO(b"") 64 outputfile = BytesIO() 65 assert ( 66 po2php.convertphp(inputfile, outputfile, templatefile, False, 100) is False 67 ) 68 assert outputfile.getvalue() == b"" 69 70 def test_merging_simple(self): 71 """check the simplest case of merging a translation""" 72 posource = """#: $lang['name'] 73msgid "value" 74msgstr "waarde" 75""" 76 phptemplate = """<?php 77$lang['name'] = 'value'; 78""" 79 phpexpected = """<?php 80$lang['name'] = 'waarde'; 81""" 82 phpfile = self.merge2php(phptemplate, posource) 83 print(phpfile) 84 assert phpfile == phpexpected 85 86 def test_space_preservation(self): 87 """check that we preserve any spacing in php files when merging""" 88 posource = """#: $lang['name'] 89msgid "value" 90msgstr "waarde" 91""" 92 phptemplate = """<?php 93$lang['name'] = 'value'; 94""" 95 phpexpected = """<?php 96$lang['name'] = 'waarde'; 97""" 98 phpfile = self.merge2php(phptemplate, posource) 99 print(phpfile) 100 assert phpfile == phpexpected 101 102 def test_preserve_unused_statement(self): 103 """check that we preserve any unused statements in php files when merging""" 104 posource = """#: $lang['name'] 105msgid "value" 106msgstr "waarde" 107""" 108 phptemplate = """<?php 109error_reporting(E_ALL); 110$lang['name'] = 'value'; 111""" 112 phpexpected = """<?php 113$lang['name'] = 'waarde'; 114""" 115 phpfile = self.merge2php(phptemplate, posource) 116 assert phpfile == phpexpected 117 118 def test_not_translated_multiline(self): 119 """check that we preserve not translated multiline strings in php files when merging""" 120 posource = """#: $lang['name'] 121msgid "value" 122msgstr "waarde" 123""" 124 phptemplate = """<?php 125$lang['name'] = 'value'; 126$lang['second'] = " 127value"; 128""" 129 phpexpected = """<?php 130$lang['name'] = 'waarde'; 131$lang['second'] = " 132value"; 133""" 134 phpfile = self.merge2php(phptemplate, posource) 135 assert phpfile == phpexpected 136 137 def test_merging_blank_entries(self): 138 """check that we can correctly merge entries that are blank in the template""" 139 posource = r'''#: accesskey-accept 140msgid "" 141"_: accesskey-accept\n" 142"" 143msgstr ""''' 144 phptemplate = """<?php 145$lang['accesskey-accept'] = ''; 146""" 147 phpexpected = """<?php 148$lang['accesskey-accept'] = ''; 149""" 150 phpfile = self.merge2php(phptemplate, posource) 151 print(phpfile) 152 assert phpfile == phpexpected 153 154 def test_merging_fuzzy(self): 155 """check merging a fuzzy translation""" 156 posource = """#: %24lang%5B+%27name%27+%5D 157#, fuzzy 158msgid "value" 159msgstr "waarde" 160""" 161 phptemplate = """<?php 162$lang['name'] = 'value'; 163""" 164 phpexpected = """<?php 165$lang['name'] = 'value'; 166""" 167 phpfile = self.merge2php(phptemplate, posource) 168 print(phpfile) 169 assert phpfile == phpexpected 170 171 def test_locations_with_spaces(self): 172 """check that a location with spaces in php but spaces removed in PO is used correctly""" 173 posource = """#: %24lang%5B+%27name%27+%5D 174msgid "value" 175msgstr "waarde"\n""" 176 phptemplate = """<?php 177$lang[ 'name' ] = 'value'; 178""" 179 phpexpected = """<?php 180$lang[ 'name' ] = 'waarde'; 181""" 182 phpfile = self.merge2php(phptemplate, posource) 183 print(phpfile) 184 assert phpfile == phpexpected 185 186 def test_inline_comments(self): 187 """check that we include inline comments from the template. Bug 590""" 188 posource = """#: %24lang%5B+%27name%27+%5D 189msgid "value" 190msgstr "waarde" 191""" 192 phptemplate = """<?php 193$lang[ 'name' ] = 'value'; //inline comment 194""" 195 phpexpected = """<?php 196//inline comment 197$lang[ 'name' ] = 'waarde'; 198""" 199 phpfile = self.merge2php(phptemplate, posource) 200 print(phpfile) 201 assert phpfile == phpexpected 202 203 def test_block_comments(self): 204 """check that we include block comments from the template""" 205 posource = """#: %24lang%5B+%27name%27+%5D 206msgid "value" 207msgstr "waarde" 208""" 209 phptemplate = """<?php 210/* some comment */ 211$lang[ 'name' ] = 'value'; 212""" 213 phpexpected = """<?php 214/* some comment */ 215$lang[ 'name' ] = 'waarde'; 216""" 217 phpfile = self.merge2php(phptemplate, posource) 218 assert phpfile == phpexpected 219 220 def test_named_variables(self): 221 """check that we convert correctly if using named variables.""" 222 posource = """#: $dictYear 223msgid "Year" 224msgstr "Jaar" 225""" 226 phptemplate = """<?php 227$dictYear = 'Year'; 228""" 229 phpexpected = """<?php 230$dictYear = 'Jaar'; 231""" 232 phpfile = self.merge2php(phptemplate, posource) 233 print(phpfile) 234 assert phpfile == phpexpected 235 236 def test_multiline(self): 237 """ 238 Check that we convert multiline strings correctly. 239 240 Bug 1296. 241 """ 242 posource = r"""#: $string['upgradesure'] 243msgid "" 244"Your Moodle files have been changed, and you are\n" 245"about to automatically upgrade your server to this version:\n" 246"<p><b>$a</b></p>\n" 247"<p>Once you do this you can not go back again.</p>\n" 248"<p>Are you sure you want to upgrade this server to this version?</p>" 249msgstr "" 250""" 251 phptemplate = """<?php 252$string['upgradesure'] = 'Your Moodle files have been changed, and you are 253about to automatically upgrade your server to this version: 254<p><b>$a</b></p> 255<p>Once you do this you can not go back again.</p> 256<p>Are you sure you want to upgrade this server to this version?</p>';\n""" 257 phpfile = self.merge2php(phptemplate, posource) 258 print(phpfile) 259 assert phpfile == phptemplate 260 261 def test_hash_comment(self): 262 """check that we convert # comments correctly.""" 263 posource = """#: $variable 264msgid "stringy" 265msgstr "stringetjie" 266""" 267 phptemplate = """<?php 268# inside alt= stuffies 269$variable = 'stringy'; 270""" 271 phpexpected = """<?php 272# inside alt= stuffies 273$variable = 'stringetjie'; 274""" 275 phpfile = self.merge2php(phptemplate, posource) 276 print(phpfile) 277 assert phpfile == phpexpected 278 279 def test_arrays(self): 280 """check that we can handle arrays""" 281 posource = """#: $lang->'name' 282msgid "value" 283msgstr "waarde" 284""" 285 phptemplate = """<?php 286$lang = array( 287 'name' => 'value', 288); 289""" 290 phpexpected = """<?php 291$lang = array( 292 'name' => 'waarde', 293); 294""" 295 phpfile = self.merge2php(phptemplate, posource) 296 print(phpfile) 297 assert phpfile == phpexpected 298 299 def test_named_nested_array(self): 300 """check that we can handle nested arrays""" 301 posource = """#: $lang->'codes'->'name' 302msgid "value" 303msgstr "waarde" 304""" 305 phptemplate = """<?php 306$lang = array( 307 'codes' => array( 308 'name' => 'value', 309 ), 310); 311""" 312 phpexpected = """<?php 313$lang = array( 314 'codes' => array( 315 'name' => 'waarde', 316 ), 317); 318""" 319 phpfile = self.merge2php(phptemplate, posource) 320 print(phpfile) 321 assert phpfile == phpexpected 322 323 def test_unnamed_nested_arrays(self): 324 posource = """ 325#: return->'name1' 326msgid "source1" 327msgstr "target1" 328 329#: return->'list1'->'l1' 330msgid "source_l1_1" 331msgstr "target_l1_1" 332 333#: return->'list1'->'list2'->'l1' 334msgid "source_l1_l2_l1" 335msgstr "target_l1_l2_l1" 336 337#: return->'list1'->'l3' 338msgid "source_l1_3" 339msgstr "target_l1_3" 340 341#: return->'name2' 342msgid "source2" 343msgstr "target2" 344""" 345 phptemplate = """<?php 346return array( 347 'name1' => 'source1', 348 'list1' => array( 349 'l1' => 'source_l1_1', 350 'list2' => array( 351 'l1' => 'source_l1_l2_l1', 352 ), 353 'l3' => 'source_l1_3', 354 ), 355 'name2' => 'source2', 356);""" 357 phpexpected = """<?php 358return array( 359 'name1' => 'target1', 360 'list1' => array( 361 'l1' => 'target_l1_1', 362 'list2' => array( 363 'l1' => 'target_l1_l2_l1', 364 ), 365 'l3' => 'target_l1_3', 366 ), 367 'name2' => 'target2', 368);\n""" 369 phpfile = self.merge2php(phptemplate, posource) 370 print(phpfile) 371 assert phpfile == phpexpected 372 373 @mark.xfail(reason="Need to review if we want this behaviour") 374 def test_merging_propertyless_template(self): 375 """check that when merging with a template with no property values that we copy the template""" 376 posource = "" 377 proptemplate = "# A comment\n" 378 propexpected = proptemplate 379 propfile = self.merge2prop(proptemplate, posource) 380 print(propfile) 381 assert propfile == [propexpected] 382 383 384class TestPO2PhpCommand(test_convert.TestConvertCommand, TestPO2Php): 385 """Tests running actual po2php commands on files""" 386 387 convertmodule = po2php 388 defaultoptions = {"progress": "none"} 389 390 def test_help(self, capsys): 391 """tests getting help""" 392 options = super().test_help(capsys) 393 options = self.help_check(options, "-t TEMPLATE, --template=TEMPLATE") 394 options = self.help_check(options, "--threshold=PERCENT") 395 options = self.help_check(options, "--fuzzy") 396 options = self.help_check(options, "--nofuzzy", last=True) 397