toolkit/mozapps/installer/windows/nsis/preprocess-locale.py

changeset 0
6474c204b198
     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)

mercurial