ya2 · news · projects · code · about

housekeeping: ya2.utils.gui
[pmachines.git] / ya2 / build / lang.py
CommitLineData
8ee66edd 1'''Tools for l10n.'''
de1cfa8a
FC
2from os import system, makedirs, remove, listdir
3from os.path import exists, isfile, join
8ee66edd 4from shutil import move, copy
aa577aeb
FC
5from json import loads
6from polib import pofile, POEntry
9f095a28 7from ya2.build.build import find_file_names, FindFileNamesArgs
8ee66edd
FC
8
9
10class LanguageBuilder:
11 '''Tools for building files for l10n.'''
12
aa577aeb 13 def __init__(self, app_name, po_path, json_path, mo_path):
4e980d83
FC
14 self.__app_name = app_name
15 self.__po_path = po_path
aa577aeb 16 self.__json_path = json_path
4e980d83
FC
17 self.__mo_path = mo_path
18
de1cfa8a
FC
19 def build(self):
20 self.__build_pot()
21 po_files = [name for name in listdir(self.__po_path)
22 if isfile(join(self.__po_path, name)) and
23 name.endswith('.po')]
24 language_codes = [f.split('.')[0] for f in po_files]
25 for l in language_codes: self.__process_language(l)
8ee66edd 26
de1cfa8a 27 def __build_pot(self):
8ee66edd 28 '''Builds the pot file in the lng_dir_code directory.'''
9f095a28 29 find_info = FindFileNamesArgs(['py'], ['tests'])
d3ef798c 30 src_files = ' '.join(find_file_names(find_info))
8ee66edd
FC
31 cmd_tmpl = 'xgettext -ci18n -d {appname} -L python ' + \
32 '-o {pot_path}{appname}.pot '
4e980d83 33 system(cmd_tmpl.format(appname=self.__app_name, pot_path=self.__po_path) + src_files)
aa577aeb
FC
34 self.__add_from_json_to_pot()
35
36 def __add_from_json_to_pot(self):
37 json_files = [name for name in listdir(self.__json_path)
38 if isfile(join(self.__json_path, name)) and
88dde925
FC
39 name.endswith('.json') and
40 name != 'index.json']
aa577aeb
FC
41 json_strings = []
42 for json_file in json_files:
43 with open(f'{self.__json_path}{json_file}') as f:
44 json = loads(f.read())
45 json_strings += [json['name']]
88dde925
FC
46 for instruction_line in json['instructions'].split('\n'):
47 if instruction_line:
48 json_strings += [instruction_line]
aa577aeb
FC
49 def process_json_escape(string):
50 return bytes(string, 'utf-8').decode('unicode-escape')
51 json_strings = [process_json_escape(s) for s in json_strings]
52 json_strings = list(set(json_strings))
53 pot = pofile(f'{self.__po_path}{self.__app_name}.pot')
54 pot_ids = [entry.msgid for entry in pot]
55 for json_string in json_strings:
56 if json_string not in pot_ids:
57 entry = POEntry(msgid=json_string)
58 pot.append(entry)
59 pot.save(f'{self.__po_path}{self.__app_name}.pot')
8ee66edd 60
de1cfa8a
FC
61 def __process_language(self, language_code):
62 self.__merge(language_code)
63 self.__build_mo(language_code)
64
65 def __build_mo(self, language_code):
66 '''Builds the mo file in the lng_dir_code directory.'''
67 mo_template = '%s%s/LC_MESSAGES/%s.mo'
68 mo_name = mo_template % (self.__mo_path, language_code, self.__app_name)
69 lng_code = mo_name[len(self.__mo_path):].split('/')[0]
70 lng_dir = self.__mo_path + lng_code + '/LC_MESSAGES/'
71 cmd = 'msgfmt -o {lng_dir}{appname}.mo assets/locale/po/{lng_code}.po'
72 system(cmd.format(lng_dir=lng_dir, appname=self.__app_name, lng_code=lng_code))
73
74 def __merge(self, lng_code):
8ee66edd 75 '''Merges the new strings with the previous ones.'''
4e980d83 76 lng_base_dir = self.__prepare(lng_code)
de1cfa8a 77 self.__do_merge(lng_base_dir, lng_code)
4e980d83 78 self.__postprocess(lng_code)
8ee66edd 79
4e980d83 80 def __prepare(self, lng_code):
8ee66edd 81 '''Prepares a directory for working with languages.'''
4e980d83
FC
82 makedirs(self.__mo_path + lng_code + '/LC_MESSAGES', exist_ok=True)
83 lng_dir = self.__mo_path + lng_code + '/LC_MESSAGES/'
84 if not exists('assets/locale/po/' + lng_code + '.po'):
8ee66edd 85 lines_to_fix = ['CHARSET/UTF-8', 'ENCODING/8bit']
4e980d83 86 [self.__fix_line(line, lng_dir)
e65a09cf 87 for line in lines_to_fix]
4e980d83 88 copy(lng_dir + self.__app_name + '.pot', lng_dir + self.__app_name + '.po')
8ee66edd
FC
89 return lng_dir
90
4e980d83 91 def __fix_line(self, line, lng_dir):
8ee66edd
FC
92 '''Fixes po files (misaligned entries).'''
93 cmd_tmpl = "sed 's/{line}/' {lng_dir}{appname}.pot > " + \
94 "{lng_dir}{appname}tmp.po"
4e980d83
FC
95 system(cmd_tmpl.format(line=line, lng_dir=lng_dir, appname=self.__app_name))
96 move(lng_dir + self.__app_name + 'tmp.po', lng_dir + self.__app_name + '.pot')
8ee66edd 97
de1cfa8a 98 def __do_merge(self, lng_dir, lng_code):
8ee66edd
FC
99 '''Manages the msgmerge's invokation.'''
100 print('merge', lng_dir)
101 cmd = 'msgmerge -o {lng_dir}{appname}merge.po ' + \
102 '{tgt_path}{lng_code}.po {tgt_path}{appname}.pot'
4e980d83
FC
103 cmd = cmd.format(lng_dir=lng_dir, lng_code=lng_code, appname=self.__app_name,
104 tgt_path=self.__po_path)
8ee66edd 105 system(cmd)
4e980d83 106 copy(lng_dir + self.__app_name + 'merge.po',
e65a09cf 107 'assets/locale/po/%s.po' % lng_code)
8ee66edd 108 poname_tmpl = '{lng_dir}{appname}merge.po'
4e980d83 109 remove(poname_tmpl.format(lng_dir=lng_dir, appname=self.__app_name))
8ee66edd 110
4e980d83 111 def __postprocess(self, lng_code):
8ee66edd 112 '''Fixes po files at the end of the building process.'''
58c1093d
FC
113 lines = open('assets/locale/po/%s.po' % lng_code, 'r').readlines()
114 with open('assets/locale/po/%s.po' % lng_code, 'w') as outf:
8ee66edd
FC
115 for line in lines:
116 po_str = '"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\\n"\n'
117 outf.write(po_str if line.startswith(po_str[:20]) else line)