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\"--> " \
110 def setDocumentLocator(self, locator):
112 Override setDocumentLocator so we can track line numbers
114 self.locator = locator
116 def startElement(self, name, attributes):
118 Return the reporter:label or name attribute value for each class
122 lineno = self.locator.getLineNumber()
124 self.classid = attributes['id']
125 if attributes.has_key('reporter:label'):
127 entity = "%s.%s.label" % (name, self.classid)
128 elif name == 'field':
129 entity = "%s.%s.%s.label" % (name, self.classid, \
131 label = attributes['reporter:label']
132 if not self.entities.has_key(label):
133 self.entities[label] = [(lineno, str(entity))]
135 self.entities[label].append((lineno, str(entity)))
137 # Now we'll render an entity-ized version of this element
138 element = "<%s" % (name)
139 for att in attributes.keys():
140 # Replace reporter:label attribute values with entities
141 if att == 'reporter:label':
142 element = element + " %s='&%s;'" % (att, entity)
144 element = element + " %s='%s'" % (att, attributes[att])
146 # field and link elements are empty elements
147 if name == 'field' or name == 'link':
148 element = element + " />"
150 element = element + ">"
151 self.entityized = self.entityized + element
153 def characters(self, content):
155 Shove character data into the entityized IDL file
157 self.entityized = self.entityized + content
159 def endElement(self, name):
161 field and link elements are empty elements
163 if name == 'field' or name == 'link':
166 self.entityized = self.entityized + "</%s>" % (name)
170 Determine what action to take
172 opts = optparse.OptionParser()
173 opts.add_option('-p', '--pot', action='store', \
174 help='Create a POT file from the specified fieldmapper IDL file', \
176 opts.add_option('-c', '--convert', action='store', \
177 help='Create a fieldmapper FILE that uses entities instead of text ' \
178 'strings for field labels and names', metavar='FILE')
179 opts.add_option('-e', '--entity', action='store', \
180 help='Create an entity definition from a translated PO FILE', \
182 opts.add_option('-o', '--output', dest='outfile', \
183 help='Write output to FILE (defaults to STDOUT)', metavar='FILE')
184 (options, args) = opts.parse_args()
187 # Generate a new POT file from the fieldmapper IDL
189 pot.get_strings(options.pot)
191 pot.savepot(options.outfile)
193 sys.stdout.write(pot.pot.__str__())
194 # Generate an entity file from a PO file
196 pot.loadpo(options.entity)
199 outfile = open(options.outfile, 'w')
200 for entity in pot.definitions:
201 outfile.write(entity)
203 for entity in pot.definitions:
205 # Generate an entity-ized fieldmapper IDL file
206 elif options.convert:
207 pot.get_strings(options.convert)
209 outfile = open(options.outfile)
210 outfile.write(pot.idl)
212 sys.stdout.write(pot.idl)
213 # No options were recognized - print help and bail
217 if __name__ == '__main__':