Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(59)

Side by Side Diff: translate/convert/pot2po.py

Issue 64: pot2po should support previous messages SVN Base: https://translate.svn.sourceforge.net/svnroot/translate/src/trunk/
Patch Set: Created 1 year, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*- 2 # -*- coding: utf-8 -*-
3 # 3 #
4 # Copyright 2004-2007 Zuza Software Foundation 4 # Copyright 2004-2007 Zuza Software Foundation
5 # 5 #
6 # This file is part of translate. 6 # This file is part of translate.
7 # 7 #
8 # translate is free software; you can redistribute it and/or modify 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 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 10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version. 11 # (at your option) any later version.
12 # 12 #
13 # translate is distributed in the hope that it will be useful, 13 # translate is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details. 16 # GNU General Public License for more details.
17 # 17 #
18 # You should have received a copy of the GNU General Public License 18 # You should have received a copy of the GNU General Public License
19 # along with translate; if not, write to the Free Software 19 # along with translate; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 21
22 """convert Gettext PO templates (.pot) to PO localization files, preserving exis ting translations 22 """convert Gettext PO templates (.pot) to PO localization files, preserving exis ting translations
23 23
24 See: http://translate.sourceforge.net/wiki/toolkit/pot2po for examples and 24 See: http://translate.sourceforge.net/wiki/toolkit/pot2po for examples and
25 usage instructions 25 usage instructions
26 """ 26 """
27 27
28 from translate.storage import po 28 from translate.storage import po
29 from translate.storage import factory 29 from translate.storage import factory
30 from translate.search import match 30 from translate.search import match
31 from translate.misc.multistring import multistring 31 from translate.misc.multistring import multistring
32 32
33 # We don't want to reinitialise the TM each time, so let's store it here. 33 # We don't want to reinitialise the TM each time, so let's store it here.
34 tmmatcher = None 34 tmmatcher = None
35 35
36 def memory(tmfiles, max_candidates=1, min_similarity=75, max_length=1000): 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.""" 37 """Returns the TM store to use. Only initialises on first call."""
38 global tmmatcher 38 global tmmatcher
39 # Only initialise first time 39 # Only initialise first time
40 if tmmatcher is None: 40 if tmmatcher is None:
41 if isinstance(tmfiles, list): 41 if isinstance(tmfiles, list):
42 tmstore = [factory.getobject(tmfile) for tmfile in tmfiles] 42 tmstore = [factory.getobject(tmfile) for tmfile in tmfiles]
43 else: 43 else:
44 tmstore = factory.getobject(tmfiles) 44 tmstore = factory.getobject(tmfiles)
45 tmmatcher = match.matcher(tmstore, max_candidates=max_candidates, min_si milarity=min_similarity, max_length=max_length) 45 tmmatcher = match.matcher(tmstore, max_candidates=max_candidates, min_si milarity=min_similarity, max_length=max_length)
46 return tmmatcher 46 return tmmatcher
47 47
48 def convertpot(inputpotfile, outputpofile, templatepofile, tm=None, min_similari ty=75, fuzzymatching=True, **kwargs): 48 def convertpot(inputpotfile, outputpofile, templatepofile, tm=None, min_similari ty=75,
49 fuzzymatching=True, ignore_previous=False, **kwargs):
49 inputpot = po.pofile(inputpotfile) 50 inputpot = po.pofile(inputpotfile)
50 templatepo = None 51 templatepo = None
51 if templatepofile is not None: 52 if templatepofile is not None:
52 templatepo = po.pofile(templatepofile) 53 templatepo = po.pofile(templatepofile)
53 outputpo = convertpot_stores(inputpot, templatepo, tm, min_similarity, fuzzy matching, **kwargs) 54 outputpo = convertpot_stores(inputpot, templatepo, tm, min_similarity,
55 fuzzymatching, ignore_previous, **kwargs)
54 outputpofile.write(str(outputpo)) 56 outputpofile.write(str(outputpo))
55 return 1 57 return 1
56 58
57 def convertpot_stores(inputpot, templatepo, tm=None, min_similarity=75, fuzzymat ching=True, **kwargs): 59 def convertpot_stores(inputpot, templatepo, tm=None, min_similarity=75,
60 fuzzymatching=True, ignore_previous=False, **kwargs):
58 """reads in inputpotfile, adjusts header, writes to outputpofile. if templat epofile exists, merge translations from it into outputpofile""" 61 """reads in inputpotfile, adjusts header, writes to outputpofile. if templat epofile exists, merge translations from it into outputpofile"""
59 inputpot.makeindex() 62 inputpot.makeindex()
60 thetargetfile = po.pofile() 63 thetargetfile = po.pofile()
61 # header values 64 # header values
62 charset = "UTF-8" 65 charset = "UTF-8"
63 encoding = "8bit" 66 encoding = "8bit"
64 project_id_version = None 67 project_id_version = None
65 pot_creation_date = None 68 pot_creation_date = None
66 po_revision_date = None 69 po_revision_date = None
67 last_translator = None 70 last_translator = None
68 language_team = None 71 language_team = None
69 mime_version = None 72 mime_version = None
70 plural_forms = None 73 plural_forms = None
71 kwargs = {} 74 kwargs = {}
72 if templatepo is not None: 75 if templatepo is not None:
73 fuzzyfilematcher = None 76 fuzzyfilematcher = None
74 if fuzzymatching: 77 if fuzzymatching:
75 for unit in templatepo.units: 78 for unit in templatepo.units:
76 if unit.isobsolete(): 79 if unit.isobsolete():
77 unit.resurrect() 80 unit.resurrect()
78 try: 81 try:
79 fuzzyfilematcher = match.matcher(templatepo, max_candidates=1, m in_similarity=min_similarity, max_length=3000, usefuzzy=True) 82 fuzzyfilematcher = match.matcher(templatepo, max_candidates=1, m in_similarity=min_similarity, max_length=3000, usefuzzy=True)
80 fuzzyfilematcher.addpercentage = False 83 fuzzyfilematcher.addpercentage = False
81 except ValueError: 84 except ValueError:
82 # Probably no usable units 85 # Probably no usable units
83 pass 86 pass
84 87
85 templatepo.makeindex() 88 templatepo.makeindex()
86 templateheadervalues = templatepo.parseheader() 89 templateheadervalues = templatepo.parseheader()
87 for key, value in templateheadervalues.iteritems(): 90 for key, value in templateheadervalues.iteritems():
88 if key == "Project-Id-Version": 91 if key == "Project-Id-Version":
89 project_id_version = value 92 project_id_version = value
90 elif key == "Last-Translator": 93 elif key == "Last-Translator":
91 last_translator = value 94 last_translator = value
92 elif key == "Language-Team": 95 elif key == "Language-Team":
93 language_team = value 96 language_team = value
94 elif key == "PO-Revision-Date": 97 elif key == "PO-Revision-Date":
95 po_revision_date = value 98 po_revision_date = value
96 elif key in ("POT-Creation-Date", "MIME-Version"): 99 elif key in ("POT-Creation-Date", "MIME-Version"):
97 # don't know how to handle these keys, or ignoring them 100 # don't know how to handle these keys, or ignoring them
98 pass 101 pass
99 elif key == "Content-Type": 102 elif key == "Content-Type":
100 kwargs[key] = value 103 kwargs[key] = value
101 elif key == "Content-Transfer-Encoding": 104 elif key == "Content-Transfer-Encoding":
102 encoding = value 105 encoding = value
103 elif key == "Plural-Forms": 106 elif key == "Plural-Forms":
104 plural_forms = value 107 plural_forms = value
105 else: 108 else:
106 kwargs[key] = value 109 kwargs[key] = value
107 fuzzyglobalmatcher = None 110 fuzzyglobalmatcher = None
108 if fuzzymatching and tm: 111 if fuzzymatching and tm:
109 fuzzyglobalmatcher = memory(tm, max_candidates=1, min_similarity=min_sim ilarity, max_length=1000) 112 fuzzyglobalmatcher = memory(tm, max_candidates=1, min_similarity=min_sim ilarity, max_length=1000)
110 fuzzyglobalmatcher.addpercentage = False 113 fuzzyglobalmatcher.addpercentage = False
111 inputheadervalues = inputpot.parseheader() 114 inputheadervalues = inputpot.parseheader()
112 for key, value in inputheadervalues.iteritems(): 115 for key, value in inputheadervalues.iteritems():
113 if key in ("Project-Id-Version", "Last-Translator", "Language-Team", "PO -Revision-Date", "Content-Type", "Content-Transfer-Encoding", "Plural-Forms"): 116 if key in ("Project-Id-Version", "Last-Translator", "Language-Team", "PO -Revision-Date", "Content-Type", "Content-Transfer-Encoding", "Plural-Forms"):
114 # want to carry these from the template so we ignore them 117 # want to carry these from the template so we ignore them
115 pass 118 pass
116 elif key == "POT-Creation-Date": 119 elif key == "POT-Creation-Date":
117 pot_creation_date = value 120 pot_creation_date = value
118 elif key == "MIME-Version": 121 elif key == "MIME-Version":
119 mime_version = value 122 mime_version = value
120 else: 123 else:
121 kwargs[key] = value 124 kwargs[key] = value
122 targetheader = thetargetfile.makeheader(charset=charset, encoding=encoding, project_id_version=project_id_version, 125 targetheader = thetargetfile.makeheader(charset=charset, encoding=encoding, project_id_version=project_id_version,
123 pot_creation_date=pot_creation_date, po_revision_date=po_revision_date, last_translator=last_translator, 126 pot_creation_date=pot_creation_date, po_revision_date=po_revision_date, last_translator=last_translator,
124 language_team=language_team, mime_version=mime_version, plural_forms=plu ral_forms, **kwargs) 127 language_team=language_team, mime_version=mime_version, plural_forms=plu ral_forms, **kwargs)
125 # Get the header comments and fuzziness state 128 # Get the header comments and fuzziness state
126 if templatepo is not None and len(templatepo.units) > 0: 129 if templatepo is not None and len(templatepo.units) > 0:
127 if templatepo.units[0].isheader(): 130 if templatepo.units[0].isheader():
128 if templatepo.units[0].getnotes("translator"): 131 if templatepo.units[0].getnotes("translator"):
129 targetheader.addnote(templatepo.units[0].getnotes("translator"), "translator") 132 targetheader.addnote(templatepo.units[0].getnotes("translator"), "translator")
130 if inputpot.units[0].getnotes("developer"): 133 if inputpot.units[0].getnotes("developer"):
131 targetheader.addnote(inputpot.units[0].getnotes("developer"), "d eveloper") 134 targetheader.addnote(inputpot.units[0].getnotes("developer"), "d eveloper")
132 targetheader.markfuzzy(templatepo.units[0].isfuzzy()) 135 targetheader.markfuzzy(templatepo.units[0].isfuzzy())
133 elif len(inputpot.units) > 0 and inputpot.units[0].isheader(): 136 elif len(inputpot.units) > 0 and inputpot.units[0].isheader():
134 targetheader.addnote(inputpot.units[0].getnotes()) 137 targetheader.addnote(inputpot.units[0].getnotes())
135 thetargetfile.addunit(targetheader) 138 thetargetfile.addunit(targetheader)
136 # Do matching 139 # Do matching
137 for inputpotunit in inputpot.units: 140 for inputpotunit in inputpot.units:
138 if not (inputpotunit.isheader() or inputpotunit.isobsolete()): 141 if not (inputpotunit.isheader() or inputpotunit.isobsolete()):
139 if templatepo: 142 if templatepo:
140 possiblematches = [] 143 possiblematches = []
141 for location in inputpotunit.getlocations(): 144 for location in inputpotunit.getlocations():
142 templatepounit = templatepo.locationindex.get(location, None ) 145 templatepounit = templatepo.locationindex.get(location, None )
143 if templatepounit is not None: 146 if templatepounit is not None:
144 possiblematches.append(templatepounit) 147 possiblematches.append(templatepounit)
145 if len(inputpotunit.getlocations()) == 0: 148 if len(inputpotunit.getlocations()) == 0:
146 templatepounit = templatepo.findunit(inputpotunit.source) 149 templatepounit = templatepo.findunit(inputpotunit.source)
147 if templatepounit: 150 if templatepounit:
148 possiblematches.append(templatepounit) 151 possiblematches.append(templatepounit)
149 for templatepounit in possiblematches: 152 for templatepounit in possiblematches:
150 if inputpotunit.source == templatepounit.source and template pounit.target: 153 if inputpotunit.source == templatepounit.source and template pounit.target:
151 inputpotunit.merge(templatepounit, authoritative=True) 154 inputpotunit.merge(templatepounit, authoritative=True)
152 break 155 break
153 else: 156 else:
154 fuzzycandidates = [] 157 fuzzycandidates = []
155 if fuzzyfilematcher: 158 if fuzzyfilematcher:
156 fuzzycandidates = fuzzyfilematcher.matches(inputpotunit. source) 159 fuzzycandidates = fuzzyfilematcher.matches(inputpotunit. source)
157 if fuzzycandidates: 160 if fuzzycandidates:
158 inputpotunit.merge(fuzzycandidates[0])
159 original = templatepo.findunit(fuzzycandidates[0].so urce) 161 original = templatepo.findunit(fuzzycandidates[0].so urce)
162 if original and not ignore_previous:
163 inputpotunit.set_as_previous()
164 inputpotunit.source = original.source
165 else:
166 inputpotunit.merge(fuzzycandidates[0])
160 if original: 167 if original:
161 original.reused = True 168 original.reused = True
162 if fuzzyglobalmatcher and not fuzzycandidates: 169 if fuzzyglobalmatcher and not fuzzycandidates:
163 fuzzycandidates = fuzzyglobalmatcher.matches(inputpotuni t.source) 170 fuzzycandidates = fuzzyglobalmatcher.matches(inputpotuni t.source)
164 if fuzzycandidates: 171 if fuzzycandidates:
165 inputpotunit.merge(fuzzycandidates[0]) 172 inputpotunit.merge(fuzzycandidates[0])
166 else: 173 else:
167 if fuzzyglobalmatcher: 174 if fuzzyglobalmatcher:
168 fuzzycandidates = fuzzyglobalmatcher.matches(inputpotunit.so urce) 175 fuzzycandidates = fuzzyglobalmatcher.matches(inputpotunit.so urce)
169 if fuzzycandidates: 176 if fuzzycandidates:
170 inputpotunit.merge(fuzzycandidates[0]) 177 inputpotunit.merge(fuzzycandidates[0])
171 if inputpotunit.hasplural() and len(inputpotunit.target) == 0: 178 if inputpotunit.hasplural() and len(inputpotunit.target) == 0:
172 # Let's ensure that we have the correct number of plural forms: 179 # Let's ensure that we have the correct number of plural forms:
173 nplurals, plural = thetargetfile.getheaderplural() 180 nplurals, plural = thetargetfile.getheaderplural()
174 if nplurals and nplurals.isdigit() and nplurals != '2': 181 if nplurals and nplurals.isdigit() and nplurals != '2':
175 inputpotunit.target = multistring([""]*int(nplurals)) 182 inputpotunit.target = multistring([""]*int(nplurals))
176 thetargetfile.addunit(inputpotunit) 183 thetargetfile.addunit(inputpotunit)
177 184
178 #Let's take care of obsoleted messages 185 #Let's take care of obsoleted messages
179 if templatepo: 186 if templatepo:
180 newlyobsoleted = [] 187 newlyobsoleted = []
181 for unit in templatepo.units: 188 for unit in templatepo.units:
182 if unit.isheader(): 189 if unit.isheader():
183 continue 190 continue
184 if unit.target and not (inputpot.findunit(unit.source) or hasattr(un it, "reused")): 191 if unit.target and not (inputpot.findunit(unit.source) or hasattr(un it, "reused")):
185 #not in .pot, make it obsolete 192 #not in .pot, make it obsolete
186 unit.makeobsolete() 193 unit.makeobsolete()
187 newlyobsoleted.append(unit) 194 newlyobsoleted.append(unit)
188 elif unit.isobsolete(): 195 elif unit.isobsolete():
189 thetargetfile.addunit(unit) 196 thetargetfile.addunit(unit)
190 for unit in newlyobsoleted: 197 for unit in newlyobsoleted:
191 thetargetfile.addunit(unit) 198 thetargetfile.addunit(unit)
192 return thetargetfile 199 return thetargetfile
193 200
194 def main(argv=None): 201 def main(argv=None):
195 from translate.convert import convert 202 from translate.convert import convert
196 formats = {"pot": ("po", convertpot), ("pot", "po"): ("po", convertpot)} 203 formats = {"pot": ("po", convertpot), ("pot", "po"): ("po", convertpot)}
197 parser = convert.ConvertOptionParser(formats, usepots=True, usetemplates=Tru e, 204 parser = convert.ConvertOptionParser(formats, usepots=True, usetemplates=Tru e,
198 allowmissingtemplate=True, description=__doc__) 205 allowmissingtemplate=True, description=__doc__)
199 parser.add_option("", "--tm", dest="tm", default=None, 206 parser.add_option("", "--tm", dest="tm", default=None,
200 help="The file to use as translation memory when fuzzy matching") 207 help="The file to use as translation memory when fuzzy matching")
201 parser.passthrough.append("tm") 208 parser.passthrough.append("tm")
202 defaultsimilarity = 75 209 defaultsimilarity = 75
203 parser.add_option("-s", "--similarity", dest="min_similarity", default=defau ltsimilarity, 210 parser.add_option("-s", "--similarity", dest="min_similarity", default=defau ltsimilarity,
204 type="float", help="The minimum similarity for inclusion (default: %d%%) " % defaultsimilarity) 211 type="float", help="The minimum similarity for inclusion (default: %d%%) " % defaultsimilarity)
205 parser.passthrough.append("min_similarity") 212 parser.passthrough.append("min_similarity")
206 parser.add_option("--nofuzzymatching", dest="fuzzymatching", action="store_f alse", 213 parser.add_option("--nofuzzymatching", dest="fuzzymatching", action="store_f alse",
207 default=True, help="Disable fuzzy matching") 214 default=True, help="Disable fuzzy matching")
208 parser.passthrough.append("fuzzymatching") 215 parser.passthrough.append("fuzzymatching")
216 parser.add_option("-g", "--ignore-previous", dest="ignore_previous",
217 action="store_true", default=False,
218 help="Don't keep previous messages")
219 parser.passthrough.append("ignore_previous")
209 parser.run(argv) 220 parser.run(argv)
210 221
211 222
212 if __name__ == '__main__': 223 if __name__ == '__main__':
213 main() 224 main()
OLDNEW

Powered by Google App Engine
This is Rietveld r159