fix git support for v1.5.3 (or higher) by setting "--work-tree"
[translate_toolkit.git] / convert / oo2po.py
blobc465b3b9649db9ec2c7e7cdd4d85f9a59996bc79
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
4 # Copyright 2003-2008 Zuza Software Foundation
5 #
6 # This file is part of translate.
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.
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.
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
23 """convert an OpenOffice.org (SDF) localization file to Gettext PO localization files
25 See: http://translate.sourceforge.net/wiki/toolkit/oo2po for examples and
26 usage instructions
27 """
29 import os
30 import sys
31 from translate.storage import po
32 from translate.storage import oo
34 # TODO: support using one GSI file as template, another as input (for when English is in one and translation in another)
36 class oo2po:
37 def __init__(self, sourcelanguage, targetlanguage, blankmsgstr=False, long_keys=False):
38 """construct an oo2po converter for the specified languages"""
39 self.sourcelanguage = sourcelanguage
40 self.targetlanguage = targetlanguage
41 self.blankmsgstr = blankmsgstr
42 self.long_keys = long_keys
44 def maketargetunit(self, part1, part2, translators_comment, key, subkey):
45 """makes a base unit (.po or XLIFF) out of a subkey of two parts"""
46 #TODO: Do better
47 text1 = getattr(part1, subkey)
48 if text1 == "":
49 return None
50 text2 = getattr(part2, subkey)
52 unit = po.pounit(text1.decode('utf-8'), encoding="UTF-8")
53 unit.target = text2.decode('utf-8')
54 unit.addlocation(key + "." + subkey)
55 if getattr(translators_comment, subkey).strip() != "":
56 unit.addnote(getattr(translators_comment, subkey), origin="developer")
57 return unit
59 def makekey(self, ookey):
60 """converts an oo key tuple into a key identifier for the base class file (.po or XLIFF)"""
61 project, sourcefile, resourcetype, groupid, localid, platform = ookey
62 sourcefile = sourcefile.replace('\\','/')
63 if self.long_keys:
64 sourcebase = os.path.join(project, sourcefile)
65 else:
66 sourceparts = sourcefile.split('/')
67 sourcebase = "".join(sourceparts[-1:])
68 if (groupid) == 0 or len(localid) == 0:
69 ooid = groupid + localid
70 else:
71 ooid = groupid + "." + localid
72 if resourcetype:
73 ooid = ooid + "." + resourcetype
74 key = "%s#%s" % (sourcebase, ooid)
75 return oo.normalizefilename(key)
77 def convertelement(self, theoo):
78 """convert an oo element into a list of base units (.po or XLIFF)"""
79 if self.sourcelanguage in theoo.languages:
80 part1 = theoo.languages[self.sourcelanguage]
81 else:
82 print >> sys.stderr, "/".join(theoo.lines[0].getkey()), "language not found: %s" % (self.sourcelanguage)
83 return []
84 if self.blankmsgstr:
85 # use a blank part2
86 part2 = oo.ooline()
87 else:
88 if self.targetlanguage in theoo.languages:
89 part2 = theoo.languages[self.targetlanguage]
90 else:
91 # if the language doesn't exist, the translation is missing ... so make it blank
92 part2 = oo.ooline()
93 if "x-comment" in theoo.languages:
94 translators_comment = theoo.languages["x-comment"]
95 else:
96 translators_comment = oo.ooline()
97 key = self.makekey(part1.getkey())
98 unitlist = []
99 for subkey in ("text", "quickhelptext", "title"):
100 unit = self.maketargetunit(part1, part2, translators_comment, key, subkey)
101 if unit is not None:
102 unitlist.append(unit)
103 return unitlist
105 def convertstore(self, theoofile, duplicatestyle="msgctxt"):
106 """converts an entire oo file to a base class format (.po or XLIFF)"""
107 thetargetfile = po.pofile()
108 # create a header for the file
109 bug_url = 'http://qa.openoffice.org/issues/enter_bug.cgi' + ('''?subcomponent=ui&comment=&short_desc=Localization issue in file: %(filename)s&component=l10n&form_name=enter_issue''' % {"filename": theoofile.filename}).replace(" ", "%20").replace(":", "%3A")
110 targetheader = thetargetfile.makeheader(charset="UTF-8", encoding="8bit", x_accelerator_marker="~", report_msgid_bugs_to=bug_url)
111 targetheader.addnote("extracted from %s" % theoofile.filename, "developer")
112 thetargetfile.addunit(targetheader)
113 # go through the oo and convert each element
114 for theoo in theoofile.units:
115 unitlist = self.convertelement(theoo)
116 for unit in unitlist:
117 thetargetfile.addunit(unit)
118 thetargetfile.removeduplicates(duplicatestyle)
119 return thetargetfile
121 def verifyoptions(options):
122 """verifies the commandline options"""
123 if not options.pot and not options.targetlanguage:
124 raise ValueError("You must specify the target language unless generating POT files (-P)")
126 def convertoo(inputfile, outputfile, templates, pot=False, sourcelanguage=None, targetlanguage=None, duplicatestyle="msgid_comment", multifilestyle="single"):
127 """reads in stdin using inputstore class, converts using convertorclass, writes to stdout"""
128 inputstore = oo.oofile()
129 if hasattr(inputfile, "filename"):
130 inputfilename = inputfile.filename
131 else:
132 inputfilename = "(input file name not known)"
133 inputstore.filename = inputfilename
134 inputstore.parse(inputfile.read())
135 if not sourcelanguage:
136 testlangtype = targetlanguage or (inputstore and inputstore.languages[0]) or ""
137 if testlangtype.isdigit():
138 sourcelanguage = "01"
139 else:
140 sourcelanguage = "en-US"
141 if not sourcelanguage in inputstore.languages:
142 print >> sys.stderr, "Warning: sourcelanguage '%s' not found in inputfile '%s' (contains %s)" % (sourcelanguage, inputfilename, ", ".join(inputstore.languages))
143 if targetlanguage and targetlanguage not in inputstore.languages:
144 print >> sys.stderr, "Warning: targetlanguage '%s' not found in inputfile '%s' (contains %s)" % (targetlanguage, inputfilename, ", ".join(inputstore.languages))
145 convertor = oo2po(sourcelanguage, targetlanguage, blankmsgstr=pot, long_keys=multifilestyle!="single")
146 outputstore = convertor.convertstore(inputstore, duplicatestyle)
147 if outputstore.isempty():
148 return 0
149 outputfile.write(str(outputstore))
150 return 1
152 def main(argv=None):
153 from translate.convert import convert
154 formats = {"oo":("po", convertoo), "sdf":("po", convertoo)}
155 # always treat the input as an archive unless it is a directory
156 archiveformats = {(None, "input"): oo.oomultifile}
157 parser = convert.ArchiveConvertOptionParser(formats, usepots=True, description=__doc__, archiveformats=archiveformats)
158 parser.add_option("-l", "--language", dest="targetlanguage", default=None,
159 help="set target language to extract from oo file (e.g. af-ZA)", metavar="LANG")
160 parser.add_option("", "--source-language", dest="sourcelanguage", default=None,
161 help="set source language code (default en-US)", metavar="LANG")
162 parser.add_option("", "--nonrecursiveinput", dest="allowrecursiveinput", default=True, action="store_false", help="don't treat the input oo as a recursive store")
163 parser.add_duplicates_option()
164 parser.add_multifile_option()
165 parser.passthrough.append("pot")
166 parser.passthrough.append("sourcelanguage")
167 parser.passthrough.append("targetlanguage")
168 parser.verifyoptions = verifyoptions
169 parser.run(argv)
171 if __name__ == '__main__':
172 main()