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

Source Code for Module translate.storage.ts

  1  #!/usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3  # 
  4  # Copyright 2004-2007 Zuza Software Foundation 
  5  # 
  6  # This file is part of translate. 
  7  # 
  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 
 10  # the Free Software Foundation; either version 2 of the License, or 
 11  # (at your option) any later version. 
 12  # 
 13  # translate is distributed in the hope that it will be useful, 
 14  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 15  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 16  # GNU General Public License for more details. 
 17  # 
 18  # You should have received a copy of the GNU General Public License 
 19  # along with translate; if not, write to the Free Software 
 20  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 21  # 
 22   
 23  """Module for parsing Qt .ts files for translation. 
 24   
 25  Currently this module supports the old format of .ts files. Some applictaions 
 26  use the newer .ts format which are documented here: 
 27  U{TS file format 4.3<http://doc.trolltech.com/4.3/linguist-ts-file-format.html>}, 
 28  U{Example<http://svn.ez.no/svn/ezcomponents/trunk/Translation/docs/linguist-format.txt>} 
 29   
 30  U{Specification of the valid variable entries <http://doc.trolltech.com/4.3/qstring.html#arg>}, 
 31  U{2 <http://doc.trolltech.com/4.3/qstring.html#arg-2>} 
 32  """ 
 33   
 34  from translate.misc import ourdom 
 35   
 36   
37 -class QtTsParser:
38 contextancestors = dict.fromkeys(["TS"]) 39 messageancestors = dict.fromkeys(["TS", "context"]) 40
41 - def __init__(self, inputfile=None):
42 """make a new QtTsParser, reading from the given inputfile if required""" 43 self.filename = getattr(inputfile, "filename", None) 44 self.knowncontextnodes = {} 45 self.indexcontextnodes = {} 46 if inputfile is None: 47 self.document = ourdom.parseString("<!DOCTYPE TS><TS></TS>") 48 else: 49 self.document = ourdom.parse(inputfile) 50 assert self.document.documentElement.tagName == "TS"
51
52 - def addtranslation(self, contextname, source, translation, comment=None, transtype=None, createifmissing=False):
53 """adds the given translation (will create the nodes required if asked). Returns success""" 54 contextnode = self.getcontextnode(contextname) 55 if contextnode is None: 56 if not createifmissing: 57 return False 58 # construct a context node with the given name 59 contextnode = self.document.createElement("context") 60 namenode = self.document.createElement("name") 61 nametext = self.document.createTextNode(contextname) 62 namenode.appendChild(nametext) 63 contextnode.appendChild(namenode) 64 self.document.documentElement.appendChild(contextnode) 65 if not createifmissing: 66 return False 67 messagenode = self.document.createElement("message") 68 sourcenode = self.document.createElement("source") 69 sourcetext = self.document.createTextNode(source) 70 sourcenode.appendChild(sourcetext) 71 messagenode.appendChild(sourcenode) 72 if comment: 73 commentnode = self.document.createElement("comment") 74 commenttext = self.document.createTextNode(comment) 75 commentnode.appendChild(commenttext) 76 messagenode.appendChild(commentnode) 77 translationnode = self.document.createElement("translation") 78 translationtext = self.document.createTextNode(translation) 79 translationnode.appendChild(translationtext) 80 if transtype: 81 translationnode.setAttribute("type", transtype) 82 messagenode.appendChild(translationnode) 83 contextnode.appendChild(messagenode) 84 return True
85
86 - def getxml(self):
87 """return the ts file as xml""" 88 xml = self.document.toprettyxml(indent=" ", encoding="utf-8") 89 #This line causes empty lines in the translation text to be removed (when there are two newlines) 90 xml = "\n".join([line for line in xml.split("\n") if line.strip()]) 91 return xml
92
93 - def getcontextname(self, contextnode):
94 """returns the name of the given context""" 95 namenode = ourdom.getFirstElementByTagName(contextnode, "name") 96 return ourdom.getnodetext(namenode)
97
98 - def getcontextnode(self, contextname):
99 """finds the contextnode with the given name""" 100 contextnode = self.knowncontextnodes.get(contextname, None) 101 if contextnode is not None: 102 return contextnode 103 contextnodes = self.document.searchElementsByTagName("context", self.contextancestors) 104 for contextnode in contextnodes: 105 if self.getcontextname(contextnode) == contextname: 106 self.knowncontextnodes[contextname] = contextnode 107 return contextnode 108 return None
109
110 - def getmessagenodes(self, context=None):
111 """returns all the messagenodes, limiting to the given context (name or node) if given""" 112 if context is None: 113 return self.document.searchElementsByTagName("message", self.messageancestors) 114 else: 115 if isinstance(context, (str, unicode)): 116 # look up the context node by name 117 context = self.getcontextnode(context) 118 if context is None: 119 return [] 120 return context.searchElementsByTagName("message", self.messageancestors)
121
122 - def getmessagesource(self, message):
123 """returns the message source for a given node""" 124 sourcenode = ourdom.getFirstElementByTagName(message, "source") 125 return ourdom.getnodetext(sourcenode)
126
127 - def getmessagetranslation(self, message):
128 """returns the message translation for a given node""" 129 translationnode = ourdom.getFirstElementByTagName(message, "translation") 130 return ourdom.getnodetext(translationnode)
131
132 - def getmessagetype(self, message):
133 """returns the message translation attributes for a given node""" 134 translationnode = ourdom.getFirstElementByTagName(message, "translation") 135 return translationnode.getAttribute("type")
136
137 - def getmessagecomment(self, message):
138 """returns the message comment for a given node""" 139 commentnode = ourdom.getFirstElementByTagName(message, "comment") 140 # NOTE: handles only one comment per msgid (OK) 141 # and only one-line comments (can be VERY wrong) TODO!!! 142 return ourdom.getnodetext(commentnode)
143
144 - def iteritems(self):
145 """iterates through (contextname, messages)""" 146 for contextnode in self.document.searchElementsByTagName("context", self.contextancestors): 147 yield self.getcontextname(contextnode), self.getmessagenodes(contextnode)
148
149 - def __del__(self):
150 """clean up the document if required""" 151 if hasattr(self, "document"): 152 self.document.unlink()
153