4 This class enables translation of Evergreen's fieldmapper IDL XML.
6 Requires polib from http://polib.googlecode.com
8 # Copyright 2007 Dan Scott <dscott@laurentian.ca>
10 # This program is free software; you can redistribute it and/or
11 # modify it under the terms of the GNU General Public License
12 # as published by the Free Software Foundation; either version 2
13 # of the License, or (at your option) any later version.
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
25 import xml.sax.handler
27 class IDL(basel10n.BaseL10N):
29 This class provides methods for extracting translatable strings from
30 Evergreen's fieldmapper IDL reporter:label attributes, generating a
31 translatable POT file, reading translated PO files, and generating
32 an updated fm_IDL.xml file with the additional language strings.
37 basel10n.BaseL10N.__init__(self)
41 def loadpo(self, potfile):
45 basel10n.BaseL10N.loadpo(self, potfile)
49 Initialize POT metadata
51 basel10n.BaseL10N.pothead(self)
53 def savepot(self, outfile):
57 basel10n.BaseL10N.savepot(self, outfile)
59 def get_strings(self, source):
61 Extracts translatable strings from the reporter:label attributes
62 in Evergreen's fieldmapper IDL file.
66 locator = xml.sax.xmlreader.Locator()
67 parser = xml.sax.make_parser()
68 handler = IDLHandler()
69 handler.setDocumentLocator(locator)
70 parser.setContentHandler(handler)
73 for entity in handler.entities:
75 poe.occurences = handler.entities[entity]
78 self.idl = handler.entityized
80 def create_entity(self):
82 Creates an entity definition file based on a translated PO file.
84 entity = '<!ENTITY %s "%s">'
85 for entry in self.pot:
86 for name in entry.occurences:
87 if entry.msgstr == '':
88 # No translation available; use the en-US definition
89 self.definitions.append(entity % (name[0], entry.msgid))
91 self.definitions.append(entity % (name[0], entry.msgstr))
93 class IDLHandler(xml.sax.handler.ContentHandler):
95 Parses a fieldmapper IDL file to get at reporter:label and name attributes.
96 Generates a list of entity definitions and their values, as well as an
97 entity-ized version of the fieldmapper IDL.
101 xml.sax.handler.ContentHandler.__init__(self)
102 self.entities = dict()
104 self.entityized = u"""<?xml version="1.0" encoding="utf-8"?>
105 <!DOCTYPE fieldmapper [
106 <!--#include virtual="/opac/locale/${locale}/fm_IDL.dtd"-->
111 def setDocumentLocator(self, locator):
113 Override setDocumentLocator so we can track line numbers
115 self.locator = locator
117 def startElement(self, name, attributes):
119 Return the reporter:label or name attribute value for each class
123 lineno = self.locator.getLineNumber()
125 self.classid = attributes['id']
126 if attributes.has_key('reporter:label'):
128 entity = "%s.%s.label" % (name, self.classid)
129 elif name == 'field':
130 entity = "%s.%s.%s.label" % (name, self.classid, \
132 label = attributes['reporter:label']
133 if not self.entities.has_key(label):
134 self.entities[label] = [(str(entity), lineno)]
136 self.entities[label].append((str(entity), lineno))
138 # Now we'll render an entity-ized version of this element
139 element = "<%s" % (name)
140 for att in attributes.keys():
141 # Replace reporter:label attribute values with entities
142 if att == 'reporter:label':
143 element = element + " %s='&%s;'" % (att, entity)
145 element = element + " %s='%s'" % (att, attributes[att])
147 # field and link elements are empty elements
148 if name == 'field' or name == 'link':
149 element = element + " />"
151 element = element + ">"
152 self.entityized = self.entityized + element
154 def characters(self, content):
156 Shove character data into the entityized IDL file
158 self.entityized = self.entityized + content
160 def endElement(self, name):
162 field and link elements are empty elements
164 if name == 'field' or name == 'link':
167 self.entityized = self.entityized + "</%s>" % (name)
171 Determine what action to take
173 opts = optparse.OptionParser()
174 opts.add_option('-p', '--pot', action='store', \
175 help='Create a POT file from the specified fieldmapper IDL file', \
177 opts.add_option('-c', '--convert', action='store', \
178 help='Create a fieldmapper FILE that uses entities instead of text ' \
179 'strings for field labels and names', metavar='FILE')
180 opts.add_option('-e', '--entity', action='store', \
181 help='Create an entity definition from a translated PO FILE', \
183 opts.add_option('-o', '--output', dest='outfile', \
184 help='Write output to FILE (defaults to STDOUT)', metavar='FILE')
185 (options, args) = opts.parse_args()
188 # Generate a new POT file from the fieldmapper IDL
190 pot.get_strings(options.pot)
192 pot.savepot(options.outfile)
194 sys.stdout.write(pot.pot.__str__())
195 # Generate an entity file from a PO file
197 pot.loadpo(options.entity)
200 outfile = open(options.outfile, 'w')
201 for entity in pot.definitions:
202 outfile.write(entity + "\n")
204 for entity in pot.definitions:
206 # Generate an entity-ized fieldmapper IDL file
207 elif options.convert:
208 pot.get_strings(options.convert)
210 outfile = open(options.outfile, 'w')
211 outfile.write(pot.idl)
213 sys.stdout.write(pot.idl)
214 # No options were recognized - print help and bail
218 if __name__ == '__main__':