nss: upgrade to release 3.73
[LibreOffice.git] / solenv / bin / desktop-translate.py
blob639fa89af48fc77599aecf3c6cc2533da6cf096b
2 # This file is part of the LibreOffice project.
4 # This Source Code Form is subject to the terms of the Mozilla Public
5 # License, v. 2.0. If a copy of the MPL was not distributed with this
6 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 # This file incorporates work covered by the following license notice:
10 # Licensed to the Apache Software Foundation (ASF) under one or more
11 # contributor license agreements. See the NOTICE file distributed
12 # with this work for additional information regarding copyright
13 # ownership. The ASF licenses this file to you under the Apache
14 # License, Version 2.0 (the "License"); you may not use this file
15 # except in compliance with the License. You may obtain a copy of
16 # the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 # Translates multiple .desktop files at once with strings from .ulf
21 # files; if you add new translatable .ulf files please add them to
22 # l10ntools/source/localize.cxx
25 import os, sys, argparse, io
27 def encodeDesktopString(s):
28 # <https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.1.html#
29 # value-types> says "The escape sequences \s, \n, \t, \r, and \\ are supported for values of
30 # type string and localestring, meaning ASCII space, newline, tab, carriage return, and
31 # backslash, respectively." <https://specifications.freedesktop.org/desktop-entry-spec/
32 # desktop-entry-spec-1.1.html#basic-format> says "A file is interpreted as a series of lines
33 # that are separated by linefeed characters", so it is apparently necessary to escape at least
34 # linefeed and backslash characters. It is unclear why that spec talks about "linefeed" in
35 # one place and about "newline" ("\n") and "carriage return" ("\r") in another, and how they are
36 # supposed to relate, so just escape any U+000A LINE FEED as "\n" and any U+000D CARRIAGE RETURN
37 # as "\r"; it is unclear exactly which occurrences of U+0020 SPACE and U+0009 CHARACTER
38 # TABULATION would need to be escaped, so they are mostly left unescaped, for readability:
39 s = s.replace('\\', '\\\\').replace('\n', '\\n').replace('\r', '\\r');
40 if s.startswith(' '):
41 # <https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.1.html#
42 # entries> says "Space before and after the equals sign should be ignored", so escape a
43 # leading U+0020 SPACE as "\s" (while it is not clear whether "space" there means just
44 # U+0020 SPACE or any kind of white space, in which case at least a leading U+0009 CHARACTER
45 # TABULATION should similarly be escaped as "\t"; also, it is unclear whether such
46 # characters should also be escaped at the end):
47 s = '\\s' + s[1:]
48 return s
50 parser = argparse.ArgumentParser()
51 parser.add_argument('-p', dest='productname', default='LibreOffice')
52 parser.add_argument('-d', dest='workdir', default='.')
53 parser.add_argument('--key', dest='key')
54 parser.add_argument('--prefix', dest='prefix', default='')
55 parser.add_argument('--ext', dest='ext')
56 parser.add_argument('--template-dir', dest='template_dir', default=None)
57 parser.add_argument('ifile')
59 o = parser.parse_args()
61 if o.template_dir is None:
62 template_dir = '{}/{}'.format(o.workdir, o.prefix)
63 else:
64 template_dir = o.template_dir
66 # hack for unity section
67 if o.key == "UnityQuickList":
68 outkey = "Name"
69 else:
70 outkey = o.key
73 templates = {}
75 # open input file
76 source = io.open(o.ifile, encoding='utf-8')
78 template = None
80 # read ulf file
81 for line in source:
82 if line.strip() == '':
83 continue
84 if line[0] == "[":
85 template = line.split(']', 1)[0][1:]
86 entry = {}
87 # For every section in the specified ulf file there should exist
88 # a template file in $workdir ..
89 entry['outfile'] = "{}{}.{}".format(template_dir, template, o.ext)
90 entry['translations'] = {}
91 templates[template] = entry
92 else:
93 # split locale = "value" into 2 strings
94 if ' = ' not in line:
95 continue
96 locale, value = line.split(' = ')
98 if locale != line:
99 # replace en-US with en
100 locale = locale.replace('en-US', 'en')
102 # use just anything inside the ""
103 assert(value[0] == '"')
104 # Some entries span multiple lines.
105 # An entry will always end on a double quote.
106 while not value.endswith('"\n'):
107 value += source.readline()
108 value = value[1:-2]
110 # replace resource placeholder
111 value = value.replace('%PRODUCTNAME', o.productname)
113 locale = locale.replace('-', '_')
115 templates[template]['translations'][locale] = value
117 source.close()
119 processed = 0
120 # process templates
121 for template in templates:
122 outfilename = templates[template]['outfile']
124 # open the template file - ignore sections for which no
125 # templates exist
126 try:
127 template_file = io.open(outfilename, encoding='utf-8')
128 except Exception:
129 # string files processed one by one
130 if o.ext == 'str':
131 continue
132 sys.exit("Warning: No template found for item '{}' : '{}' : '{}': $!\n".format(template, outfile, line))
133 processed += 1
135 # open output file
136 tmpfilename = '{}.tmp'.format(outfilename)
137 outfile = io.open(tmpfilename, 'w', encoding='utf-8')
139 # emit the template to the output file
140 for line in template_file:
141 keyline = line
142 if keyline.startswith(o.key):
143 keyline = outkey + keyline[len(o.key):]
144 outfile.write(keyline)
145 if o.key in line:
146 translations = templates[template]['translations']
147 for locale in sorted (translations.keys()):
148 value = translations.get(locale, None)
149 # print "locale is $locale\n";
150 # print "value is $value\n";
151 if value:
152 if o.ext == "desktop" or o.ext == "str":
153 if o.ext == "desktop":
154 value = encodeDesktopString(value)
155 outfile.write(u"""{}[{}]={}\n""".format(outkey, locale, value))
156 else:
157 outfile.write(u"""\t[{}]{}={}\n""".format(locale, outkey, value))
159 template_file.close()
161 outfile.close()
162 if os.path.exists(outfilename):
163 os.unlink(outfilename)
164 os.rename(tmpfilename, outfilename)
166 if o.ext == 'str' and processed == 0:
167 sys.exit("Warning: No matching templates processed")