1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/mozapps/installer/windows/nsis/preprocess-locale.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,360 @@ 1.4 +# preprocess-locale.py 1.5 +# Any copyright is dedicated to the Public Domain. 1.6 +# http://creativecommons.org/publicdomain/zero/1.0/ 1.7 + 1.8 +# preprocess-locale.py provides two functions depending on the arguments passed 1.9 +# to it when invoked. 1.10 +# 1.11 +# Preprocesses installer locale properties files and creates a basic NSIS nlf 1.12 +# file when invoked with --preprocess-locale. 1.13 +# 1.14 +# Converts a UTF-8 file to a new UTF-16LE file when invoked with 1.15 +# --convert-utf8-utf16le. 1.16 + 1.17 +from codecs import BOM_UTF16_LE 1.18 +from os.path import join, isfile 1.19 +import sys 1.20 +from optparse import OptionParser 1.21 + 1.22 +def open_utf16le_file(path): 1.23 + """ 1.24 + Returns an opened file object with a a UTF-16LE byte order mark. 1.25 + """ 1.26 + fp = open(path, "w+b") 1.27 + fp.write(BOM_UTF16_LE) 1.28 + return fp 1.29 + 1.30 +def get_locale_strings(path, prefix, middle, add_cr): 1.31 + """ 1.32 + Returns a string created by converting an installer locale properties file 1.33 + into the format required by NSIS locale files. 1.34 + 1.35 + Parameters: 1.36 + path - the path to the installer locale properties file to preprocess 1.37 + prefix - a string to prefix each line with 1.38 + middle - a string to insert between the name and value for each line 1.39 + add_cr - boolean for whether to add an NSIS carriage return before NSIS 1.40 + linefeeds when there isn't one already 1.41 + """ 1.42 + output = "" 1.43 + fp = open(path, "r") 1.44 + for line in fp: 1.45 + line = line.strip() 1.46 + if line == "" or line[0] == "#": 1.47 + continue 1.48 + 1.49 + name, value = line.split("=", 1) 1.50 + value = value.strip() # trim whitespace from the start and end 1.51 + if value and value[-1] == "\"" and value[0] == "\"": 1.52 + value = value[1:-1] # remove " from the start and end 1.53 + 1.54 + if add_cr: 1.55 + value = value.replace("\\n", "\\r\\n") # prefix $\n with $\r 1.56 + value = value.replace("\\r\\r", "\\r") # replace $\r$\r with $\r 1.57 + 1.58 + value = value.replace("\"", "$\\\"") # prefix " with $\ 1.59 + value = value.replace("\\r", "$\\r") # prefix \r with $ 1.60 + value = value.replace("\\n", "$\\n") # prefix \n with $ 1.61 + value = value.replace("\\t", "$\\t") # prefix \t with $ 1.62 + 1.63 + output += prefix + name.strip() + middle + " \"" + value + "\"\n" 1.64 + fp.close() 1.65 + return output 1.66 + 1.67 +def lookup(path, l10ndirs): 1.68 + for d in l10ndirs: 1.69 + if isfile(join(d, path)): 1.70 + return join(d, path) 1.71 + return join(l10ndirs[-1], path) 1.72 + 1.73 +def preprocess_locale_files(config_dir, l10ndirs): 1.74 + """ 1.75 + Preprocesses the installer localized properties files into the format 1.76 + required by NSIS and creates a basic NSIS nlf file. 1.77 + 1.78 + Parameters: 1.79 + config_dir - the path to the destination directory 1.80 + l10ndirs - list of paths to search for installer locale files 1.81 + """ 1.82 + 1.83 + # Create the main NSIS language file 1.84 + fp = open_utf16le_file(join(config_dir, "overrideLocale.nsh")) 1.85 + locale_strings = get_locale_strings(lookup("override.properties", 1.86 + l10ndirs), 1.87 + "LangString ^", 1.88 + " 0 ", 1.89 + False) 1.90 + fp.write(unicode(locale_strings, "utf-8").encode("utf-16-le")) 1.91 + fp.close() 1.92 + 1.93 + # Create the Modern User Interface language file 1.94 + fp = open_utf16le_file(join(config_dir, "baseLocale.nsh")) 1.95 + fp.write((u""";NSIS Modern User Interface - Language File 1.96 +;Compatible with Modern UI 1.68 1.97 +;Language: baseLocale (0) 1.98 +!insertmacro MOZ_MUI_LANGUAGEFILE_BEGIN \"baseLocale\" 1.99 +!define MUI_LANGNAME \"baseLocale\" 1.100 +""").encode("utf-16-le")) 1.101 + locale_strings = get_locale_strings(lookup("mui.properties", l10ndirs), 1.102 + "!define ", " ", True) 1.103 + fp.write(unicode(locale_strings, "utf-8").encode("utf-16-le")) 1.104 + fp.write(u"!insertmacro MOZ_MUI_LANGUAGEFILE_END\n".encode("utf-16-le")) 1.105 + fp.close() 1.106 + 1.107 + # Create the custom language file for our custom strings 1.108 + fp = open_utf16le_file(join(config_dir, "customLocale.nsh")) 1.109 + locale_strings = get_locale_strings(lookup("custom.properties", 1.110 + l10ndirs), 1.111 + "LangString ", 1.112 + " 0 ", 1.113 + True) 1.114 + fp.write(unicode(locale_strings, "utf-8").encode("utf-16-le")) 1.115 + fp.close() 1.116 + 1.117 +def create_nlf_file(moz_dir, ab_cd, config_dir): 1.118 + """ 1.119 + Create a basic NSIS nlf file. 1.120 + 1.121 + Parameters: 1.122 + moz_dir - the path to top source directory for the toolkit source 1.123 + ab_cd - the locale code 1.124 + config_dir - the path to the destination directory 1.125 + """ 1.126 + rtl = "-" 1.127 + 1.128 + # Check whether the locale is right to left from locales.nsi. 1.129 + fp = open(join(moz_dir, 1.130 + "toolkit/mozapps/installer/windows/nsis/locales.nsi"), 1.131 + "r") 1.132 + for line in fp: 1.133 + line = line.strip() 1.134 + if line == "!define " + ab_cd + "_rtl": 1.135 + rtl = "RTL" 1.136 + break 1.137 + 1.138 + fp.close() 1.139 + 1.140 + # Create the main NSIS language file with RTL for right to left locales 1.141 + # along with the default codepage, font name, and font size represented 1.142 + # by the '-' character. 1.143 + fp = open_utf16le_file(join(config_dir, "baseLocale.nlf")) 1.144 + fp.write((u"""# Header, don't edit 1.145 +NLF v6 1.146 +# Start editing here 1.147 +# Language ID 1.148 +0 1.149 +# Font and size - dash (-) means default 1.150 +- 1.151 +- 1.152 +# Codepage - dash (-) means ANSI code page 1.153 +- 1.154 +# RTL - anything else than RTL means LTR 1.155 +%s 1.156 +""" % rtl).encode("utf-16-le")) 1.157 + fp.close() 1.158 + 1.159 +def preprocess_locale_file(config_dir, 1.160 + l10ndirs, 1.161 + properties_filename, 1.162 + output_filename): 1.163 + """ 1.164 + Preprocesses a single localized properties file into the format 1.165 + required by NSIS and creates a basic NSIS nlf file. 1.166 + 1.167 + Parameters: 1.168 + config_dir - the path to the destination directory 1.169 + l10ndirs - list of paths to search for installer locale files 1.170 + properties_filename - the name of the properties file to search for 1.171 + output_filename - the output filename to write 1.172 + """ 1.173 + 1.174 + # Create the custom language file for our custom strings 1.175 + fp = open_utf16le_file(join(config_dir, output_filename)) 1.176 + locale_strings = get_locale_strings(lookup(properties_filename, 1.177 + l10ndirs), 1.178 + "LangString ", 1.179 + " 0 ", 1.180 + True) 1.181 + fp.write(unicode(locale_strings, "utf-8").encode("utf-16-le")) 1.182 + fp.close() 1.183 + 1.184 + 1.185 +def convert_utf8_utf16le(in_file_path, out_file_path): 1.186 + """ 1.187 + Converts a UTF-8 file to a new UTF-16LE file 1.188 + 1.189 + Arguments: 1.190 + in_file_path - the path to the UTF-8 source file to convert 1.191 + out_file_path - the path to the UTF-16LE destination file to create 1.192 + """ 1.193 + in_fp = open(in_file_path, "r") 1.194 + out_fp = open_utf16le_file(out_file_path) 1.195 + out_fp.write(unicode(in_fp.read(), "utf-8").encode("utf-16-le")) 1.196 + in_fp.close() 1.197 + out_fp.close() 1.198 + 1.199 +if __name__ == '__main__': 1.200 + usage = """usage: %prog command <args> 1.201 + 1.202 +Commands: 1.203 + --convert-utf8-utf16le - Preprocesses installer locale properties files 1.204 + --preprocess-locale - Preprocesses the installer localized properties 1.205 + files into the format required by NSIS and 1.206 + creates a basic NSIS nlf file. 1.207 + --preprocess-single-file - Preprocesses a single properties file into the 1.208 + format required by NSIS 1.209 + --create-nlf-file - Creates a basic NSIS nlf file 1.210 + 1.211 +preprocess-locale.py --preprocess-locale <src> <locale> <code> <dest> 1.212 + 1.213 +Arguments: 1.214 + <src> \tthe path to top source directory for the toolkit source 1.215 + <locale>\tthe path to the installer's locale files 1.216 + <code> \tthe locale code 1.217 + <dest> \tthe path to the destination directory 1.218 + 1.219 + 1.220 +preprocess-locale.py --preprocess-single-file <src> 1.221 + <locale> 1.222 + <dest> 1.223 + <infile> 1.224 + <outfile> 1.225 + 1.226 +Arguments: 1.227 + <src> \tthe path to top source directory for the toolkit source 1.228 + <locale> \tthe path to the installer's locale files 1.229 + <dest> \tthe path to the destination directory 1.230 + <infile> \tthe properties file to process 1.231 + <outfile>\tthe nsh file to write 1.232 + 1.233 + 1.234 +preprocess-locale.py --create-nlf-file <src> 1.235 + <code> 1.236 + <dest> 1.237 + 1.238 +Arguments: 1.239 + <src> \tthe path to top source directory for the toolkit source 1.240 + <code> \tthe locale code 1.241 + <dest> \tthe path to the destination directory 1.242 + 1.243 + 1.244 +preprocess-locale.py --convert-utf8-utf16le <src> <dest> 1.245 + 1.246 +Arguments: 1.247 + <src> \tthe path to the UTF-8 source file to convert 1.248 + <dest>\tthe path to the UTF-16LE destination file to create 1.249 +""" 1.250 + 1.251 + preprocess_locale_args_help_string = """\ 1.252 +Arguments to --preprocess-locale should be: 1.253 + <src> <locale> <code> <dest> 1.254 +or 1.255 + <src> <code> <dest> --l10n-dir <dir> [--l10n-dir <dir> ...]""" 1.256 + 1.257 + preprocess_single_file_args_help_string = """\ 1.258 +Arguments to --preprocess-single_file should be: 1.259 + <src> <locale> <code> <dest> <infile> <outfile> 1.260 +or 1.261 + <src> <locale> <code> <dest> <infile> <outfile> 1.262 + --l10n-dir <dir> [--l10n-dir <dir>...]""" 1.263 + 1.264 + create_nlf_args_help_string = """\ 1.265 +Arguments to --create-nlf-file should be: 1.266 + <src> <code> <dest>""" 1.267 + 1.268 + p = OptionParser(usage=usage) 1.269 + p.add_option("--preprocess-locale", action="store_true", default=False, 1.270 + dest='preprocess') 1.271 + p.add_option("--preprocess-single-file", action="store_true", default=False, 1.272 + dest='preprocessSingle') 1.273 + p.add_option("--create-nlf-file", action="store_true", default=False, 1.274 + dest='createNlf') 1.275 + p.add_option("--l10n-dir", action="append", default=[], 1.276 + dest="l10n_dirs", 1.277 + help="Add directory to lookup for locale files") 1.278 + p.add_option("--convert-utf8-utf16le", action="store_true", default=False, 1.279 + dest='convert') 1.280 + 1.281 + options, args = p.parse_args() 1.282 + 1.283 + foundOne = False 1.284 + if (options.preprocess): 1.285 + foundOne = True 1.286 + if (options.convert): 1.287 + if(foundOne): 1.288 + p.error("More than one command specified") 1.289 + else: 1.290 + foundOne = True 1.291 + if (options.preprocessSingle): 1.292 + if(foundOne): 1.293 + p.error("More than one command specified") 1.294 + else: 1.295 + foundOne = True 1.296 + if (options.createNlf): 1.297 + if(foundOne): 1.298 + p.error("More than one command specified") 1.299 + else: 1.300 + foundOne = True 1.301 + 1.302 + if (not foundOne): 1.303 + p.error("No command specified") 1.304 + 1.305 + if options.preprocess: 1.306 + if len(args) not in (3,4): 1.307 + p.error(preprocess_locale_args_help_string) 1.308 + 1.309 + # Parse args 1.310 + pargs = args[:] 1.311 + moz_dir = pargs[0] 1.312 + if len(pargs) == 4: 1.313 + l10n_dirs = [pargs[1]] 1.314 + del pargs[1] 1.315 + else: 1.316 + if not options.l10n_dirs: 1.317 + p.error(preprocess_locale_args_help_string) 1.318 + l10n_dirs = options.l10n_dirs 1.319 + ab_cd = pargs[1] 1.320 + config_dir = pargs[2] 1.321 + 1.322 + # Create the output files 1.323 + create_nlf_file(moz_dir, ab_cd, config_dir) 1.324 + preprocess_locale_files(config_dir, l10n_dirs) 1.325 + elif options.preprocessSingle: 1.326 + if len(args) not in (4,5): 1.327 + p.error(preprocess_single_file_args_help_string) 1.328 + 1.329 + # Parse args 1.330 + pargs = args[:] 1.331 + moz_dir = pargs[0] 1.332 + if len(pargs) == 5: 1.333 + l10n_dirs = [pargs[1]] 1.334 + del pargs[1] 1.335 + else: 1.336 + if not options.l10n_dirs: 1.337 + p.error(preprocess_single_file_args_help_string) 1.338 + l10n_dirs = options.l10n_dirs 1.339 + config_dir = pargs[1] 1.340 + in_file = pargs[2] 1.341 + out_file = pargs[3] 1.342 + 1.343 + # Create the output files 1.344 + preprocess_locale_file(config_dir, 1.345 + l10n_dirs, 1.346 + in_file, 1.347 + out_file) 1.348 + elif options.createNlf: 1.349 + if len(args) != 3: 1.350 + p.error(create_nlf_args_help_string) 1.351 + 1.352 + # Parse args 1.353 + pargs = args[:] 1.354 + moz_dir = pargs[0] 1.355 + ab_cd = pargs[1] 1.356 + config_dir = pargs[2] 1.357 + 1.358 + # Create the output files 1.359 + create_nlf_file(moz_dir, ab_cd, config_dir) 1.360 + elif options.convert: 1.361 + if len(args) != 2: 1.362 + p.error("--convert-utf8-utf16le needs both of <src> <dest>") 1.363 + convert_utf8_utf16le(*args)