4 This class enables translation of Evergreen's seed database strings.
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.
26 class SQL(basel10n.BaseL10N):
28 This class provides methods for extracting translatable strings from
29 Evergreen's database seed values, generating a translatable POT file,
30 reading translated PO files, and generating SQL for inserting the
31 translated values into the Evergreen database.
36 basel10n.BaseL10N.__init__(self)
39 def loadpo(self, potfile):
43 basel10n.BaseL10N.loadpo(self, potfile)
47 Initialize POT metadata
49 basel10n.BaseL10N.pothead(self)
51 def savepot(self, outfile):
55 basel10n.BaseL10N.savepot(self, outfile)
57 def getstrings(self, source):
59 Each INSERT statement contains a schema and tablename which we need to
60 insert into the config.i18n table. We'll push this into our
61 POEntry.occurences attribute.
63 Each INSERT statement also contains 0 or more oils_i18n_gettext()
64 markers for the en-US string that we'll use for our msgid attribute.
66 A sample INSERT string that we'll scan is as follows:
68 INSERT INTO foo.bar (key, value) VALUES
69 (99, oils_i18n_gettext('string'));
73 # table holds the fully-qualified table name (schema.table)
74 # The source SQL may use multi-row VALUES clauses for a single
75 # insert statement, so we need to remember the fq-table for
79 findtable = re.compile(r'\s*INSERT\s+INTO\s+(\S+).*?$')
80 findi18n = re.compile(r'.*?oils_i18n_gettext\(\'(.+?)\'\)')
82 # Iterate through the source SQL grabbing table names and l10n strings
83 sourcefile = open(source)
84 for line in sourcefile:
85 ftable = findtable.search(line)
86 if ftable is not None:
87 table = ftable.group(1)
88 fi18n = findi18n.search(line)
90 for i18n in fi18n.groups():
91 # Unescape escaped SQL single-quotes for translators' sanity
92 i18n = re.compile(r'\'\'').sub("'", i18n)
95 poe.occurences = [(table, num)]
100 def create_sql(self, locale):
102 Creates a set of INSERT statements that place translated strings
103 into the config.i18n_core table.
106 insert = "INSERT INTO config.i18n_core (fq_field, identity_value," \
107 " translation, string) VALUES ('%s', '%s', '%s', '%s');"
108 for entry in self.pot:
109 for table in entry.occurences:
110 # Escape SQL single-quotes to avoid b0rkage
111 msgid = re.compile(r'\'').sub("''", entry.msgid)
112 msgstr = re.compile(r'\'').sub("''", entry.msgstr)
114 # Don't generate a stmt for an untranslated string
116 self.sql.append(insert % (table[0], msgid, locale, msgstr))
120 Determine what action to take
122 opts = optparse.OptionParser()
123 opts.add_option('-p', '--pot', action='store', \
124 help='Generate POT from the specified source SQL file', metavar='FILE')
125 opts.add_option('-s', '--sql', action='store', \
126 help='Generate SQL from the specified source POT file', metavar='FILE')
127 opts.add_option('-l', '--locale', \
128 help='Locale of the SQL file that will be generated')
129 opts.add_option('-o', '--output', dest='outfile', \
130 help='Write output to FILE (defaults to STDOUT)', metavar='FILE')
131 (options, args) = opts.parse_args()
135 pot.getstrings(options.pot)
137 pot.savepot(options.outfile)
139 sys.stdout.write(pot.pot.__str__())
141 if not options.locale:
142 opts.error('Must specify an output locale')
144 pot.loadpo(options.sql)
145 pot.create_sql(options.locale)
146 if not options.outfile:
149 outfile = open(options.outfile, 'w')
150 for insert in pot.sql:
151 outfile.write(insert + "\n")
155 if __name__ == '__main__':