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