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 get_strings(self, source):
43 Extracts translatable strings from the reporter:label attributes
44 in Evergreen's fieldmapper IDL file.
48 locator = xml.sax.xmlreader.Locator()
49 parser = xml.sax.make_parser()
50 handler = IDLHandler()
51 handler.setDocumentLocator(locator)
52 parser.setContentHandler(handler)
55 for entity in handler.entities:
57 poe.occurrences = handler.entities[entity]
60 self.idl = handler.entityized
62 def create_entity(self):
64 Creates an entity definition file based on a translated PO file.
66 entity = '<!ENTITY %s "%s">'
67 for entry in self.pot:
68 for name in entry.occurrences:
69 if entry.msgstr == '':
70 # No translation available; use the en-US definition
71 self.definitions.append(entity % (name[0], entry.msgid))
73 self.definitions.append(entity % (name[0], entry.msgstr))
75 class IDLHandler(xml.sax.handler.ContentHandler):
77 Parses a fieldmapper IDL file to get at reporter:label and name attributes.
78 Generates a list of entity definitions and their values, as well as an
79 entity-ized version of the fieldmapper IDL.
83 xml.sax.handler.ContentHandler.__init__(self)
84 self.entities = dict()
86 self.entityized = u"""<?xml version="1.0" encoding="utf-8"?>
87 <!DOCTYPE fieldmapper [
88 <!--#include virtual="/opac/locale/${locale}/fm_IDL.dtd"-->
93 def setDocumentLocator(self, locator):
95 Override setDocumentLocator so we can track line numbers
97 self.locator = locator
99 def startElement(self, name, attributes):
101 Return the reporter:label or name attribute value for each class
102 field, or link element.
105 lineno = self.locator.getLineNumber()
107 self.classid = attributes['id']
108 if attributes.has_key('reporter:label'):
110 entity = "%s.%s.label" % (name, self.classid)
111 elif name == 'field':
112 entity = "%s.%s.%s.label" % (name, self.classid, \
115 entity = "%s.%s.%s.label" % (name, self.classid, \
117 label = attributes['reporter:label']
118 if not self.entities.has_key(label):
119 self.entities[label] = [(str(entity), lineno)]
121 self.entities[label].append((str(entity), lineno))
123 # Now we'll render an entity-ized version of this element
124 element = "<%s" % (name)
125 for att in attributes.keys():
126 # Replace reporter:label attribute values with entities
127 if att == 'reporter:label':
128 element = element + " %s='&%s;'" % (att, entity)
130 element = element + " %s='%s'" % (att, attributes[att])
132 # field and link elements are empty elements
133 if name == 'field' or name == 'link':
134 element = element + " />"
136 element = element + ">"
137 self.entityized = self.entityized + element
139 def characters(self, content):
141 Shove character data into the entityized IDL file
143 self.entityized = self.entityized + xml.sax.saxutils.escape(content)
145 def endElement(self, name):
147 field and link elements are empty elements
149 if name == 'field' or name == 'link':
152 self.entityized = self.entityized + "</%s>" % (name)
156 Determine what action to take
158 opts = optparse.OptionParser()
159 opts.add_option('-p', '--pot', action='store', \
160 help='Create a POT file from the specified fieldmapper IDL file', \
162 opts.add_option('-c', '--convert', action='store', \
163 help='Create a fieldmapper FILE that uses entities instead of text ' \
164 'strings for field labels and names', metavar='FILE')
165 opts.add_option('-e', '--entity', action='store', \
166 help='Create an entity definition from a translated PO FILE', \
168 opts.add_option('-o', '--output', dest='outfile', \
169 help='Write output to FILE (defaults to STDOUT)', metavar='FILE')
170 (options, args) = opts.parse_args()
173 # Generate a new POT file from the fieldmapper IDL
175 pot.get_strings(options.pot)
177 pot.savepot(options.outfile)
179 sys.stdout.write(pot.pot.__str__())
180 # Generate an entity file from a PO file
182 pot.loadpo(options.entity)
185 outfile = open(options.outfile, 'w')
186 for entity in pot.definitions:
187 outfile.write(entity + "\n")
189 for entity in pot.definitions:
191 # Generate an entity-ized fieldmapper IDL file
192 elif options.convert:
193 pot.get_strings(options.convert)
195 outfile = open(options.outfile, 'w')
196 outfile.write(pot.idl)
198 sys.stdout.write(pot.idl)
199 # No options were recognized - print help and bail
203 if __name__ == '__main__':