Package translate :: Package storage :: Module test_po
[hide private]
[frames] | no frames]

Source Code for Module translate.storage.test_po

  1  #!/usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3   
  4  from translate.storage import po 
  5  from translate.storage import test_base 
  6  from translate.misc import wStringIO 
  7  from translate.misc.multistring import multistring 
  8  from py.test import raises 
  9   
10 -def test_roundtrip_quoting():
11 specials = ['Fish & chips', 'five < six', 'six > five', 12 'Use &nbsp;', 'Use &amp;nbsp;' 13 'A "solution"', "skop 'n bal", '"""', "'''", 14 '\n', '\t', '\r', 15 '\\n', '\\t', '\\r', '\\"', '\r\n', '\\r\\n', '\\'] 16 for special in specials: 17 quoted_special = po.quoteforpo(special) 18 unquoted_special = po.unquotefrompo(quoted_special) 19 print "special: %r\nquoted: %r\nunquoted: %r\n" % (special, quoted_special, unquoted_special) 20 assert special == unquoted_special
21
22 -class TestPOUnit(test_base.TestTranslationUnit):
23 UnitClass = po.pounit
24 - def test_istranslatable(self):
25 """Tests for the correct behaviour of istranslatable().""" 26 unit = self.UnitClass("Message") 27 assert unit.istranslatable() 28 29 unit.source = "" 30 assert not unit.istranslatable() 31 # simulate a header 32 unit.target = "PO-Revision-Date: 2006-02-09 23:33+0200\n" 33 assert unit.isheader() 34 assert not unit.istranslatable() 35 36 unit.source = "Message" 37 unit.target = "Boodskap" 38 unit.makeobsolete() 39 assert not unit.istranslatable()
40
41 - def test_adding_empty_note(self):
42 unit = self.UnitClass("bla") 43 assert not '#' in str(unit) 44 unit.addnote("") 45 assert not '#' in str(unit)
46
47 - def test_markreview(self):
48 """Tests if we can mark the unit to need review.""" 49 unit = self.unit 50 # We have to explicitly set the target to nothing, otherwise xliff 51 # tests will fail. 52 # Can we make it default behavior for the UnitClass? 53 unit.target = "" 54 55 unit.addnote("Test note 1", origin="translator") 56 unit.addnote("Test note 2", origin="translator") 57 original_notes = unit.getnotes(origin="translator") 58 59 assert not unit.isreview() 60 unit.markreviewneeded() 61 print unit.getnotes() 62 assert unit.isreview() 63 unit.markreviewneeded(False) 64 assert not unit.isreview() 65 assert unit.getnotes(origin="translator") == original_notes 66 unit.markreviewneeded(explanation="Double check spelling.") 67 assert unit.isreview() 68 notes = unit.getnotes(origin="translator") 69 assert notes.count("Double check spelling.") == 1
70
71 - def test_errors(self):
72 """Tests that we can add and retrieve error messages for a unit.""" 73 unit = self.unit 74 75 assert len(unit.geterrors()) == 0 76 unit.adderror(errorname='test1', errortext='Test error message 1.') 77 unit.adderror(errorname='test2', errortext='Test error message 2.') 78 unit.adderror(errorname='test3', errortext='Test error message 3.') 79 assert len(unit.geterrors()) == 3 80 assert unit.geterrors()['test1'] == 'Test error message 1.' 81 assert unit.geterrors()['test2'] == 'Test error message 2.' 82 assert unit.geterrors()['test3'] == 'Test error message 3.' 83 unit.adderror(errorname='test1', errortext='New error 1.') 84 assert unit.geterrors()['test1'] == 'New error 1.'
85
86 - def test_no_plural_settarget(self):
87 """tests that target handling of file with no plural is correct""" 88 # plain text, no plural test 89 unit = self.UnitClass("Tree") 90 unit.target = "ki" 91 assert unit.target.strings == ["ki"] 92 assert unit.source.strings == ["Tree"] 93 assert unit.hasplural() == False 94 95 # plural test with multistring 96 unit.setsource(["Tree", "Trees"]) 97 assert unit.source.strings == ["Tree", "Trees"] 98 assert unit.hasplural() 99 unit.target = multistring(["ki", "ni ki"]) 100 assert unit.target.strings == ["ki", "ni ki"] 101 102 # test of msgid with no plural and msgstr with plural 103 unit = self.UnitClass("Tree") 104 assert raises(ValueError, unit.settarget, [u"ki", u"ni ki"]) 105 assert unit.hasplural() == False
106
107 - def test_wrapping_bug(self):
108 """This tests for a wrapping bug that existed at some stage.""" 109 unit = self.UnitClass("") 110 message = 'Projeke ya Pootle ka boyona e ho <a href="http://translate.sourceforge.net/">translate.sourceforge.net</a> moo o ka fumanang dintlha ka source code, di mailing list jwalo jwalo.' 111 unit.target = message 112 print unit.target 113 assert unit.target == message
114
116 """Test that KDE style comments are extracted correctly.""" 117 unit = self.UnitClass("test source") 118 119 kdetext = "_: Simple comment\nsimple text" 120 assert unit._extract_msgidcomments(kdetext) == "Simple comment"
121
122 - def test_isheader(self):
123 """checks that we deal correctly with headers.""" 124 unit = self.UnitClass() 125 unit.target = "PO-Revision-Date: 2006-02-09 23:33+0200\n" 126 assert unit.isheader() 127 unit.source = "Some English string" 128 assert not unit.isheader() 129 unit.source = u"Goeiemôre" 130 assert not unit.isheader()
131
132 -class TestPOFile(test_base.TestTranslationStore):
133 StoreClass = po.pofile
134 - def poparse(self, posource):
135 """helper that parses po source without requiring files""" 136 dummyfile = wStringIO.StringIO(posource) 137 pofile = self.StoreClass(dummyfile) 138 return pofile
139
140 - def poregen(self, posource):
141 """helper that converts po source to pofile object and back""" 142 return str(self.poparse(posource))
143
144 - def pomerge(self, oldmessage, newmessage, authoritative):
145 """helper that merges two messages""" 146 oldpofile = self.poparse(oldmessage) 147 oldunit = oldpofile.units[0] 148 if newmessage: 149 newpofile = self.poparse(newmessage) 150 newunit = newpofile.units[0] 151 else: 152 newunit = oldpofile.UnitClass() 153 oldunit.merge(newunit, authoritative=authoritative) 154 print oldunit 155 return str(oldunit)
156
157 - def test_simpleentry(self):
158 """checks that a simple po entry is parsed correctly""" 159 posource = '#: test.c:100 test.c:101\nmsgid "test"\nmsgstr "rest"\n' 160 pofile = self.poparse(posource) 161 assert len(pofile.units) == 1 162 thepo = pofile.units[0] 163 assert thepo.getlocations() == ["test.c:100", "test.c:101"] 164 assert thepo.source == "test" 165 assert thepo.target == "rest"
166
167 - def test_copy(self):
168 """checks that we can copy all the needed PO fields""" 169 posource = '''# TRANSLATOR-COMMENTS 170 #. AUTOMATIC-COMMENTS 171 #: REFERENCE... 172 #, fuzzy 173 msgctxt "CONTEXT" 174 msgid "UNTRANSLATED-STRING" 175 msgstr "TRANSLATED-STRING"''' 176 pofile = self.poparse(posource) 177 oldunit = pofile.units[0] 178 newunit = oldunit.copy() 179 assert newunit == oldunit
180
181 - def test_parse_source_string(self):
182 """parse a string""" 183 posource = '#: test.c\nmsgid "test"\nmsgstr "rest"\n' 184 pofile = self.poparse(posource) 185 assert len(pofile.units) == 1
186
187 - def test_parse_file(self):
188 """test parsing a real file""" 189 posource = '#: test.c\nmsgid "test"\nmsgstr "rest"\n' 190 pofile = self.poparse(posource) 191 assert len(pofile.units) == 1
192
193 - def test_unicode(self):
194 """check that the po class can handle Unicode characters""" 195 posource = 'msgid ""\nmsgstr ""\n"Content-Type: text/plain; charset=UTF-8\\n"\n\n#: test.c\nmsgid "test"\nmsgstr "rest\xe2\x80\xa6"\n' 196 pofile = self.poparse(posource) 197 print pofile 198 assert len(pofile.units) == 2
199
200 - def test_plurals(self):
201 posource = r'''msgid "Cow" 202 msgid_plural "Cows" 203 msgstr[0] "Koei" 204 msgstr[1] "Koeie" 205 ''' 206 pofile = self.poparse(posource) 207 assert len(pofile.units) == 1 208 unit = pofile.units[0] 209 assert isinstance(unit.target, multistring) 210 print unit.target.strings 211 assert unit.target == "Koei" 212 assert unit.target.strings == ["Koei", "Koeie"] 213 214 posource = r'''msgid "Skaap" 215 msgid_plural "Skape" 216 msgstr[0] "Sheep" 217 ''' 218 pofile = self.poparse(posource) 219 assert len(pofile.units) == 1 220 unit = pofile.units[0] 221 assert isinstance(unit.target, multistring) 222 print unit.target.strings 223 assert unit.target == "Sheep" 224 assert unit.target.strings == ["Sheep"]
225
226 - def test_plural_unicode(self):
227 """tests that all parts of the multistring are unicode.""" 228 posource = r'''msgid "Ców" 229 msgid_plural "Cóws" 230 msgstr[0] "Kóei" 231 msgstr[1] "Kóeie" 232 ''' 233 pofile = self.poparse(posource) 234 unit = pofile.units[0] 235 assert isinstance(unit.source, multistring) 236 assert isinstance(unit.source.strings[1], unicode)
237 238
239 - def wtest_kde_plurals(self):
240 """Tests kde-style plurals. (Bug: 191)""" 241 posource = '''msgid "_n Singular\n" 242 "Plural" 243 msgstr "Een\n" 244 "Twee\n" 245 "Drie" 246 ''' 247 pofile = self.poparse(posource) 248 assert len(pofile.units) == 1 249 unit = pofile.units[0] 250 assert unit.hasplural() == True 251 assert isinstance(unit.source, multistring) 252 print unit.source.strings 253 assert unit.source == "Singular" 254 assert unit.source.strings == ["Singular", "Plural"] 255 assert isinstance(unit.target, multistring) 256 print unit.target.strings 257 assert unit.target == "Een" 258 assert unit.target.strings == ["Een", "Twee", "Drie"]
259
260 - def test_empty_lines_notes(self):
261 """Tests that empty comment lines are preserved""" 262 posource = r'''# License name 263 # 264 # license line 1 265 # license line 2 266 # license line 3 267 msgid "" 268 msgstr "POT-Creation-Date: 2006-03-08 17:30+0200\n" 269 ''' 270 pofile = self.poparse(posource) 271 assert str(pofile) == posource
272
273 - def test_fuzzy(self):
274 """checks that fuzzy functionality works as expected""" 275 posource = '#, fuzzy\nmsgid "ball"\nmsgstr "bal"\n' 276 expectednonfuzzy = 'msgid "ball"\nmsgstr "bal"\n' 277 pofile = self.poparse(posource) 278 print pofile 279 assert pofile.units[0].isfuzzy() 280 pofile.units[0].markfuzzy(False) 281 assert not pofile.units[0].isfuzzy() 282 assert str(pofile) == expectednonfuzzy 283 284 posource = '#, fuzzy, python-format\nmsgid "ball"\nmsgstr "bal"\n' 285 expectednonfuzzy = '#, python-format\nmsgid "ball"\nmsgstr "bal"\n' 286 pofile = self.poparse(posource) 287 print pofile 288 assert pofile.units[0].isfuzzy() 289 pofile.units[0].markfuzzy(False) 290 assert not pofile.units[0].isfuzzy() 291 assert str(pofile) == expectednonfuzzy
292
294 """Tests making an untranslated unit obsolete""" 295 posource = '#. The automatic one\n#: test.c\nmsgid "test"\nmsgstr ""\n' 296 pofile = self.poparse(posource) 297 unit = pofile.units[0] 298 assert not unit.isobsolete() 299 unit.makeobsolete() 300 assert str(unit) == ""
301 # a better way might be for pomerge/pot2po to remove the unit 302
304 """checks that new automatic comments override old ones""" 305 oldsource = '#. old comment\n#: line:10\nmsgid "One"\nmsgstr "Een"\n' 306 newsource = '#. new comment\n#: line:10\nmsgid "One"\nmsgstr ""\n' 307 expected = '#. new comment\n#: line:10\nmsgid "One"\nmsgstr "Een"\n' 308 assert self.pomerge(newsource, oldsource, authoritative=True) == expected
309
310 - def test_malformed_units(self):
311 """Test that we handle malformed units reasonably.""" 312 posource = 'msgid "thing\nmsgstr "ding"\nmsgid "Second thing"\nmsgstr "Tweede ding"\n' 313 pofile = self.poparse(posource) 314 assert len(pofile.units) == 2
315
317 """Test that we handle malformed obsolete units reasonably.""" 318 posource = '''msgid "thing 319 msgstr "ding" 320 321 #~ msgid "Second thing" 322 #~ msgstr "Tweede ding" 323 #~ msgid "Third thing" 324 #~ msgstr "Derde ding" 325 ''' 326 pofile = self.poparse(posource) 327 assert len(pofile.units) == 3
328
329 - def test_uniforum_po(self):
330 """Test that we handle Uniforum PO files.""" 331 posource = '''# File: ../somefile.cpp, line: 33 332 msgid "thing" 333 msgstr "ding" 334 # 335 # File: anotherfile.cpp, line: 34 336 msgid "second" 337 msgstr "tweede" 338 ''' 339 pofile = self.poparse(posource) 340 assert len(pofile.units) == 2
341 # FIXME we still need to handle this correctly for proper Uniforum support if required 342 #assert pofile.units[0].getlocations() == "File: somefile, line: 300" 343 #assert pofile.units[1].getlocations() == "File: anotherfile, line: 200" 344
345 - def test_obsolete(self):
346 """Tests that obsolete messages work""" 347 posource = '#~ msgid "Old thing"\n#~ msgstr "Ou ding"\n' 348 pofile = self.poparse(posource) 349 assert pofile.isempty() 350 assert len(pofile.units) == 1 351 unit = pofile.units[0] 352 assert unit.isobsolete() 353 assert str(pofile) == posource
354
355 - def test_header_escapes(self):
356 pofile = self.StoreClass() 357 header = pofile.makeheader(**{"Report-Msgid-Bugs-To": r"http://qa.openoffice.org/issues/enter_bug.cgi?subcomponent=ui&comment=&short_desc=Localization%20issue%20in%20file%3A%20dbaccess\source\core\resource.oo&component=l10n&form_name=enter_issue"}) 358 pofile.addunit(header) 359 filecontents = str(pofile) 360 print filecontents 361 # We need to make sure that the \r didn't get misrepresented as a 362 # carriage return, but as a slash (escaped) followed by a normal 'r' 363 assert r'\source\core\resource' in pofile.header().target 364 assert r're\\resource' in filecontents
365
366 - def test_makeobsolete(self):
367 """Tests making a unit obsolete""" 368 posource = '#. The automatic one\n#: test.c\nmsgid "test"\nmsgstr "rest"\n' 369 poexpected = '#~ msgid "test"\n#~ msgstr "rest"\n' 370 pofile = self.poparse(posource) 371 print pofile 372 unit = pofile.units[0] 373 assert not unit.isobsolete() 374 unit.makeobsolete() 375 assert unit.isobsolete() 376 print pofile 377 assert str(unit) == poexpected
378
379 - def test_makeobsolete_plural(self):
380 """Tests making a plural unit obsolete""" 381 posource = r'''msgid "Cow" 382 msgid_plural "Cows" 383 msgstr[0] "Koei" 384 msgstr[1] "Koeie" 385 ''' 386 poexpected = '''#~ msgid "Cow" 387 #~ msgid_plural "Cows" 388 #~ msgstr[0] "Koei" 389 #~ msgstr[1] "Koeie" 390 ''' 391 pofile = self.poparse(posource) 392 print pofile 393 unit = pofile.units[0] 394 assert not unit.isobsolete() 395 unit.makeobsolete() 396 assert unit.isobsolete() 397 print pofile 398 assert str(unit) == poexpected
399 400
402 """Tests making a unit with msgctxt obsolete""" 403 posource = '#: test.c\nmsgctxt "Context"\nmsgid "test"\nmsgstr "rest"\n' 404 poexpected = '#~ msgctxt "Context"\n#~ msgid "test"\n#~ msgstr "rest"\n' 405 pofile = self.poparse(posource) 406 print pofile 407 unit = pofile.units[0] 408 assert not unit.isobsolete() 409 unit.makeobsolete() 410 assert unit.isobsolete() 411 print pofile 412 assert str(unit) == poexpected
413
415 """Tests making a unit with msgidcomments obsolete""" 416 posource = '#: first.c\nmsgid ""\n"_: first.c\\n"\n"test"\nmsgstr "rest"\n\n#: second.c\nmsgid ""\n"_: second.c\\n"\n"test"\nmsgstr "rest"' 417 poexpected = '#~ msgid ""\n#~ "_: first.c\\n"\n#~ "test"\n#~ msgstr "rest"\n' 418 print "Source:\n%s" % posource 419 print "Expected:\n%s" % poexpected 420 pofile = self.poparse(posource) 421 unit = pofile.units[0] 422 assert not unit.isobsolete() 423 unit.makeobsolete() 424 assert unit.isobsolete() 425 print "Result:\n%s" % pofile 426 assert str(unit) == poexpected
427
428 - def test_multiline_obsolete(self):
429 """Tests for correct output of mulitline obsolete messages""" 430 posource = '#~ msgid "Old thing\\n"\n#~ "Second old thing"\n#~ msgstr "Ou ding\\n"\n#~ "Tweede ou ding"\n' 431 pofile = self.poparse(posource) 432 assert pofile.isempty() 433 assert len(pofile.units) == 1 434 unit = pofile.units[0] 435 assert unit.isobsolete() 436 print str(pofile) 437 print posource 438 assert str(pofile) == posource
439
440 - def test_merge_duplicates(self):
441 """checks that merging duplicates works""" 442 posource = '#: source1\nmsgid "test me"\nmsgstr ""\n\n#: source2\nmsgid "test me"\nmsgstr ""\n' 443 pofile = self.poparse(posource) 444 #assert len(pofile.units) == 2 445 pofile.removeduplicates("merge") 446 assert len(pofile.units) == 1 447 assert pofile.units[0].getlocations() == ["source1", "source2"] 448 print pofile
449
450 - def test_merge_mixed_sources(self):
451 """checks that merging works with different source location styles""" 452 posource = ''' 453 #: source1 454 #: source2 455 msgid "test" 456 msgstr "" 457 458 #: source1 source2 459 msgid "test" 460 msgstr "" 461 ''' 462 pofile = self.poparse(posource) 463 print str(pofile) 464 pofile.removeduplicates("merge") 465 print str(pofile) 466 assert len(pofile.units) == 1 467 assert pofile.units[0].getlocations() == ["source1", "source2"]
468
469 - def test_parse_context(self):
470 """Tests that msgctxt is parsed correctly and that it is accessible via the api methods.""" 471 posource = '''# Test comment 472 #: source1 473 msgctxt "noun" 474 msgid "convert" 475 msgstr "bekeerling" 476 477 # Test comment 2 478 #: source2 479 msgctxt "verb" 480 msgid "convert" 481 msgstr "omskakel" 482 ''' 483 pofile = self.poparse(posource) 484 unit = pofile.units[0] 485 486 assert unit.getcontext() == 'noun' 487 assert unit.getnotes() == 'Test comment' 488 489 unit = pofile.units[1] 490 assert unit.getcontext() == 'verb' 491 assert unit.getnotes() == 'Test comment 2'
492
494 """Tests that some weird possible msgctxt scenarios are parsed correctly.""" 495 posource = r'''# Test multiline context 496 #: source1 497 msgctxt "Noun." 498 " A person that changes his or her ways." 499 msgid "convert" 500 msgstr "bekeerling" 501 502 # Test quotes 503 #: source2 504 msgctxt "Verb. Converting from \"something\" to \"something else\"." 505 msgid "convert" 506 msgstr "omskakel" 507 508 # Test quotes, newlines and multiline. 509 #: source3 510 msgctxt "Verb.\nConverting from \"something\"" 511 " to \"something else\"." 512 msgid "convert" 513 msgstr "omskakel" 514 ''' 515 pofile = self.poparse(posource) 516 unit = pofile.units[0] 517 518 assert unit.getcontext() == 'Noun. A person that changes his or her ways.' 519 assert unit.getnotes() == 'Test multiline context' 520 521 unit = pofile.units[1] 522 assert unit.getcontext() == 'Verb. Converting from "something" to "something else".' 523 assert unit.getnotes() == 'Test quotes' 524 525 unit = pofile.units[2] 526 assert unit.getcontext() == 'Verb.\nConverting from "something" to "something else".' 527 assert unit.getnotes() == 'Test quotes, newlines and multiline.'
528
529 - def test_kde_context(self):
530 """Tests that kde-style msgid comments can be retrieved via getcontext().""" 531 posource = '''# Test comment 532 #: source1 533 msgid "" 534 "_: Noun\\n" 535 "convert" 536 msgstr "bekeerling" 537 538 # Test comment 2 539 #: source2 540 msgid "" 541 "_: Verb. _: " 542 "The action of changing.\\n" 543 "convert" 544 msgstr "omskakel" 545 ''' 546 pofile = self.poparse(posource) 547 unit = pofile.units[0] 548 549 assert unit.getcontext() == 'Noun' 550 assert unit.getnotes() == 'Test comment' 551 552 unit = pofile.units[1] 553 assert unit.getcontext() == 'Verb. _: The action of changing.' 554 assert unit.getnotes() == 'Test comment 2'
555
556 - def test_id(self):
557 """checks that ids work correctly""" 558 posource = r''' 559 msgid "" 560 msgstr "" 561 "PO-Revision-Date: 2006-02-09 23:33+0200\n" 562 "MIME-Version: 1.0\n" 563 "Content-Type: text/plain; charset=UTF-8\n" 564 "Content-Transfer-Encoding: 8-bit\n" 565 566 msgid "plant" 567 msgstr "" 568 569 msgid "" 570 "_: Noun\n" 571 "convert" 572 msgstr "bekeerling" 573 574 msgctxt "verb" 575 msgid "" 576 "convert" 577 msgstr "omskakel" 578 579 msgid "tree" 580 msgid_plural "trees" 581 msgstr[0] "" 582 ''' 583 pofile = self.poparse(posource) 584 assert pofile.units[0].getid() == "" 585 assert pofile.units[1].getid() == "plant" 586 assert pofile.units[2].getid() == "_: Noun\nconvert" 587 assert pofile.units[3].getid() == "verb\04convert"
588 # Gettext does not consider the plural to determine duplicates, only 589 # the msgid. For generation of .mo files, we might want to use this 590 # code to generate the entry for the hash table, but for now, it is 591 # commented out for conformance to gettext. 592 # assert pofile.units[4].getid() == "tree\0trees" 593