6 Run this script from the root of the repository to update all translations from 8 It will do the following automatically: 10 - fetch all translations using the tx tool 11 - post-process them into valid and committable format 12 - remove invalid control characters 13 - remove location tags (makes diffs less noisy) 16 - auto-add new translations to the build system according to the translation process 18 from __future__
import division, print_function
24 import xml.etree.ElementTree
as ET
29 SOURCE_LANG =
'dash_en.ts' 31 LOCALE_DIR =
'src/qt/locale' 36 if not os.path.exists(
'.git'):
37 print(
'No .git directory found')
38 print(
'Execute this script at the root of the repository', file=sys.stderr)
42 if subprocess.call([TX,
'pull',
'-f',
'-a']):
43 print(
'Error while fetching translations', file=sys.stderr)
47 '''Find all format specifiers in a string.''' 51 percent = s.find(
'%', pos)
55 specifiers.append(s[percent+1])
57 print(
'Failed to get specifier')
62 '''Split format specifiers between numeric (Qt) and others (strprintf)''' 66 if s
in {
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9'}:
72 return set(numeric),other
75 '''Sanitize string for printing''' 76 return s.replace(
'\n',
' ')
89 if source_f != translation_f:
90 if numerus
and source_f == (set(), [
'n'])
and translation_f == (set(), [])
and translation.find(
'%') == -1:
98 for filename
in os.listdir(LOCALE_DIR):
100 if not filename.endswith(
'.ts'+suffix)
or filename == SOURCE_LANG+suffix:
103 filename = filename[0:-len(suffix)]
104 filepath = os.path.join(LOCALE_DIR, filename)
105 yield(filename, filepath)
107 FIX_RE = re.compile(b
'[\x00-\x09\x0b\x0c\x0e-\x1f]')
109 '''Remove invalid characters from translation string''' 110 return FIX_RE.sub(b
'', s)
114 _orig_escape_cdata =
None 117 text = text.replace(
"'",
''')
118 text = text.replace(
'"',
'"')
122 print(
'Checking and postprocessing...')
124 if reduce_diff_hacks:
125 global _orig_escape_cdata
126 _orig_escape_cdata = ET._escape_cdata
127 ET._escape_cdata = escape_cdata
130 os.rename(filepath, filepath+
'.orig')
135 parser = ET.XMLParser(encoding=
'utf-8')
136 with open(filepath +
'.orig',
'rb')
as f:
140 tree = ET.parse(io.BytesIO(data), parser=parser)
143 root = tree.getroot()
144 for context
in root.findall(
'context'):
145 for message
in context.findall(
'message'):
146 numerus = message.get(
'numerus') ==
'yes' 147 source = message.find(
'source').text
148 translation_node = message.find(
'translation')
151 translations = [i.text
for i
in translation_node.findall(
'numerusform')]
153 translations = [translation_node.text]
155 for translation
in translations:
156 if translation
is None:
162 print(
'%s: %s' % (filename, error))
165 translation_node.clear()
166 translation_node.set(
'type',
'unfinished')
170 for location
in message.findall(
'location'):
171 message.remove(location)
174 if translation_node.get(
'type') ==
'unfinished':
175 context.remove(message)
179 for context
in root.findall(
'context'):
180 for message
in context.findall(
'message'):
182 if num_messages < MIN_NUM_MESSAGES:
183 print(
'Removing %s, as it contains only %i messages' % (filepath, num_messages))
188 if reduce_diff_hacks:
190 tree.write(out, encoding=
'utf-8')
192 out = out.replace(b
' />', b
'/>')
193 with open(filepath,
'wb')
as f:
196 tree.write(filepath, encoding=
'utf-8')
199 if __name__ ==
'__main__':
def split_format_specifiers(specifiers)
def postprocess_translations(reduce_diff_hacks=False)
def find_format_specifiers(s)
def all_ts_files(suffix='')
def check_at_repository_root()
def check_format_specifiers(source, translation, errors, numerus)
def remove_invalid_characters(s)
def fetch_all_translations()