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

Source Code for Module translate.storage.pocommon

  1  #!/usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3  # 
  4  # Copyright 2002-2011 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  import re 
 23  import urllib 
 24   
 25  from translate.storage import base 
 26  from translate.storage import poheader 
 27  from translate.storage.workflow import StateEnum as state 
 28   
 29  msgid_comment_re = re.compile("_: (.*?)\n") 
 30   
 31   
32 -def extract_msgid_comment(text):
33 """The one definitive way to extract a msgid comment out of an unescaped 34 unicode string that might contain it. 35 36 @rtype: unicode""" 37 msgidcomment = msgid_comment_re.match(text) 38 if msgidcomment: 39 return msgidcomment.group(1) 40 return u""
41 42
43 -def quote_plus(text):
44 """Quote the query fragment of a URL; replacing ' ' with '+'""" 45 return urllib.quote_plus(text.encode("utf-8"))
46 47
48 -def unquote_plus(text):
49 """unquote('%7e/abc+def') -> '~/abc def'""" 50 return urllib.unquote_plus(text).decode('utf-8')
51 52
53 -class pounit(base.TranslationUnit):
54 S_FUZZY_OBSOLETE = state.OBSOLETE-1 55 S_OBSOLETE = state.OBSOLETE 56 S_UNTRANSLATED = state.EMPTY 57 S_FUZZY = state.NEEDS_WORK 58 S_TRANSLATED = state.UNREVIEWED 59 60 STATE = { 61 S_FUZZY_OBSOLETE: (S_FUZZY_OBSOLETE, state.OBSOLETE), 62 S_OBSOLETE: (state.OBSOLETE, state.EMPTY), 63 S_UNTRANSLATED: (state.EMPTY, state.NEEDS_WORK), 64 S_FUZZY: (state.NEEDS_WORK, state.UNREVIEWED), 65 S_TRANSLATED: (state.UNREVIEWED, state.MAX), 66 } 67
68 - def adderror(self, errorname, errortext):
69 """Adds an error message to this unit.""" 70 text = u'(pofilter) %s: %s' % (errorname, errortext) 71 # Don't add the same error twice: 72 if text not in self.getnotes(origin='translator'): 73 self.addnote(text, origin="translator")
74
75 - def geterrors(self):
76 """Get all error messages.""" 77 notes = self.getnotes(origin="translator").split('\n') 78 errordict = {} 79 for note in notes: 80 if '(pofilter) ' in note: 81 error = note.replace('(pofilter) ', '') 82 errorname, errortext = error.split(': ', 1) 83 errordict[errorname] = errortext 84 return errordict
85
86 - def markreviewneeded(self, needsreview=True, explanation=None):
87 """Marks the unit to indicate whether it needs review. Adds an optional explanation as a note.""" 88 if needsreview: 89 reviewnote = "(review)" 90 if explanation: 91 reviewnote += " " + explanation 92 self.addnote(reviewnote, origin="translator") 93 else: 94 # Strip (review) notes. 95 notestring = self.getnotes(origin="translator") 96 notes = notestring.split('\n') 97 newnotes = [] 98 for note in notes: 99 if not '(review)' in note: 100 newnotes.append(note) 101 newnotes = '\n'.join(newnotes) 102 self.removenotes() 103 self.addnote(newnotes, origin="translator")
104
105 - def istranslated(self):
106 return super(pounit, self).istranslated() and not self.isobsolete() and not self.isheader()
107
108 - def istranslatable(self):
109 return not (self.isheader() or self.isblank() or self.isobsolete())
110
111 - def hasmarkedcomment(self, commentmarker):
112 raise NotImplementedError
113
114 - def isreview(self):
115 return self.hasmarkedcomment("review") or self.hasmarkedcomment("pofilter")
116
117 - def isobsolete(self):
118 return self.STATE[self.S_FUZZY_OBSOLETE][0] <= self.get_state_n() < self.STATE[self.S_OBSOLETE][1]
119
120 - def isfuzzy(self):
121 # implementation specific fuzzy detection, must not use get_state_n() 122 raise NotImplementedError()
123
124 - def markfuzzy(self, present=True):
125 if present: 126 self.set_state_n(self.STATE[self.S_FUZZY][0]) 127 else: 128 self.set_state_n(self.STATE[self.S_TRANSLATED][0])
129 # set_state_n will check if target exists 130
131 - def makeobsolete(self):
132 if self.isfuzzy(): 133 self.set_state_n(self.STATE[self.S_FUZZY_OBSOLETE][0]) 134 else: 135 self.set_state_n(self.STATE[self.S_OBSOLETE][0])
136
137 - def resurrect(self):
138 self.set_state_n(self.STATE[self.S_TRANSLATED][0]) 139 if not self.gettarget(): 140 self.set_state_n(self.STATE[self.S_UNTRANSLATED][0])
141
142 - def _domarkfuzzy(self, present=True):
143 raise NotImplementedError()
144
145 - def get_state_n(self):
146 value = super(pounit, self).get_state_n() 147 if value <= self.S_OBSOLETE: 148 return value 149 if self.target: 150 if self.isfuzzy(): 151 return self.S_FUZZY 152 else: 153 return self.S_TRANSLATED 154 else: 155 return self.S_UNTRANSLATED
156
157 - def set_state_n(self, value):
158 super(pounit, self).set_state_n(value) 159 has_target = False 160 if self.hasplural(): 161 for string in self.target.strings: 162 if string: 163 has_target = True 164 break 165 else: 166 has_target = bool(self.target) 167 if has_target: 168 isfuzzy = self.STATE[self.S_FUZZY][0] <= value < self.STATE[self.S_FUZZY][1] or \ 169 self.STATE[self.S_FUZZY_OBSOLETE][0] <= value < self.STATE[self.S_FUZZY_OBSOLETE][1] 170 self._domarkfuzzy(isfuzzy) # Implementation specific fuzzy-marking 171 else: 172 super(pounit, self).set_state_n(self.S_UNTRANSLATED) 173 self._domarkfuzzy(False)
174 175
176 -def encodingToUse(encoding):
177 """Tests whether the given encoding is known in the python runtime, or returns utf-8. 178 This function is used to ensure that a valid encoding is always used.""" 179 if encoding == "CHARSET" or encoding == None: 180 return 'utf-8' 181 return encoding
182 # if encoding is None: return False 183 # return True 184 # try: 185 # tuple = codecs.lookup(encoding) 186 # except LookupError: 187 # return False 188 # return True 189 190
191 -class pofile(poheader.poheader, base.TranslationStore):
192 Name = _("Gettext PO file") # pylint: disable-msg=E0602 193 Mimetypes = ["text/x-gettext-catalog", "text/x-gettext-translation", "text/x-po", "text/x-pot"] 194 Extensions = ["po", "pot"] 195 # We don't want windows line endings on Windows: 196 _binary = True 197
198 - def __init__(self, inputfile=None, encoding=None):
199 super(pofile, self).__init__(unitclass=self.UnitClass) 200 self.units = [] 201 self.filename = '' 202 self._encoding = encodingToUse(encoding) 203 if inputfile is not None: 204 self.parse(inputfile) 205 else: 206 self.init_headers()
207