1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15   
 16   
 17   
 18   
 19   
 20   
 21   
 22   
 23  """An xliff file specifically suited for handling the po representation of  
 24  xliff. """ 
 25   
 26  from translate.storage import xliff 
 27  from translate.storage import lisa  
 28  from translate.storage import poheader 
 29  from translate.misc.multistring import multistring 
 30  from lxml import etree 
 31  import re 
 32   
 34      if not isinstance(thing, multistring): 
 35          return False 
 36      return len(thing.strings) > 1 
  37   
 39      """A class to specifically handle the plural units created from a po file.""" 
 40 -    def __init__(self, source, empty=False): 
  53   
 72   
 73 -    def setsource(self, source, sourcelang="en"): 
  91   
 96      source = property(getsource, setsource) 
 97       
 98 -    def settarget(self, text, lang='xx', append=False): 
 122   
132   
133      target = property(gettarget, settarget) 
134   
135 -    def addnote(self, text, origin=None): 
 136          """Add a note specifically in a "note" tag""" 
137          if isinstance(text, str): 
138              text = text.decode("utf-8") 
139          note = etree.SubElement(self.xmlelement, self.namespaced("note")) 
140          note.text = text 
141          if origin: 
142              note.set("from", origin) 
143          for unit in self.units[1:]: 
144              unit.addnote(text, origin) 
 145   
147           
148          if origin == "translator": 
149              notes = super(PoXliffUnit, self).getnotes("translator") 
150              trancomments = self.gettranslatorcomments() 
151              if notes == trancomments or trancomments.find(notes) >= 0: 
152                  notes = "" 
153              elif notes.find(trancomments) >= 0: 
154                  trancomments = notes 
155                  notes = "" 
156              trancomments = trancomments + notes 
157              return trancomments 
158          elif origin in ["programmer", "developer", "source code"]: 
159              devcomments = super(PoXliffUnit, self).getnotes("developer") 
160              autocomments = self.getautomaticcomments() 
161              if devcomments == autocomments or autocomments.find(devcomments) >= 0: 
162                  devcomments = "" 
163              elif devcomments.find(autocomments) >= 0: 
164                  autocomments = devcomments 
165                  devcomments = "" 
166              return autocomments 
167          else: 
168              return super(PoXliffUnit, self).getnotes(origin) 
 169   
174   
179   
181          self.xmlelement.set("id", id) 
182          if len(self.units) > 1: 
183              for i in range(len(self.units)): 
184                  self.units[i].setid("%s[%d]" % (id, i)) 
 185   
187          """Returns all the references (source locations)""" 
188          groups = self.getcontextgroups("po-reference") 
189          references = [] 
190          for group in groups: 
191              sourcefile = "" 
192              linenumber = "" 
193              for (type,text) in group: 
194                  if type == "sourcefile": 
195                      sourcefile = text 
196                  elif type == "linenumber": 
197                      linenumber = text 
198              assert sourcefile 
199              if linenumber: 
200                  sourcefile = sourcefile + ":" + linenumber 
201              references.append(sourcefile) 
202          return references 
 203   
209          groups = self.getcontextgroups("po-entry") 
210          comments = [] 
211          for group in groups: 
212              commentpairs = filter(hasautocomment, group) 
213              for (type,text) in commentpairs: 
214                  comments.append(text) 
215          return "\n".join(comments) 
 216       
218          """Returns the translator comments (x-po-trancomment), which corresponds 
219          to the # style po comments.""" 
220          def hastrancomment((type, text)): 
221              return type == "x-po-trancomment" 
222          groups = self.getcontextgroups("po-entry") 
223          comments = [] 
224          for group in groups: 
225              commentpairs = filter(hastrancomment, group) 
226              for (type,text) in commentpairs: 
227                  comments.append(text) 
228          return "\n".join(comments) 
229   
231          return "gettext-domain-header" in (self.getrestype() or "") 
 232   
249      createfromxmlElement = classmethod(createfromxmlElement) 
250   
252          return self.xmlelement.tag == self.namespaced("group") 
 253   
