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 getstrings(self, source):
41 Each INSERT statement contains a schema and tablename which we need to
42 insert into the config.i18n table. We'll push this into our
43 POEntry.occurrences attribute.
45 Each INSERT statement also contains 0 or more oils_i18n_gettext()
46 markers for the en-US string that we'll use for our msgid attribute.
48 A sample INSERT string that we'll scan is as follows:
50 INSERT INTO foo.bar (key, value) VALUES
51 (99, oils_i18n_gettext('string'));
55 # table holds the fully-qualified table name (schema.table)
56 # The source SQL may use multi-row VALUES clauses for a single
57 # insert statement, so we need to remember the fq-table for
61 findtable = re.compile(r'\s*INSERT\s+INTO\s+(\S+).*?$')
62 findi18n = re.compile(r'.*?oils_i18n_gettext\(\'(.+?)\'\)')
64 # Iterate through the source SQL grabbing table names and l10n strings
65 sourcefile = open(source)
66 for line in sourcefile:
67 ftable = findtable.search(line)
68 if ftable is not None:
69 table = ftable.group(1)
70 fi18n = findi18n.search(line)
72 for i18n in fi18n.groups():
73 # Unescape escaped SQL single-quotes for translators' sanity
74 i18n = re.compile(r'\'\'').sub("'", i18n)
77 poe.occurrences = [(table, num)]
82 def create_sql(self, locale):
84 Creates a set of INSERT statements that place translated strings
85 into the config.i18n_core table.
88 insert = "INSERT INTO config.i18n_core (fq_field, identity_value," \
89 " translation, string) VALUES ('%s', '%s', '%s', '%s');"
90 for entry in self.pot:
91 for table in entry.occurrences:
92 # Escape SQL single-quotes to avoid b0rkage
93 msgid = re.compile(r'\'').sub("''", entry.msgid)
94 msgstr = re.compile(r'\'').sub("''", entry.msgstr)
96 # Don't generate a stmt for an untranslated string
98 self.sql.append(insert % (table[0], msgid, locale, msgstr))
102 Determine what action to take
104 opts = optparse.OptionParser()
105 opts.add_option('-p', '--pot', action='store', \
106 help='Generate POT from the specified source SQL file', metavar='FILE')
107 opts.add_option('-s', '--sql', action='store', \
108 help='Generate SQL from the specified source POT file', metavar='FILE')
109 opts.add_option('-l', '--locale', \
110 help='Locale of the SQL file that will be generated')
111 opts.add_option('-o', '--output', dest='outfile', \
112 help='Write output to FILE (defaults to STDOUT)', metavar='FILE')
113 (options, args) = opts.parse_args()
117 pot.getstrings(options.pot)
119 pot.savepot(options.outfile)
121 sys.stdout.write(pot.pot.__str__())
123 if not options.locale:
124 opts.error('Must specify an output locale')
126 pot.loadpo(options.sql)
127 pot.create_sql(options.locale)
128 if not options.outfile:
131 outfile = open(options.outfile, 'w')
132 for insert in pot.sql:
133 outfile.write(insert + "\n")
137 if __name__ == '__main__':