1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
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
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
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
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
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
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
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
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
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
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
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