michael@0: # preprocess-locale.py michael@0: # Any copyright is dedicated to the Public Domain. michael@0: # http://creativecommons.org/publicdomain/zero/1.0/ michael@0: michael@0: # preprocess-locale.py provides two functions depending on the arguments passed michael@0: # to it when invoked. michael@0: # michael@0: # Preprocesses installer locale properties files and creates a basic NSIS nlf michael@0: # file when invoked with --preprocess-locale. michael@0: # michael@0: # Converts a UTF-8 file to a new UTF-16LE file when invoked with michael@0: # --convert-utf8-utf16le. michael@0: michael@0: from codecs import BOM_UTF16_LE michael@0: from os.path import join, isfile michael@0: import sys michael@0: from optparse import OptionParser michael@0: michael@0: def open_utf16le_file(path): michael@0: """ michael@0: Returns an opened file object with a a UTF-16LE byte order mark. michael@0: """ michael@0: fp = open(path, "w+b") michael@0: fp.write(BOM_UTF16_LE) michael@0: return fp michael@0: michael@0: def get_locale_strings(path, prefix, middle, add_cr): michael@0: """ michael@0: Returns a string created by converting an installer locale properties file michael@0: into the format required by NSIS locale files. michael@0: michael@0: Parameters: michael@0: path - the path to the installer locale properties file to preprocess michael@0: prefix - a string to prefix each line with michael@0: middle - a string to insert between the name and value for each line michael@0: add_cr - boolean for whether to add an NSIS carriage return before NSIS michael@0: linefeeds when there isn't one already michael@0: """ michael@0: output = "" michael@0: fp = open(path, "r") michael@0: for line in fp: michael@0: line = line.strip() michael@0: if line == "" or line[0] == "#": michael@0: continue michael@0: michael@0: name, value = line.split("=", 1) michael@0: value = value.strip() # trim whitespace from the start and end michael@0: if value and value[-1] == "\"" and value[0] == "\"": michael@0: value = value[1:-1] # remove " from the start and end michael@0: michael@0: if add_cr: michael@0: value = value.replace("\\n", "\\r\\n") # prefix $\n with $\r michael@0: value = value.replace("\\r\\r", "\\r") # replace $\r$\r with $\r michael@0: michael@0: value = value.replace("\"", "$\\\"") # prefix " with $\ michael@0: value = value.replace("\\r", "$\\r") # prefix \r with $ michael@0: value = value.replace("\\n", "$\\n") # prefix \n with $ michael@0: value = value.replace("\\t", "$\\t") # prefix \t with $ michael@0: michael@0: output += prefix + name.strip() + middle + " \"" + value + "\"\n" michael@0: fp.close() michael@0: return output michael@0: michael@0: def lookup(path, l10ndirs): michael@0: for d in l10ndirs: michael@0: if isfile(join(d, path)): michael@0: return join(d, path) michael@0: return join(l10ndirs[-1], path) michael@0: michael@0: def preprocess_locale_files(config_dir, l10ndirs): michael@0: """ michael@0: Preprocesses the installer localized properties files into the format michael@0: required by NSIS and creates a basic NSIS nlf file. michael@0: michael@0: Parameters: michael@0: config_dir - the path to the destination directory michael@0: l10ndirs - list of paths to search for installer locale files michael@0: """ michael@0: michael@0: # Create the main NSIS language file michael@0: fp = open_utf16le_file(join(config_dir, "overrideLocale.nsh")) michael@0: locale_strings = get_locale_strings(lookup("override.properties", michael@0: l10ndirs), michael@0: "LangString ^", michael@0: " 0 ", michael@0: False) michael@0: fp.write(unicode(locale_strings, "utf-8").encode("utf-16-le")) michael@0: fp.close() michael@0: michael@0: # Create the Modern User Interface language file michael@0: fp = open_utf16le_file(join(config_dir, "baseLocale.nsh")) michael@0: fp.write((u""";NSIS Modern User Interface - Language File michael@0: ;Compatible with Modern UI 1.68 michael@0: ;Language: baseLocale (0) michael@0: !insertmacro MOZ_MUI_LANGUAGEFILE_BEGIN \"baseLocale\" michael@0: !define MUI_LANGNAME \"baseLocale\" michael@0: """).encode("utf-16-le")) michael@0: locale_strings = get_locale_strings(lookup("mui.properties", l10ndirs), michael@0: "!define ", " ", True) michael@0: fp.write(unicode(locale_strings, "utf-8").encode("utf-16-le")) michael@0: fp.write(u"!insertmacro MOZ_MUI_LANGUAGEFILE_END\n".encode("utf-16-le")) michael@0: fp.close() michael@0: michael@0: # Create the custom language file for our custom strings michael@0: fp = open_utf16le_file(join(config_dir, "customLocale.nsh")) michael@0: locale_strings = get_locale_strings(lookup("custom.properties", michael@0: l10ndirs), michael@0: "LangString ", michael@0: " 0 ", michael@0: True) michael@0: fp.write(unicode(locale_strings, "utf-8").encode("utf-16-le")) michael@0: fp.close() michael@0: michael@0: def create_nlf_file(moz_dir, ab_cd, config_dir): michael@0: """ michael@0: Create a basic NSIS nlf file. michael@0: michael@0: Parameters: michael@0: moz_dir - the path to top source directory for the toolkit source michael@0: ab_cd - the locale code michael@0: config_dir - the path to the destination directory michael@0: """ michael@0: rtl = "-" michael@0: michael@0: # Check whether the locale is right to left from locales.nsi. michael@0: fp = open(join(moz_dir, michael@0: "toolkit/mozapps/installer/windows/nsis/locales.nsi"), michael@0: "r") michael@0: for line in fp: michael@0: line = line.strip() michael@0: if line == "!define " + ab_cd + "_rtl": michael@0: rtl = "RTL" michael@0: break michael@0: michael@0: fp.close() michael@0: michael@0: # Create the main NSIS language file with RTL for right to left locales michael@0: # along with the default codepage, font name, and font size represented michael@0: # by the '-' character. michael@0: fp = open_utf16le_file(join(config_dir, "baseLocale.nlf")) michael@0: fp.write((u"""# Header, don't edit michael@0: NLF v6 michael@0: # Start editing here michael@0: # Language ID michael@0: 0 michael@0: # Font and size - dash (-) means default michael@0: - michael@0: - michael@0: # Codepage - dash (-) means ANSI code page michael@0: - michael@0: # RTL - anything else than RTL means LTR michael@0: %s michael@0: """ % rtl).encode("utf-16-le")) michael@0: fp.close() michael@0: michael@0: def preprocess_locale_file(config_dir, michael@0: l10ndirs, michael@0: properties_filename, michael@0: output_filename): michael@0: """ michael@0: Preprocesses a single localized properties file into the format michael@0: required by NSIS and creates a basic NSIS nlf file. michael@0: michael@0: Parameters: michael@0: config_dir - the path to the destination directory michael@0: l10ndirs - list of paths to search for installer locale files michael@0: properties_filename - the name of the properties file to search for michael@0: output_filename - the output filename to write michael@0: """ michael@0: michael@0: # Create the custom language file for our custom strings michael@0: fp = open_utf16le_file(join(config_dir, output_filename)) michael@0: locale_strings = get_locale_strings(lookup(properties_filename, michael@0: l10ndirs), michael@0: "LangString ", michael@0: " 0 ", michael@0: True) michael@0: fp.write(unicode(locale_strings, "utf-8").encode("utf-16-le")) michael@0: fp.close() michael@0: michael@0: michael@0: def convert_utf8_utf16le(in_file_path, out_file_path): michael@0: """ michael@0: Converts a UTF-8 file to a new UTF-16LE file michael@0: michael@0: Arguments: michael@0: in_file_path - the path to the UTF-8 source file to convert michael@0: out_file_path - the path to the UTF-16LE destination file to create michael@0: """ michael@0: in_fp = open(in_file_path, "r") michael@0: out_fp = open_utf16le_file(out_file_path) michael@0: out_fp.write(unicode(in_fp.read(), "utf-8").encode("utf-16-le")) michael@0: in_fp.close() michael@0: out_fp.close() michael@0: michael@0: if __name__ == '__main__': michael@0: usage = """usage: %prog command michael@0: michael@0: Commands: michael@0: --convert-utf8-utf16le - Preprocesses installer locale properties files michael@0: --preprocess-locale - Preprocesses the installer localized properties michael@0: files into the format required by NSIS and michael@0: creates a basic NSIS nlf file. michael@0: --preprocess-single-file - Preprocesses a single properties file into the michael@0: format required by NSIS michael@0: --create-nlf-file - Creates a basic NSIS nlf file michael@0: michael@0: preprocess-locale.py --preprocess-locale michael@0: michael@0: Arguments: michael@0: \tthe path to top source directory for the toolkit source michael@0: \tthe path to the installer's locale files michael@0: \tthe locale code michael@0: \tthe path to the destination directory michael@0: michael@0: michael@0: preprocess-locale.py --preprocess-single-file michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: Arguments: michael@0: \tthe path to top source directory for the toolkit source michael@0: \tthe path to the installer's locale files michael@0: \tthe path to the destination directory michael@0: \tthe properties file to process michael@0: \tthe nsh file to write michael@0: michael@0: michael@0: preprocess-locale.py --create-nlf-file michael@0: michael@0: michael@0: michael@0: Arguments: michael@0: \tthe path to top source directory for the toolkit source michael@0: \tthe locale code michael@0: \tthe path to the destination directory michael@0: michael@0: michael@0: preprocess-locale.py --convert-utf8-utf16le michael@0: michael@0: Arguments: michael@0: \tthe path to the UTF-8 source file to convert michael@0: \tthe path to the UTF-16LE destination file to create michael@0: """ michael@0: michael@0: preprocess_locale_args_help_string = """\ michael@0: Arguments to --preprocess-locale should be: michael@0: michael@0: or michael@0: --l10n-dir [--l10n-dir ...]""" michael@0: michael@0: preprocess_single_file_args_help_string = """\ michael@0: Arguments to --preprocess-single_file should be: michael@0: michael@0: or michael@0: michael@0: --l10n-dir [--l10n-dir ...]""" michael@0: michael@0: create_nlf_args_help_string = """\ michael@0: Arguments to --create-nlf-file should be: michael@0: """ michael@0: michael@0: p = OptionParser(usage=usage) michael@0: p.add_option("--preprocess-locale", action="store_true", default=False, michael@0: dest='preprocess') michael@0: p.add_option("--preprocess-single-file", action="store_true", default=False, michael@0: dest='preprocessSingle') michael@0: p.add_option("--create-nlf-file", action="store_true", default=False, michael@0: dest='createNlf') michael@0: p.add_option("--l10n-dir", action="append", default=[], michael@0: dest="l10n_dirs", michael@0: help="Add directory to lookup for locale files") michael@0: p.add_option("--convert-utf8-utf16le", action="store_true", default=False, michael@0: dest='convert') michael@0: michael@0: options, args = p.parse_args() michael@0: michael@0: foundOne = False michael@0: if (options.preprocess): michael@0: foundOne = True michael@0: if (options.convert): michael@0: if(foundOne): michael@0: p.error("More than one command specified") michael@0: else: michael@0: foundOne = True michael@0: if (options.preprocessSingle): michael@0: if(foundOne): michael@0: p.error("More than one command specified") michael@0: else: michael@0: foundOne = True michael@0: if (options.createNlf): michael@0: if(foundOne): michael@0: p.error("More than one command specified") michael@0: else: michael@0: foundOne = True michael@0: michael@0: if (not foundOne): michael@0: p.error("No command specified") michael@0: michael@0: if options.preprocess: michael@0: if len(args) not in (3,4): michael@0: p.error(preprocess_locale_args_help_string) michael@0: michael@0: # Parse args michael@0: pargs = args[:] michael@0: moz_dir = pargs[0] michael@0: if len(pargs) == 4: michael@0: l10n_dirs = [pargs[1]] michael@0: del pargs[1] michael@0: else: michael@0: if not options.l10n_dirs: michael@0: p.error(preprocess_locale_args_help_string) michael@0: l10n_dirs = options.l10n_dirs michael@0: ab_cd = pargs[1] michael@0: config_dir = pargs[2] michael@0: michael@0: # Create the output files michael@0: create_nlf_file(moz_dir, ab_cd, config_dir) michael@0: preprocess_locale_files(config_dir, l10n_dirs) michael@0: elif options.preprocessSingle: michael@0: if len(args) not in (4,5): michael@0: p.error(preprocess_single_file_args_help_string) michael@0: michael@0: # Parse args michael@0: pargs = args[:] michael@0: moz_dir = pargs[0] michael@0: if len(pargs) == 5: michael@0: l10n_dirs = [pargs[1]] michael@0: del pargs[1] michael@0: else: michael@0: if not options.l10n_dirs: michael@0: p.error(preprocess_single_file_args_help_string) michael@0: l10n_dirs = options.l10n_dirs michael@0: config_dir = pargs[1] michael@0: in_file = pargs[2] michael@0: out_file = pargs[3] michael@0: michael@0: # Create the output files michael@0: preprocess_locale_file(config_dir, michael@0: l10n_dirs, michael@0: in_file, michael@0: out_file) michael@0: elif options.createNlf: michael@0: if len(args) != 3: michael@0: p.error(create_nlf_args_help_string) michael@0: michael@0: # Parse args michael@0: pargs = args[:] michael@0: moz_dir = pargs[0] michael@0: ab_cd = pargs[1] michael@0: config_dir = pargs[2] michael@0: michael@0: # Create the output files michael@0: create_nlf_file(moz_dir, ab_cd, config_dir) michael@0: elif options.convert: michael@0: if len(args) != 2: michael@0: p.error("--convert-utf8-utf16le needs both of ") michael@0: convert_utf8_utf16le(*args)