1#!/usr/bin/env python3 2# 3# Copyright (C) 2004-2020 ZNC, see the NOTICE file for details. 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18import argparse 19import glob 20import os 21import re 22import subprocess 23 24parser = argparse.ArgumentParser() 25parser.add_argument('--include_dir', action='store') 26parser.add_argument('--explicit_sources', action='append') 27parser.add_argument('--tmpl_dirs', action='append') 28parser.add_argument('--strip_prefix', action='store') 29parser.add_argument('--tmp_prefix', action='store') 30parser.add_argument('--output', action='store') 31args = parser.parse_args() 32 33pot_list = [] 34 35# .tmpl 36tmpl_pot = args.tmp_prefix + '_tmpl.pot' 37tmpl_uniq_pot = args.tmp_prefix + '_tmpl_uniq.pot' 38tmpl = [] 39pattern = re.compile(r'<\?\s*(?:FORMAT|(PLURAL))\s+(?:CTX="([^"]+?)"\s+)?"([^"]+?)"(?(1)\s+"([^"]+?)"|).*?(?:"TRANSLATORS:\s*([^"]+?)")?\s*\?>') 40for tmpl_dir in args.tmpl_dirs: 41 for fname in glob.iglob(tmpl_dir + '/*.tmpl'): 42 fbase = fname[len(args.strip_prefix):] 43 with open(fname, 'rt', encoding='utf8') as f: 44 for linenum, line in enumerate(f): 45 for x in pattern.finditer(line): 46 text, plural, context, comment = x.group(3), x.group(4), x.group(2), x.group(5) 47 if comment: 48 tmpl.append('# {}'.format(comment)) 49 tmpl.append('#: {}:{}'.format(fbase, linenum + 1)) 50 if context: 51 tmpl.append('msgctxt "{}"'.format(context)) 52 tmpl.append('msgid "{}"'.format(text)) 53 if plural: 54 tmpl.append('msgid_plural "{}"'.format(plural)) 55 tmpl.append('msgstr[0] ""') 56 tmpl.append('msgstr[1] ""') 57 else: 58 tmpl.append('msgstr ""') 59 tmpl.append('') 60 61# Bundle header to .tmpl, even if there were no .tmpl files. 62# Some .tmpl files contain non-ASCII characters, and the header is needed 63# anyway, because it's omitted from xgettext call below. 64with open(tmpl_pot, 'wt', encoding='utf8') as f: 65 print('msgid ""', file=f) 66 print('msgstr ""', file=f) 67 print(r'"Content-Type: text/plain; charset=UTF-8\n"', file=f) 68 print(r'"Content-Transfer-Encoding: 8bit\n"', file=f) 69 print(file=f) 70 for line in tmpl: 71 print(line, file=f) 72subprocess.check_call(['msguniq', '--force-po', '-o', tmpl_uniq_pot, tmpl_pot]) 73pot_list.append(tmpl_uniq_pot) 74 75# .cpp 76main_pot = args.tmp_prefix + '_main.pot' 77subprocess.check_call(['xgettext', 78 '--omit-header', 79 '-D', args.include_dir, 80 '-o', main_pot, 81 '--keyword=t_s:1,1t', '--keyword=t_s:1,2c,2t', 82 '--keyword=t_f:1,1t', '--keyword=t_f:1,2c,2t', 83 '--keyword=t_p:1,2,3t', '--keyword=t_p:1,2,4c,4t', 84 '--keyword=t_d:1,1t', '--keyword=t_d:1,2c,2t', 85] + args.explicit_sources) 86if os.path.isfile(main_pot): 87 pot_list.append(main_pot) 88 89# combine 90if pot_list: 91 subprocess.check_call(['msgcat', '-o', args.output] + pot_list) 92