1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3# 4# Copyright (C) 2013-2021 Edgewall Software 5# Copyright (C) 2013 Christian Boos <cboos@edgewall.org> 6# All rights reserved. 7# 8# This software is licensed as described in the file COPYING, which 9# you should have received as part of this distribution. The terms 10# are also available at https://trac.edgewall.org/wiki/TracLicense. 11# 12# This software consists of voluntary contributions made by many 13# individuals. For the exact contribution history, see the revision 14# history and logs, available at https://trac.edgewall.org/. 15 16""" 17 18L10N tool which prepares an index of "interesting" changes found in a 19.diff. 20 21Skipped changes are: 22 - the changes for which the msgid has changed 23 - removal only of msgstr content 24 25 26Example workflow 1), review changes to the 'fr' translation before 27committing: 28 29 make diff-fr | less 30 31 32Example workflow 2), force a pull of all changes from Transifex:: 33 34 make update updateopts=-N 35 tx pull -f 36 make update updateopts=-N 37 svn diff > tx.diff 38 python l10n_diff_index.py tx.diff 39 svn revert -R . 40 41And then use either:: 42 43 emacs tx.diff.index --eval '(grep-mode)' 44 45or:: 46 47 vim -c :cbuffer -c :copen tx.diff.index 48 49This makes it easier to go through the potentially interesting changes 50only, and apply the corresponding chunks if needed. 51 52""" 53 54from bisect import bisect_left 55import re 56 57interesting_changes_re = re.compile(r''' 58 \n 59 \s (?: msgid(?:_plural)?\s)? ".*" \n # ' ' msgid or "...", 60 (?: 61 [-\s] ".*" \n # ' ' or - "...", 62 | 63 - msgstr(?:\[\d+\])? \s ".*" \n # or the -msgstr 64 )* 65 66 (?: 67 ( \+ msgstr(?:\[\d+\])? \s "[^"].*" ) \n # \1 is a non-empty +msgstr 68 | 69 [+\s] msgstr(?:\[\d+\])? \s ".*" \n # or after the msgstr, 70 (?: [-\s] ".*" \n # optional ' ' or -"...", 71 )* 72 ( \+ "[^"].*" ) # \2 is a non-empty +"..." 73 ) 74''', re.MULTILINE | re.VERBOSE) 75 76def index_diffs(path, diffs): 77 linenums = [] 78 re.sub(r'\n', lambda m: linenums.append(m.start()), diffs) 79 index = [] 80 for m in interesting_changes_re.finditer(diffs): 81 line = m.group(m.lastindex) 82 if line.startswith(('+"Project-Id-Version:', '+"PO-Revision-Date:')): 83 continue 84 pos = m.start(m.lastindex) 85 index.append((bisect_left(linenums, pos) + 1, line)) 86 return index 87 88def write_index_for(path): 89 with open(path, 'rb') as f: 90 diffs = str(f.read(), 'utf-8') 91 changes = index_diffs(path, diffs) 92 if changes: 93 index = path + '.index' 94 with open(index, 'wb') as idx: 95 for n, line in changes: 96 print(("%s:%s: %s" % (path, n, line)).encode('utf-8'), 97 file=idx) 98 print("%s: %d changes indexed in %s" % (path, len(changes), index)) 99 else: 100 print("%s: no interesting changes" % path) 101 102if __name__ == '__main__': 103 import sys 104 for path in sys.argv[1:]: 105 write_index_for(path) 106