Package translate :: Package convert :: Module pot2po
[hide private]
[frames] | no frames]

Source Code for Module translate.convert.pot2po

  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  """convert Gettext PO templates (.pot) to PO localization files, preserving existing translations 
 23   
 24  See: http://translate.sourceforge.net/wiki/toolkit/pot2po for examples and  
 25  usage instructions 
 26  """ 
 27   
 28  from translate.storage import po 
 29  from translate.storage import factory 
 30  from translate.search import match 
 31  from translate.misc.multistring import multistring 
 32   
 33  # We don't want to reinitialise the TM each time, so let's store it here. 
 34  tmmatcher = None 
 35   
36 -def memory(tmfiles, max_candidates=1, min_similarity=75, max_length=1000):
37 """Returns the TM store to use. Only initialises on first call.""" 38 global tmmatcher 39 # Only initialise first time 40 if tmmatcher is None: 41 if isinstance(tmfiles, list): 42 tmstore = [factory.getobject(tmfile) for tmfile in tmfiles] 43 else: 44 tmstore = factory.getobject(tmfiles) 45 tmmatcher = match.matcher(tmstore, max_candidates=max_candidates, min_similarity=min_similarity, max_length=max_length) 46 return tmmatcher
47
48 -def convertpot(inputpotfile, outputpofile, templatepofile, tm=None, min_similarity=75, fuzzymatching=True, **kwargs):
49 """reads in inputpotfile, adjusts header, writes to outputpofile. if templatepofile exists, merge translations from it into outputpofile""" 50 inputpot = po.pofile(inputpotfile) 51 inputpot.makeindex() 52 thetargetfile = po.pofile() 53 # header values 54 charset = "UTF-8" 55 encoding = "8bit" 56 project_id_version = None 57 pot_creation_date = None 58 po_revision_date = None 59 last_translator = None 60 language_team = None 61 mime_version = None 62 plural_forms = None 63 kwargs = {} 64 if templatepofile is not None: 65 templatepo = po.pofile(templatepofile) 66 fuzzyfilematcher = None 67 if fuzzymatching: 68 for unit in templatepo.units: 69 if unit.isobsolete(): 70 unit.resurrect() 71 try: 72 fuzzyfilematcher = match.matcher(templatepo, max_candidates=1, min_similarity=min_similarity, max_length=1000, usefuzzy=True) 73 fuzzyfilematcher.addpercentage = False 74 except ValueError: 75 # Probably no usable units 76 pass 77 78 templatepo.makeindex() 79 templateheadervalues = templatepo.parseheader() 80 for key, value in templateheadervalues.iteritems(): 81 if key == "Project-Id-Version": 82 project_id_version = value 83 elif key == "Last-Translator": 84 last_translator = value 85 elif key == "Language-Team": 86 language_team = value 87 elif key == "PO-Revision-Date": 88 po_revision_date = value 89 elif key in ("POT-Creation-Date", "MIME-Version"): 90 # don't know how to handle these keys, or ignoring them 91 pass 92 elif key == "Content-Type": 93 kwargs[key] = value 94 elif key == "Content-Transfer-Encoding": 95 encoding = value 96 elif key == "Plural-Forms": 97 plural_forms = value 98 else: 99 kwargs[key] = value 100 fuzzyglobalmatcher = None 101 if fuzzymatching and tm: 102 fuzzyglobalmatcher = memory(tm, max_candidates=1, min_similarity=min_similarity, max_length=1000) 103 fuzzyglobalmatcher.addpercentage = False 104 inputheadervalues = inputpot.parseheader() 105 for key, value in inputheadervalues.iteritems(): 106 if key in ("Project-Id-Version", "Last-Translator", "Language-Team", "PO-Revision-Date", "Content-Type", "Content-Transfer-Encoding", "Plural-Forms"): 107 # want to carry these from the template so we ignore them 108 pass 109 elif key == "POT-Creation-Date": 110 pot_creation_date = value 111 elif key == "MIME-Version": 112 mime_version = value 113 else: 114 kwargs[key] = value 115 targetheader = thetargetfile.makeheader(charset=charset, encoding=encoding, project_id_version=project_id_version, 116 pot_creation_date=pot_creation_date, po_revision_date=po_revision_date, last_translator=last_translator, 117 language_team=language_team, mime_version=mime_version, plural_forms=plural_forms, **kwargs) 118 # Get the header comments and fuzziness state 119 if templatepofile is not None and len(templatepo.units) > 0: 120 if templatepo.units[0].isheader(): 121 if templatepo.units[0].getnotes("translator"): 122 targetheader.addnote(templatepo.units[0].getnotes("translator"), "translator") 123 if inputpot.units[0].getnotes("developer"): 124 targetheader.addnote(inputpot.units[0].getnotes("developer"), "developer") 125 targetheader.markfuzzy(templatepo.units[0].isfuzzy()) 126 elif inputpot.units[0].isheader(): 127 targetheader.addnote(inputpot.units[0].getnotes()) 128 thetargetfile.addunit(targetheader) 129 # Do matching 130 for inputpotunit in inputpot.units: 131 if not (inputpotunit.isheader() or inputpotunit.isobsolete()): 132 if templatepofile: 133 possiblematches = [] 134 for location in inputpotunit.getlocations(): 135 templatepounit = templatepo.locationindex.get(location, None) 136 if templatepounit is not None: 137 possiblematches.append(templatepounit) 138 if len(inputpotunit.getlocations()) == 0: 139 templatepounit = templatepo.findunit(inputpotunit.source) 140 if templatepounit: 141 possiblematches.append(templatepounit) 142 for templatepounit in possiblematches: 143 if inputpotunit.source == templatepounit.source and templatepounit.target: 144 inputpotunit.merge(templatepounit, authoritative=True) 145 break 146 else: 147 fuzzycandidates = [] 148 if fuzzyfilematcher: 149 fuzzycandidates = fuzzyfilematcher.matches(inputpotunit.source) 150 if fuzzycandidates: 151 inputpotunit.merge(fuzzycandidates[0]) 152 original = templatepo.findunit(fuzzycandidates[0].source) 153 if original: 154 original.reused = True 155 if fuzzyglobalmatcher and not fuzzycandidates: 156 fuzzycandidates = fuzzyglobalmatcher.matches(inputpotunit.source) 157 if fuzzycandidates: 158 inputpotunit.merge(fuzzycandidates[0]) 159 else: 160 if fuzzyglobalmatcher: 161 fuzzycandidates = fuzzyglobalmatcher.matches(inputpotunit.source) 162 if fuzzycandidates: 163 inputpotunit.merge(fuzzycandidates[0]) 164 if inputpotunit.hasplural() and len(inputpotunit.target) == 0: 165 # Let's ensure that we have the correct number of plural forms: 166 nplurals, plural = thetargetfile.getheaderplural() 167 if nplurals and nplurals.isdigit() and nplurals != '2': 168 inputpotunit.target = multistring([""]*int(nplurals)) 169 thetargetfile.addunit(inputpotunit) 170 171 #Let's take care of obsoleted messages 172 if templatepofile: 173 newlyobsoleted = [] 174 for unit in templatepo.units: 175 if unit.isheader(): 176 continue 177 if unit.target and not (inputpot.findunit(unit.source) or hasattr(unit, "reused")): 178 #not in .pot, make it obsolete 179 unit.makeobsolete() 180 newlyobsoleted.append(unit) 181 elif unit.isobsolete(): 182 thetargetfile.addunit(unit) 183 for unit in newlyobsoleted: 184 thetargetfile.addunit(unit) 185 outputpofile.write(str(thetargetfile)) 186 return 1
187
188 -def main(argv=None):
189 from translate.convert import convert 190 formats = {"pot": ("po", convertpot), ("pot", "po"): ("po", convertpot)} 191 parser = convert.ConvertOptionParser(formats, usepots=True, usetemplates=True, 192 allowmissingtemplate=True, description=__doc__) 193 parser.add_option("", "--tm", dest="tm", default=None, 194 help="The file to use as translation memory when fuzzy matching") 195 parser.passthrough.append("tm") 196 defaultsimilarity = 75 197 parser.add_option("-s", "--similarity", dest="min_similarity", default=defaultsimilarity, 198 type="float", help="The minimum similarity for inclusion (default: %d%%)" % defaultsimilarity) 199 parser.passthrough.append("min_similarity") 200 parser.add_option("--nofuzzymatching", dest="fuzzymatching", action="store_false", 201 default=True, help="Disable fuzzy matching") 202 parser.passthrough.append("fuzzymatching") 203 parser.run(argv)
204 205 206 if __name__ == '__main__': 207 main() 208