ya2 · news · projects · code · about

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