|
1 # preprocess-locale.py |
|
2 # Any copyright is dedicated to the Public Domain. |
|
3 # http://creativecommons.org/publicdomain/zero/1.0/ |
|
4 |
|
5 # preprocess-locale.py provides two functions depending on the arguments passed |
|
6 # to it when invoked. |
|
7 # |
|
8 # Preprocesses installer locale properties files and creates a basic NSIS nlf |
|
9 # file when invoked with --preprocess-locale. |
|
10 # |
|
11 # Converts a UTF-8 file to a new UTF-16LE file when invoked with |
|
12 # --convert-utf8-utf16le. |
|
13 |
|
14 from codecs import BOM_UTF16_LE |
|
15 from os.path import join, isfile |
|
16 import sys |
|
17 from optparse import OptionParser |
|
18 |
|
19 def open_utf16le_file(path): |
|
20 """ |
|
21 Returns an opened file object with a a UTF-16LE byte order mark. |
|
22 """ |
|
23 fp = open(path, "w+b") |
|
24 fp.write(BOM_UTF16_LE) |
|
25 return fp |
|
26 |
|
27 def get_locale_strings(path, prefix, middle, add_cr): |
|
28 """ |
|
29 Returns a string created by converting an installer locale properties file |
|
30 into the format required by NSIS locale files. |
|
31 |
|
32 Parameters: |
|
33 path - the path to the installer locale properties file to preprocess |
|
34 prefix - a string to prefix each line with |
|
35 middle - a string to insert between the name and value for each line |
|
36 add_cr - boolean for whether to add an NSIS carriage return before NSIS |
|
37 linefeeds when there isn't one already |
|
38 """ |
|
39 output = "" |
|
40 fp = open(path, "r") |
|
41 for line in fp: |
|
42 line = line.strip() |
|
43 if line == "" or line[0] == "#": |
|
44 continue |
|
45 |
|
46 name, value = line.split("=", 1) |
|
47 value = value.strip() # trim whitespace from the start and end |
|
48 if value and value[-1] == "\"" and value[0] == "\"": |
|
49 value = value[1:-1] # remove " from the start and end |
|
50 |
|
51 if add_cr: |
|
52 value = value.replace("\\n", "\\r\\n") # prefix $\n with $\r |
|
53 value = value.replace("\\r\\r", "\\r") # replace $\r$\r with $\r |
|
54 |
|
55 value = value.replace("\"", "$\\\"") # prefix " with $\ |
|
56 value = value.replace("\\r", "$\\r") # prefix \r with $ |
|
57 value = value.replace("\\n", "$\\n") # prefix \n with $ |
|
58 value = value.replace("\\t", "$\\t") # prefix \t with $ |
|
59 |
|
60 output += prefix + name.strip() + middle + " \"" + value + "\"\n" |
|
61 fp.close() |
|
62 return output |
|
63 |
|
64 def lookup(path, l10ndirs): |
|
65 for d in l10ndirs: |
|
66 if isfile(join(d, path)): |
|
67 return join(d, path) |
|
68 return join(l10ndirs[-1], path) |
|
69 |
|
70 def preprocess_locale_files(config_dir, l10ndirs): |
|
71 """ |
|
72 Preprocesses the installer localized properties files into the format |
|
73 required by NSIS and creates a basic NSIS nlf file. |
|
74 |
|
75 Parameters: |
|
76 config_dir - the path to the destination directory |
|
77 l10ndirs - list of paths to search for installer locale files |
|
78 """ |
|
79 |
|
80 # Create the main NSIS language file |
|
81 fp = open_utf16le_file(join(config_dir, "overrideLocale.nsh")) |
|
82 locale_strings = get_locale_strings(lookup("override.properties", |
|
83 l10ndirs), |
|
84 "LangString ^", |
|
85 " 0 ", |
|
86 False) |
|
87 fp.write(unicode(locale_strings, "utf-8").encode("utf-16-le")) |
|
88 fp.close() |
|
89 |
|
90 # Create the Modern User Interface language file |
|
91 fp = open_utf16le_file(join(config_dir, "baseLocale.nsh")) |
|
92 fp.write((u""";NSIS Modern User Interface - Language File |
|
93 ;Compatible with Modern UI 1.68 |
|
94 ;Language: baseLocale (0) |
|
95 !insertmacro MOZ_MUI_LANGUAGEFILE_BEGIN \"baseLocale\" |
|
96 !define MUI_LANGNAME \"baseLocale\" |
|
97 """).encode("utf-16-le")) |
|
98 locale_strings = get_locale_strings(lookup("mui.properties", l10ndirs), |
|
99 "!define ", " ", True) |
|
100 fp.write(unicode(locale_strings, "utf-8").encode("utf-16-le")) |
|
101 fp.write(u"!insertmacro MOZ_MUI_LANGUAGEFILE_END\n".encode("utf-16-le")) |
|
102 fp.close() |
|
103 |
|
104 # Create the custom language file for our custom strings |
|
105 fp = open_utf16le_file(join(config_dir, "customLocale.nsh")) |
|
106 locale_strings = get_locale_strings(lookup("custom.properties", |
|
107 l10ndirs), |
|
108 "LangString ", |
|
109 " 0 ", |
|
110 True) |
|
111 fp.write(unicode(locale_strings, "utf-8").encode("utf-16-le")) |
|
112 fp.close() |
|
113 |
|
114 def create_nlf_file(moz_dir, ab_cd, config_dir): |
|
115 """ |
|
116 Create a basic NSIS nlf file. |
|
117 |
|
118 Parameters: |
|
119 moz_dir - the path to top source directory for the toolkit source |
|
120 ab_cd - the locale code |
|
121 config_dir - the path to the destination directory |
|
122 """ |
|
123 rtl = "-" |
|
124 |
|
125 # Check whether the locale is right to left from locales.nsi. |
|
126 fp = open(join(moz_dir, |
|
127 "toolkit/mozapps/installer/windows/nsis/locales.nsi"), |
|
128 "r") |
|
129 for line in fp: |
|
130 line = line.strip() |
|
131 if line == "!define " + ab_cd + "_rtl": |
|
132 rtl = "RTL" |
|
133 break |
|
134 |
|
135 fp.close() |
|
136 |
|
137 # Create the main NSIS language file with RTL for right to left locales |
|
138 # along with the default codepage, font name, and font size represented |
|
139 # by the '-' character. |
|
140 fp = open_utf16le_file(join(config_dir, "baseLocale.nlf")) |
|
141 fp.write((u"""# Header, don't edit |
|
142 NLF v6 |
|
143 # Start editing here |
|
144 # Language ID |
|
145 0 |
|
146 # Font and size - dash (-) means default |
|
147 - |
|
148 - |
|
149 # Codepage - dash (-) means ANSI code page |
|
150 - |
|
151 # RTL - anything else than RTL means LTR |
|
152 %s |
|
153 """ % rtl).encode("utf-16-le")) |
|
154 fp.close() |
|
155 |
|
156 def preprocess_locale_file(config_dir, |
|
157 l10ndirs, |
|
158 properties_filename, |
|
159 output_filename): |
|
160 """ |
|
161 Preprocesses a single localized properties file into the format |
|
162 required by NSIS and creates a basic NSIS nlf file. |
|
163 |
|
164 Parameters: |
|
165 config_dir - the path to the destination directory |
|
166 l10ndirs - list of paths to search for installer locale files |
|
167 properties_filename - the name of the properties file to search for |
|
168 output_filename - the output filename to write |
|
169 """ |
|
170 |
|
171 # Create the custom language file for our custom strings |
|
172 fp = open_utf16le_file(join(config_dir, output_filename)) |
|
173 locale_strings = get_locale_strings(lookup(properties_filename, |
|
174 l10ndirs), |
|
175 "LangString ", |
|
176 " 0 ", |
|
177 True) |
|
178 fp.write(unicode(locale_strings, "utf-8").encode("utf-16-le")) |
|
179 fp.close() |
|
180 |
|
181 |
|
182 def convert_utf8_utf16le(in_file_path, out_file_path): |
|
183 """ |
|
184 Converts a UTF-8 file to a new UTF-16LE file |
|
185 |
|
186 Arguments: |
|
187 in_file_path - the path to the UTF-8 source file to convert |
|
188 out_file_path - the path to the UTF-16LE destination file to create |
|
189 """ |
|
190 in_fp = open(in_file_path, "r") |
|
191 out_fp = open_utf16le_file(out_file_path) |
|
192 out_fp.write(unicode(in_fp.read(), "utf-8").encode("utf-16-le")) |
|
193 in_fp.close() |
|
194 out_fp.close() |
|
195 |
|
196 if __name__ == '__main__': |
|
197 usage = """usage: %prog command <args> |
|
198 |
|
199 Commands: |
|
200 --convert-utf8-utf16le - Preprocesses installer locale properties files |
|
201 --preprocess-locale - Preprocesses the installer localized properties |
|
202 files into the format required by NSIS and |
|
203 creates a basic NSIS nlf file. |
|
204 --preprocess-single-file - Preprocesses a single properties file into the |
|
205 format required by NSIS |
|
206 --create-nlf-file - Creates a basic NSIS nlf file |
|
207 |
|
208 preprocess-locale.py --preprocess-locale <src> <locale> <code> <dest> |
|
209 |
|
210 Arguments: |
|
211 <src> \tthe path to top source directory for the toolkit source |
|
212 <locale>\tthe path to the installer's locale files |
|
213 <code> \tthe locale code |
|
214 <dest> \tthe path to the destination directory |
|
215 |
|
216 |
|
217 preprocess-locale.py --preprocess-single-file <src> |
|
218 <locale> |
|
219 <dest> |
|
220 <infile> |
|
221 <outfile> |
|
222 |
|
223 Arguments: |
|
224 <src> \tthe path to top source directory for the toolkit source |
|
225 <locale> \tthe path to the installer's locale files |
|
226 <dest> \tthe path to the destination directory |
|
227 <infile> \tthe properties file to process |
|
228 <outfile>\tthe nsh file to write |
|
229 |
|
230 |
|
231 preprocess-locale.py --create-nlf-file <src> |
|
232 <code> |
|
233 <dest> |
|
234 |
|
235 Arguments: |
|
236 <src> \tthe path to top source directory for the toolkit source |
|
237 <code> \tthe locale code |
|
238 <dest> \tthe path to the destination directory |
|
239 |
|
240 |
|
241 preprocess-locale.py --convert-utf8-utf16le <src> <dest> |
|
242 |
|
243 Arguments: |
|
244 <src> \tthe path to the UTF-8 source file to convert |
|
245 <dest>\tthe path to the UTF-16LE destination file to create |
|
246 """ |
|
247 |
|
248 preprocess_locale_args_help_string = """\ |
|
249 Arguments to --preprocess-locale should be: |
|
250 <src> <locale> <code> <dest> |
|
251 or |
|
252 <src> <code> <dest> --l10n-dir <dir> [--l10n-dir <dir> ...]""" |
|
253 |
|
254 preprocess_single_file_args_help_string = """\ |
|
255 Arguments to --preprocess-single_file should be: |
|
256 <src> <locale> <code> <dest> <infile> <outfile> |
|
257 or |
|
258 <src> <locale> <code> <dest> <infile> <outfile> |
|
259 --l10n-dir <dir> [--l10n-dir <dir>...]""" |
|
260 |
|
261 create_nlf_args_help_string = """\ |
|
262 Arguments to --create-nlf-file should be: |
|
263 <src> <code> <dest>""" |
|
264 |
|
265 p = OptionParser(usage=usage) |
|
266 p.add_option("--preprocess-locale", action="store_true", default=False, |
|
267 dest='preprocess') |
|
268 p.add_option("--preprocess-single-file", action="store_true", default=False, |
|
269 dest='preprocessSingle') |
|
270 p.add_option("--create-nlf-file", action="store_true", default=False, |
|
271 dest='createNlf') |
|
272 p.add_option("--l10n-dir", action="append", default=[], |
|
273 dest="l10n_dirs", |
|
274 help="Add directory to lookup for locale files") |
|
275 p.add_option("--convert-utf8-utf16le", action="store_true", default=False, |
|
276 dest='convert') |
|
277 |
|
278 options, args = p.parse_args() |
|
279 |
|
280 foundOne = False |
|
281 if (options.preprocess): |
|
282 foundOne = True |
|
283 if (options.convert): |
|
284 if(foundOne): |
|
285 p.error("More than one command specified") |
|
286 else: |
|
287 foundOne = True |
|
288 if (options.preprocessSingle): |
|
289 if(foundOne): |
|
290 p.error("More than one command specified") |
|
291 else: |
|
292 foundOne = True |
|
293 if (options.createNlf): |
|
294 if(foundOne): |
|
295 p.error("More than one command specified") |
|
296 else: |
|
297 foundOne = True |
|
298 |
|
299 if (not foundOne): |
|
300 p.error("No command specified") |
|
301 |
|
302 if options.preprocess: |
|
303 if len(args) not in (3,4): |
|
304 p.error(preprocess_locale_args_help_string) |
|
305 |
|
306 # Parse args |
|
307 pargs = args[:] |
|
308 moz_dir = pargs[0] |
|
309 if len(pargs) == 4: |
|
310 l10n_dirs = [pargs[1]] |
|
311 del pargs[1] |
|
312 else: |
|
313 if not options.l10n_dirs: |
|
314 p.error(preprocess_locale_args_help_string) |
|
315 l10n_dirs = options.l10n_dirs |
|
316 ab_cd = pargs[1] |
|
317 config_dir = pargs[2] |
|
318 |
|
319 # Create the output files |
|
320 create_nlf_file(moz_dir, ab_cd, config_dir) |
|
321 preprocess_locale_files(config_dir, l10n_dirs) |
|
322 elif options.preprocessSingle: |
|
323 if len(args) not in (4,5): |
|
324 p.error(preprocess_single_file_args_help_string) |
|
325 |
|
326 # Parse args |
|
327 pargs = args[:] |
|
328 moz_dir = pargs[0] |
|
329 if len(pargs) == 5: |
|
330 l10n_dirs = [pargs[1]] |
|
331 del pargs[1] |
|
332 else: |
|
333 if not options.l10n_dirs: |
|
334 p.error(preprocess_single_file_args_help_string) |
|
335 l10n_dirs = options.l10n_dirs |
|
336 config_dir = pargs[1] |
|
337 in_file = pargs[2] |
|
338 out_file = pargs[3] |
|
339 |
|
340 # Create the output files |
|
341 preprocess_locale_file(config_dir, |
|
342 l10n_dirs, |
|
343 in_file, |
|
344 out_file) |
|
345 elif options.createNlf: |
|
346 if len(args) != 3: |
|
347 p.error(create_nlf_args_help_string) |
|
348 |
|
349 # Parse args |
|
350 pargs = args[:] |
|
351 moz_dir = pargs[0] |
|
352 ab_cd = pargs[1] |
|
353 config_dir = pargs[2] |
|
354 |
|
355 # Create the output files |
|
356 create_nlf_file(moz_dir, ab_cd, config_dir) |
|
357 elif options.convert: |
|
358 if len(args) != 2: |
|
359 p.error("--convert-utf8-utf16le needs both of <src> <dest>") |
|
360 convert_utf8_utf16le(*args) |