Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(41)

Delta Between Two Patch Sets: translate/storage/cpo.py

Issue 65: xliff2po & po2xliff should handle context SVN Base: https://translate.svn.sourceforge.net/svnroot/translate/src/trunk/
Left Patch Set: Added "id's" to context-group names Created 1 year, 4 months ago
Right Patch Set: Created 1 year, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: View regular side by side diff
Right: View regular side by side diff
LEFTRIGHT
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*- 2 # -*- coding: utf-8 -*-
3 # 3 #
4 # Copyright 2002-2007 Zuza Software Foundation 4 # Copyright 2002-2007 Zuza Software Foundation
5 # 5 #
6 # This file is part of translate. 6 # This file is part of translate.
7 # 7 #
8 # translate is free software; you can redistribute it and/or modify 8 # translate is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by 9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or 10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version. 11 # (at your option) any later version.
12 # 12 #
13 # translate is distributed in the hope that it will be useful, 13 # translate is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details. 16 # GNU General Public License for more details.
17 # 17 #
18 # You should have received a copy of the GNU General Public License 18 # You should have received a copy of the GNU General Public License
19 # along with translate; if not, write to the Free Software 19 # along with translate; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 21
22 """Classes that hold units of .po files (pounit) or entire files (pofile). 22 """Classes that hold units of .po files (pounit) or entire files (pofile).
23 23
24 Gettext-style .po (or .pot) files are used in translations for KDE, GNOME and 24 Gettext-style .po (or .pot) files are used in translations for KDE, GNOME and
25 many other projects. 25 many other projects.
26 26
27 This uses libgettextpo from the gettext package. Any version before 0.17 will 27 This uses libgettextpo from the gettext package. Any version before 0.17 will
28 at least cause some subtle bugs or may not work at all. Developers might want 28 at least cause some subtle bugs or may not work at all. Developers might want
29 to have a look at gettext-tools/libgettextpo/gettext-po.h from the gettext 29 to have a look at gettext-tools/libgettextpo/gettext-po.h from the gettext
30 package for the public API of the library. 30 package for the public API of the library.
31 """ 31 """
32 32
33 from translate.misc.multistring import multistring 33 from translate.misc.multistring import multistring
34 from translate.storage import pocommon 34 from translate.storage import pocommon
35 from translate.misc import quote 35 from translate.misc import quote
36 from translate.lang import data 36 from translate.lang import data
37 from ctypes import * 37 from ctypes import *
38 import ctypes.util 38 import ctypes.util
39 try: 39 try:
40 import cStringIO as StringIO 40 import cStringIO as StringIO
41 except ImportError: 41 except ImportError:
42 import StringIO 42 import StringIO
43 import os 43 import os
44 import pypo 44 import pypo
45 import re 45 import re
46 import sys 46 import sys
47 import tempfile 47 import tempfile
48 48
49 lsep = " " 49 lsep = " "
50 """Seperator for #: entries""" 50 """Seperator for #: entries"""
(...skipping 416 matching lines...) Show 10 above Show 10 below
467 """ 467 """
468 468
469 if not text: 469 if not text:
470 text = gpo.po_message_msgid(self._gpo_message) 470 text = gpo.po_message_msgid(self._gpo_message)
471 if text: 471 if text:
472 msgidcomment = re.search("_: (.*)\n", text) 472 msgidcomment = re.search("_: (.*)\n", text)
473 if msgidcomment: 473 if msgidcomment:
474 return msgidcomment.group(1).decode(self._encoding) 474 return msgidcomment.group(1).decode(self._encoding)
475 return u"" 475 return u""
476 476
477 def __str__(self): 477 def __str__(self):
478 pf = pofile() 478 pf = pofile()
479 pf.addunit(self) 479 pf.addunit(self)
480 return str(pf) 480 return str(pf)
481 481
482 def getlocations(self): 482 def getlocations(self):
483 locations = [] 483 locations = []
484 i = 0 484 i = 0
485 location = gpo.po_message_filepos(self._gpo_message, i) 485 location = gpo.po_message_filepos(self._gpo_message, i)
486 while location: 486 while location:
487 locname = gpo.po_filepos_file(location) 487 locname = gpo.po_filepos_file(location)
488 locline = gpo.po_filepos_start_line(location) 488 locline = gpo.po_filepos_start_line(location)
489 if locline == -1: 489 if locline == -1:
490 locstring = locname 490 locstring = locname
491 else: 491 else:
492 locstring = locname + ":" + str(locline) 492 locstring = locname + ":" + str(locline)
493 locations.append(locstring) 493 locations.append(locstring)
494 i += 1 494 i += 1
495 location = gpo.po_message_filepos(self._gpo_message, i) 495 location = gpo.po_message_filepos(self._gpo_message, i)
496 return locations 496 return locations
497 497
498 def addlocation(self, location): 498 def addlocation(self, location):
499 for loc in location.split(): 499 for loc in location.split():
500 parts = loc.split(":") 500 parts = loc.split(":")
501 file = parts[0] 501 file = parts[0]
502 if len(parts) == 2: 502 if len(parts) == 2:
503 line = int(parts[1]) 503 line = int(parts[1])
504 else: 504 else:
505 line = -1 505 line = -1
506 gpo.po_message_add_filepos(self._gpo_message, file, line) 506 gpo.po_message_add_filepos(self._gpo_message, file, line)
507 507
508 def getcontext(self): 508 def getcontext(self):
509 msgctxt = gpo.po_message_msgctxt(self._gpo_message) 509 msgctxt = gpo.po_message_msgctxt(self._gpo_message)
510 msgidcomment = self._extract_msgidcomments() 510 msgidcomment = self._extract_msgidcomments()
511 if msgctxt: 511 if msgctxt:
512 return msgctxt + msgidcomment 512 return msgctxt + msgidcomment
513 else: 513 else:
514 return msgidcomment 514 return msgidcomment
515 515
516 def setcontext(self, context): 516 def setcontext(self, context):
517 """Sets the current context for this unit""" 517 """Sets the current context for this unit"""
georgeyk 2008/07/24 05:14:28 Should I care about the getcontext() ? The getcont
518 # TODO: find out what behavior this should really have 518 # TODO: inspect what behavior this should really have
519 gpo.po_message_set_msgctxt(self._gpo_message, context) 519 gpo.po_message_set_msgctxt(self._gpo_message, context)
520 520
521 class pofile(pocommon.pofile): 521 class pofile(pocommon.pofile):
522 UnitClass = pounit 522 UnitClass = pounit
523 def __init__(self, inputfile=None, encoding=None, unitclass=pounit): 523 def __init__(self, inputfile=None, encoding=None, unitclass=pounit):
524 self.UnitClass = unitclass 524 self.UnitClass = unitclass
525 pocommon.pofile.__init__(self, unitclass=unitclass) 525 pocommon.pofile.__init__(self, unitclass=unitclass)
526 self._gpo_memory_file = None 526 self._gpo_memory_file = None
527 self._gpo_message_iterator = None 527 self._gpo_message_iterator = None
528 self._encoding = encodingToUse(encoding) 528 self._encoding = encodingToUse(encoding)
529 if inputfile is not None: 529 if inputfile is not None:
530 self.parse(inputfile) 530 self.parse(inputfile)
531 else: 531 else:
532 self._gpo_memory_file = gpo.po_file_create() 532 self._gpo_memory_file = gpo.po_file_create()
533 self._gpo_message_iterator = gpo.po_message_iterator(self._gpo_memor y_file, None) 533 self._gpo_message_iterator = gpo.po_message_iterator(self._gpo_memor y_file, None)
534 534
535 def addunit(self, unit): 535 def addunit(self, unit):
536 gpo.po_message_insert(self._gpo_message_iterator, unit._gpo_message) 536 gpo.po_message_insert(self._gpo_message_iterator, unit._gpo_message)
537 self.units.append(unit) 537 self.units.append(unit)
538 538
539 def removeduplicates(self, duplicatestyle="merge"): 539 def removeduplicates(self, duplicatestyle="merge"):
540 """make sure each msgid is unique ; merge comments etc from duplicates i nto original""" 540 """make sure each msgid is unique ; merge comments etc from duplicates i nto original"""
541 msgiddict = {} 541 msgiddict = {}
542 uniqueunits = [] 542 uniqueunits = []
543 # we sometimes need to keep track of what has been marked 543 # we sometimes need to keep track of what has been marked
544 # TODO: this is using a list as the pos aren't hashable, but this is slo w... 544 # TODO: this is using a list as the pos aren't hashable, but this is slo w...
545 markedpos = [] 545 markedpos = []
546 def addcomment(thepo): 546 def addcomment(thepo):
547 thepo.msgidcomment = " ".join(thepo.getlocations()) 547 thepo.msgidcomment = " ".join(thepo.getlocations())
548 markedpos.append(thepo) 548 markedpos.append(thepo)
549 for thepo in self.units: 549 for thepo in self.units:
550 if thepo.isheader(): 550 if thepo.isheader():
551 uniqueunits.append(thepo) 551 uniqueunits.append(thepo)
552 continue 552 continue
553 if duplicatestyle.startswith("msgid_comment"): 553 if duplicatestyle.startswith("msgid_comment"):
554 msgid = thepo._extract_msgidcomments() + thepo.source 554 msgid = thepo._extract_msgidcomments() + thepo.source
555 else: 555 else:
556 msgid = thepo.source 556 msgid = thepo.source
557 if duplicatestyle == "msgid_comment_all": 557 if duplicatestyle == "msgid_comment_all":
558 addcomment(thepo) 558 addcomment(thepo)
559 uniqueunits.append(thepo) 559 uniqueunits.append(thepo)
560 elif msgid in msgiddict: 560 elif msgid in msgiddict:
561 if duplicatestyle == "merge": 561 if duplicatestyle == "merge":
562 if msgid: 562 if msgid:
563 msgiddict[msgid].merge(thepo) 563 msgiddict[msgid].merge(thepo)
564 else: 564 else:
565 addcomment(thepo) 565 addcomment(thepo)
566 uniqueunits.append(thepo) 566 uniqueunits.append(thepo)
567 elif duplicatestyle == "keep": 567 elif duplicatestyle == "keep":
568 uniqueunits.append(thepo) 568 uniqueunits.append(thepo)
(...skipping 71 matching lines...) Show 10 above Show 10 below
640 posrc = input.read() 640 posrc = input.read()
641 input.close() 641 input.close()
642 input = posrc 642 input = posrc
643 643
644 needtmpfile = not os.path.isfile(input) 644 needtmpfile = not os.path.isfile(input)
645 if needtmpfile: 645 if needtmpfile:
646 # This is not a file - we write the string to a temporary file 646 # This is not a file - we write the string to a temporary file
647 fd, fname = tempfile.mkstemp(prefix='translate', suffix='.po') 647 fd, fname = tempfile.mkstemp(prefix='translate', suffix='.po')
648 os.write(fd, input) 648 os.write(fd, input)
649 input = fname 649 input = fname
650 os.close(fd) 650 os.close(fd)
651 651
652 self._gpo_memory_file = gpo.po_file_read_v3(input, xerror_handler) 652 self._gpo_memory_file = gpo.po_file_read_v3(input, xerror_handler)
653 if self._gpo_memory_file is None: 653 if self._gpo_memory_file is None:
654 print >> sys.stderr, "Error:" 654 print >> sys.stderr, "Error:"
655 655
656 if needtmpfile: 656 if needtmpfile:
657 os.remove(input) 657 os.remove(input)
658 658
659 # Handle xerrors here 659 # Handle xerrors here
660 self._header = gpo.po_file_domain_header(self._gpo_memory_file, None) 660 self._header = gpo.po_file_domain_header(self._gpo_memory_file, None)
661 if self._header: 661 if self._header:
662 charset = gpo.po_header_field(self._header, "Content-Type") 662 charset = gpo.po_header_field(self._header, "Content-Type")
663 if charset: 663 if charset:
664 charset = re.search("charset=([^\\s]+)", charset).group(1) 664 charset = re.search("charset=([^\\s]+)", charset).group(1)
665 self._encoding = encodingToUse(charset) 665 self._encoding = encodingToUse(charset)
666 self._gpo_message_iterator = gpo.po_message_iterator(self._gpo_memory_fi le, None) 666 self._gpo_message_iterator = gpo.po_message_iterator(self._gpo_memory_fi le, None)
667 newmessage = gpo.po_next_message(self._gpo_message_iterator) 667 newmessage = gpo.po_next_message(self._gpo_message_iterator)
668 while newmessage: 668 while newmessage:
669 newunit = pounit(gpo_message=newmessage) 669 newunit = pounit(gpo_message=newmessage)
670 self.units.append(newunit) 670 self.units.append(newunit)
671 newmessage = gpo.po_next_message(self._gpo_message_iterator) 671 newmessage = gpo.po_next_message(self._gpo_message_iterator)
672 self._free_iterator() 672 self._free_iterator()
673 673
674 def __del__(self): 674 def __del__(self):
675 # We currently disable this while we still get segmentation faults. 675 # We currently disable this while we still get segmentation faults.
676 # Note that this is definitely leaking memory because of this. 676 # Note that this is definitely leaking memory because of this.
677 return 677 return
678 self._free_iterator() 678 self._free_iterator()
679 if self._gpo_memory_file is not None: 679 if self._gpo_memory_file is not None:
680 gpo.po_file_free(self._gpo_memory_file) 680 gpo.po_file_free(self._gpo_memory_file)
681 self._gpo_memory_file = None 681 self._gpo_memory_file = None
682 682
683 def _free_iterator(self): 683 def _free_iterator(self):
684 # We currently disable this while we still get segmentation faults. 684 # We currently disable this while we still get segmentation faults.
685 # Note that this is definitely leaking memory because of this. 685 # Note that this is definitely leaking memory because of this.
686 return 686 return
687 if self._gpo_message_iterator is not None: 687 if self._gpo_message_iterator is not None:
688 gpo.po_message_iterator_free(self._gpo_message_iterator) 688 gpo.po_message_iterator_free(self._gpo_message_iterator)
689 self._gpo_message_iterator = None 689 self._gpo_message_iterator = None
LEFTRIGHT

Powered by Google App Engine
This is Rietveld r159