-
-
Notifications
You must be signed in to change notification settings - Fork 25
Expand file tree
/
Copy pathcreate_strings.py
More file actions
204 lines (166 loc) · 6.42 KB
/
Copy pathcreate_strings.py
File metadata and controls
204 lines (166 loc) · 6.42 KB
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
"""
Tooling for generating i18n strings using Kolibri's translation machinery.
"""
import json
import os
import tempfile
import xml.etree.ElementTree as ET
from importlib import resources
from version import apk_version
# By default we will map the locale code to e.g. "en-us" to "en-rUS"
# except for mapping specified below.
locale_code_map = {
"es-419": "b+es+419",
"zh-hans": "zh",
}
XML_TEMPLATE = """
<resources>
<string name="loading_page_html" formatted="false"><![CDATA[
{}
]]></string>
</resources>
"""
# The language code that will be used for the non-prefixed values folder
DEFAULT_LANGUAGE = "en"
def generate_loading_pages(output_dir):
"""
Run the Django management command to generate the loading pages.
"""
# Add the local Kolibri source directory to the path
from kolibri.main import initialize
from django.core.management import call_command
initialize(skip_update=True)
call_command(
"loadingpage",
"--output-dir",
output_dir,
"--version-text",
apk_version().replace("-official", ""),
)
def _find_string(lang, string):
from kolibri.main import initialize
from django.utils.translation import override
from django.utils.translation import gettext as _
from django.utils.translation import to_locale
initialize(skip_update=True)
with override(lang):
new_string = _(string)
if new_string != string and new_string:
return new_string
for message_file in os.listdir(
resources.files("kolibri") / "locale" / "en" / "LC_MESSAGES"
):
if message_file.endswith(".json"):
with open(
resources.files("kolibri")
/ "locale"
/ "en"
/ "LC_MESSAGES"
/ message_file,
"r",
) as f:
messages = json.load(f)
for key, value in messages.items():
if value == string:
try:
# Do this in case we have a legacy translation file - this should be cleaned up
# in a future version of Kolibri
with open(
resources.files("kolibri")
/ "locale"
/ to_locale(lang)
/ "LC_MESSAGES"
/ message_file,
"r",
) as lang_message_file:
messages = json.load(lang_message_file)
new_string = messages[key]
if new_string != string and new_string:
return new_string
# If we have a translation but the string is no different in translation, it means we should
# not include it in the strings.xml file
return None
except FileNotFoundError:
break
return None
# Strings that we only access from Python, so we don't need to include them in the strings.xml file
PYTHON_ONLY_STRINGS = [
"Learner",
]
def create_resource_files(output_dir): # noqa: C901
"""
Read each language directory and create resource files in the corresponding Android values folder.
"""
en_strings_file = os.path.join(
os.path.dirname(__file__),
"../python-for-android/dists/kolibri/src/main/res/values/strings.xml",
)
en_strings_tree = ET.parse(en_strings_file)
en_strings_root = en_strings_tree.getroot()
all_langs = list(os.listdir(output_dir))
for lang_dir in all_langs:
if lang_dir == DEFAULT_LANGUAGE:
dir_name = "values"
else:
if lang_dir in locale_code_map:
locale_dir = locale_code_map[lang_dir]
else:
parts = lang_dir.split("-")
if len(parts) == 1:
locale_dir = lang_dir
elif len(parts) == 2:
locale_dir = f"{parts[0]}-r{parts[1].upper()}"
else:
raise ValueError(f"Invalid language code: {lang_dir}")
dir_name = f"values-{locale_dir}"
values_dir = os.path.join(
os.path.dirname(__file__),
"../python-for-android/dists/kolibri/src/main/res",
dir_name,
)
os.makedirs(values_dir, exist_ok=True)
with open(os.path.join(output_dir, lang_dir, "loading.html"), "r") as f:
html_content = f.read().replace("'", "\\'").replace('"', '\\"')
xml_content = XML_TEMPLATE.format(html_content)
with open(os.path.join(values_dir, "html_content.xml"), "w") as f:
f.write(xml_content)
if lang_dir == DEFAULT_LANGUAGE:
continue
new_root = ET.Element("resources")
new_tree = ET.ElementTree(element=new_root)
for string in en_strings_root.findall("string"):
name = string.get("name")
value = _find_string(lang_dir, string.text)
if value is None:
continue
new_string = ET.SubElement(new_root, "string", attrib={"name": name})
new_string.text = value
new_tree.write(
os.path.join(values_dir, "strings.xml"),
encoding="utf-8",
xml_declaration=True,
)
# Create the Python strings file
output = "# This file is auto-generated by the create_strings.py script. Do not edit it directly."
output += "\ni18n_strings = {"
for python_string in PYTHON_ONLY_STRINGS:
output += "\n " + f"'{python_string}': " + "{"
for lang_dir in all_langs:
value = _find_string(lang_dir, python_string)
if value is None:
continue
output += f"\n '{lang_dir}': '{value}', "
output += "\n },"
output += "\n}\n"
with open(os.path.join(os.path.dirname(__file__), "../src/strings.py"), "w") as f:
f.write(output)
def main():
"""
Run the script to generate the loading pages and create the Android resource files.
"""
with tempfile.TemporaryDirectory() as temp_dir:
generate_loading_pages(temp_dir)
create_resource_files(temp_dir)
if __name__ == "__main__":
# Actually run the script
main()