254   
256      """a file for the po variant of Xliff files""" 
257      UnitClass = PoXliffUnit 
259          if not "sourcelanguage" in kwargs: 
260              kwargs["sourcelanguage"] = "en-US" 
261          xliff.xlifffile.__init__(self, *args, **kwargs) 
 262   
263 -    def createfilenode(self, filename, sourcelanguage="en-US", datatype="po"): 
 267   
275   
276 -    def addplural(self, source, target, filename, createifmissing=False): 
 277          """This method should now be unnecessary, but is left for reference""" 
278          assert isinstance(source, multistring) 
279          if not isinstance(target, multistring): 
280              target = multistring(target) 
281          sourcel = len(source.strings) 
282          targetl = len(target.strings) 
283          if sourcel < targetl: 
284              sources = source.strings + [source.strings[-1]] * targetl - sourcel 
285              targets = target.strings 
286          else: 
287              sources = source.strings 
288              targets = target.strings 
289          self._messagenum += 1 
290          pluralnum = 0 
291          group = self.creategroup(filename, True, restype="x-gettext-plural") 
292          for (src, tgt) in zip(sources, targets): 
293              unit = self.UnitClass(src) 
294              unit.target = tgt 
295              unit.setid("%d[%d]" % (self._messagenum, pluralnum)) 
296              pluralnum += 1 
297              group.append(unit.xmlelement) 
298              self.units.append(unit) 
299   
300          if pluralnum < sourcel: 
301              for string in sources[pluralnum:]: 
302                  unit = self.UnitClass(src) 
303                  unit.xmlelement.set("translate", "no") 
304                  unit.setid("%d[%d]" % (self._messagenum, pluralnum)) 
305                  pluralnum += 1 
306                  group.append(unit.xmlelement) 
307                  self.units.append(unit) 
308           
309          return self.units[-pluralnum] 
 310   
312          """Populates this object from the given xml string""" 
313           
314          def ispluralgroup(node): 
315              """determines whether the xml node refers to a getttext plural""" 
316              return node.get("restype") == "x-gettext-plurals" 
 317           
318          def isnonpluralunit(node): 
319              """determindes whether the xml node contains a plural like id. 
320               
321              We want to filter out all the plural nodes, except the very first 
322              one in each group. 
323              """ 
324              return re.match(r"\d+\[[123456]\]$", node.get("id") or "") is None 
 325   
326          def pluralunits(pluralgroups): 
327              for pluralgroup in pluralgroups: 
328                  yield self.UnitClass.createfromxmlElement(pluralgroup, namespace=self.namespace) 
329           
330          self.filename = getattr(xml, 'name', '') 
331          if hasattr(xml, "read"): 
332              xml.seek(0) 
333              xmlsrc = xml.read() 
334              xml = xmlsrc 
335          self.document = etree.fromstring(xml).getroottree() 
336          self.initbody() 
337          assert self.document.getroot().tag == self.namespaced(self.rootNode) 
338          groups = self.document.findall(".//%s" % self.namespaced("group")) 
339          pluralgroups = filter(ispluralgroup, groups) 
340          termEntries = self.body.findall('.//%s' % self.namespaced(self.UnitClass.rootNode)) 
341          if termEntries is None: 
342              return 
343   
344          singularunits = filter(isnonpluralunit, termEntries) 
345          pluralunit_iter = pluralunits(pluralgroups) 
346          try: 
347              nextplural = pluralunit_iter.next() 
348          except StopIteration: 
349              nextplural = None 
350   
351          for entry in singularunits: 
352              term = self.UnitClass.createfromxmlElement(entry, namespace=self.namespace) 
353              if nextplural and unicode(term.source) in nextplural.source.strings: 
354                  self.units.append(nextplural) 
355                  try: 
356                      nextplural = pluralunit_iter.next() 
357                  except StopIteration, i: 
358                      nextplural = None 
359              else: 
360                  self.units.append(term) 
361