-
-
Notifications
You must be signed in to change notification settings - Fork 16
/
translation.py
147 lines (128 loc) · 7.11 KB
/
translation.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import glob
import subprocess
from pathlib import Path
from pytransifex import Transifex
from qgispluginci.parameters import Parameters
from qgispluginci.exceptions import TranslationFailed, TransifexNoResource, TransifexManyResources
from qgispluginci.utils import touch_file
class Translation:
def __init__(self, parameters: Parameters,
transifex_token: str,
create_project: bool = True):
"""
Parameters
----------
parameters:
transifex_token:
Transifex API token
create_project:
if True, it will create the project, resource and language on Transifex
"""
self.parameters = parameters
self._t = Transifex(transifex_token, parameters.transifex_organization, i18n_type='QT')
assert self._t.ping()
self.ts_file = '{dir}/i18n/{res}_{lan}.ts'.format(dir=self.parameters.plugin_path,
res=self.parameters.transifex_resource,
lan=self.parameters.translation_source_language)
if self._t.project_exists(parameters.transifex_project):
print('Project {o}/{p} exists on Transifex'.format(o=self.parameters.transifex_organization,
p=self.parameters.transifex_project))
elif create_project:
print('project does not exists on Transifex, creating one as {o}/{p}'.format(o=self.parameters.transifex_organization,
p=self.parameters.transifex_project))
self._t.create_project(slug=self.parameters.transifex_project,
repository_url=self.parameters.repository_url,
source_language_code=parameters.translation_source_language)
self.update_strings()
print('creating resource in {o}/{p}/{r} with {f}'.format(o=self.parameters.transifex_organization,
p=self.parameters.transifex_project,
r=self.parameters.transifex_resource,
f=self.ts_file))
self._t.create_resource(project_slug=self.parameters.transifex_project,
path_to_file=self.ts_file,
resource_slug=self.parameters.transifex_resource)
print('OK')
else:
raise TranslationFailed('Project {o}/{p} does not exists on Transifex'.format(
o=self.parameters.transifex_organization, p=self.parameters.transifex_project))
def update_strings(self):
"""
Update TS files from plugin source strings
"""
source_files = []
for ext in ('py', 'ui'):
for file in glob.glob('{dir}/**/*.{ext}'.format(dir=self.parameters.plugin_path, ext=ext), recursive=True):
source_files.append(str(Path(file).relative_to('./qgis_plugin_ci_testing')))
touch_file(self.ts_file)
project_file = Path(self.parameters.plugin_path).joinpath(self.parameters.plugin_name + '.pro')
with open(project_file, 'w') as f:
assert f.write('CODECFORTR = UTF-8\n')
assert f.write('SOURCES = {}\n'.format(' '.join(source_files)))
assert f.write('TRANSLATIONS = {}\n'.format(Path(self.ts_file).relative_to('./qgis_plugin_ci_testing')))
f.flush()
f.close()
cmd = [self.parameters.pylupdate5_path, '-noobsolete', str(project_file)]
output = subprocess.run(cmd, capture_output=True, text=True)
project_file.unlink()
if output.returncode != 0:
raise TranslationFailed(output.stderr)
else:
print('Successfully run pylupdate5: {}'.format(output.stdout))
def compile_strings(self):
"""
Compile TS file into QM files
"""
cmd = [self.parameters.lrelease_path]
for file in glob.glob('{dir}/i18n/*.ts'.format(dir=self.parameters.plugin_path)):
cmd.append(file)
output = subprocess.run(cmd, capture_output=True, text=True)
if output.returncode != 0:
raise TranslationFailed(output.stderr)
else:
print('Successfully run lrelease: {}'.format(output.stdout))
def pull(self):
"""
Pull TS files from Transifex
"""
resource = self.__get_resource()
existing_langs = self._t.list_languages(
project_slug=self.parameters.transifex_project, resource_slug=resource['slug']
)
existing_langs.remove(self.parameters.translation_source_language)
print('{c} languages found for resource ''{s}'' ({langs})'.format(
s=resource['slug'], c=len(existing_langs), langs=existing_langs)
)
for lang in self.parameters.translation_languages:
if lang not in existing_langs:
print('creating missing language: {}'.format(lang))
self._t.create_language(self.parameters.transifex_project, lang, [self.parameters.transifex_coordinator])
existing_langs.append(lang)
for lang in existing_langs:
ts_file = '{dir}/i18n/{res}_{lan}.ts'.format(dir=self.parameters.plugin_path,
res=self.parameters.transifex_resource,
lan=lang)
print('downloading translation file: {}'.format(ts_file))
self._t.get_translation(self.parameters.transifex_project, resource['slug'], lang, ts_file)
def push(self):
resource = self.__get_resource()
print('pushing resource: {} with file {}'.format(self.parameters.transifex_resource, self.ts_file))
result = self._t.update_source_translation(
project_slug=self.parameters.transifex_project,
resource_slug=resource['slug'],
path_to_file=self.ts_file)
print('done: {}'.format(result))
def __get_resource(self) -> dict:
resources = self._t.list_resources(self.parameters.transifex_project)
if len(resources) == 0:
raise TransifexNoResource("project '{}' has no resource on Transifex".format(self.parameters.transifex_project))
if len(resources) > 1:
for resource in resources:
if resource['name'] == self.parameters.transifex_resource:
return resource
raise TransifexManyResources("project '{p}' has several resources on Transifex "
"and none is named as the project slug."
"Specify one in the parameters with transifex_resource."
"These resources have been found: {r}"
.format(p=self.parameters.transifex_project,
r=', '.join([r['name'] for r in resources])))
return resources[0]