-
Notifications
You must be signed in to change notification settings - Fork 1
/
update_translations.py
197 lines (159 loc) · 7.58 KB
/
update_translations.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
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
import subprocess
import os
import xml.etree.ElementTree as ET
import utils as util
import re
import sys
# name of the master hq translations file to be updated
hq_translations_subdir = "historical-translations-by-version"
unversioned_translations_filename = 'messages_en-2.txt'
# relative path to the subfolder within the javarosa repo containing the
# messages_default.txt file
javarosa_subfolder = './javarosa/j2me/shared-resources/resources'
# relative path to the subfolder within the commcare repo containing the
# messages_cc_default.txt file
commcare_subfolder = './application/resources'
# relative path to the subfolder within the commcare-odk repo containing the
# messages_ccodk_default.txt file
ccodk_messages_subfolder = './app/assets/locales'
# relative path to the subfolder within the commcare-odk repo containing the
# strings.xml file
ccodk_strings_subfolder = './app/res/values'
j2me_repo = 'commcare-j2me'
commcare_core_repo = 'commcare-core'
commcare_android_repo = 'commcare-android'
translations_repo = 'commcare-translations'
javarosa_filename = 'messages_default.txt'
commcare_filename = 'messages_cc_default.txt'
ccodk_messages_filename = 'android_translatable_strings.txt'
ccodk_strings_filename = 'strings.xml'
#all_filenames = [javarosa_filename, commcare_filename,
# ccodk_messages_filename, ccodk_strings_filename]
all_filenames = [ccodk_messages_filename, ccodk_strings_filename]
all_repos = [commcare_core_repo,
commcare_android_repo, translations_repo]
namespace = '{http://strings_namespace}'
github_url = 'https://github.com/dimagi/commcare-translations/compare/'
def update_translations(new_version_number):
if util.unstaged_changes_present(all_repos):
raise Exception("One of your repositories has un-staged changes, " +
"please stash them and try again")
# TODO PLM: run this on J2ME releases:
# new_javarosa_text = get_updated_translations(j2me_repo,
# javarosa_subfolder,
# javarosa_filename)
# new_commcare_text = get_updated_translations(j2me_repo,
# commcare_subfolder,
# commcare_filename)
new_ccodk_text = get_updated_translations(commcare_android_repo,
ccodk_messages_subfolder,
ccodk_messages_filename)
new_strings_text = get_updated_strings_block()
new_text_blocks = [
new_ccodk_text, new_strings_text,
# new_javarosa_text, new_commcare_text,
]
new_branch_name = checkout_new_translations_branch(new_version_number)
new_file_name = create_updated_translations_file(new_text_blocks, new_version_number)
commit_and_push_new_branch(new_version_number, new_branch_name, new_file_name)
def checkout_new_translations_branch(new_version_number):
util.chdir_repo(translations_repo)
subprocess.call('git checkout master', shell=True)
subprocess.call('git pull origin master', shell=True)
new_branch_name = '{}_release_additions'.format(new_version_number)
subprocess.call('git checkout -b {}'.format(new_branch_name), shell=True)
return new_branch_name
def create_updated_translations_file(new_text_blocks, new_version_number):
versioned_filename = '{}/{}-{}'.format(hq_translations_subdir,new_version_number, unversioned_translations_filename)
"""
Write all of the updated text blocks from the 4 mobile translations files
to a new translations file for this version, with headers for each section
"""
header_prefix = '# *** '
header_suffix = ' ***'
with open(versioned_filename, 'w', encoding='utf-8') as f:
os.utime(versioned_filename, None)
num_blocks = len(all_filenames)
for i in range(num_blocks):
f.write(header_prefix + all_filenames[i] + header_suffix + '\n\n')
f.write(new_text_blocks[i])
if i < num_blocks-1:
f.write('\n\n')
# Create a simlink so that the unversioned file is equivalent to the latest versioned one
os.remove(unversioned_translations_filename)
os.symlink(versioned_filename, unversioned_translations_filename)
return versioned_filename
def commit_and_push_new_branch(new_version_number, new_branch, new_file_name):
subprocess.call('git add {}'.format(new_file_name), shell=True)
subprocess.call('git add {}'.format(unversioned_translations_filename), shell=True)
commit_message = ('Auto-commit: Update translations for ' +
'CommCare release {}').format(new_version_number)
subprocess.call("git commit -m '{}'".format(commit_message),
shell=True)
subprocess.call('git push origin {}'.format(new_branch), shell=True)
pr_url = '{}{}'.format(github_url, new_branch)
print(('An updated translations file has been pushed to GitHub ' +
'as branch {0}. To create a PR out of this ' +
'branch, you can go directly to {1}').format(new_branch, pr_url))
def get_updated_translations(repo, relative_path, filename):
"""
Return a string containing the updated text that should go into the master
hq translations file from the given file
"""
util.chdir_repo(repo)
os.chdir(relative_path)
with open(filename, 'r', encoding='utf-8') as f:
return f.read().strip()
def get_updated_strings_block():
"""
Return a string containing the updated text that should go into the master
hq translations file from the strings.xml file in the mobile codebase.
Because it is an xml file instead of a plain text file, the extraction
needs to be done in a different way from all of the other files
"""
util.chdir_repo(commcare_android_repo)
subprocess.call('git checkout master', shell=True)
os.chdir(ccodk_strings_subfolder)
tree = ET.parse(ccodk_strings_filename)
resources = tree.getroot()
string_list = []
for string in resources.findall('string'):
translatable_value = string.get('{}translatable'.format(namespace))
if translatable_value == 'true':
name = string.get('name')
value = string.text
if name is not None and value is not None:
name_with_prefix = 'odk_{}'.format(name)
value = unescape_quotes(replace_string_format_syntax(value))
string_list.append(name_with_prefix + '=' + value + '\n')
return "".join(string_list)
def replace_string_format_syntax(value):
return re.sub(r'%(\d+\$)?s', replace_helper, value)
def replace_helper(match_obj):
text = match_obj.group()
if len(text) == 2:
# This was just '%s', so want to use 0 as the index
new_index = 0
else:
# Otherwise, there is some number sitting in between '%' and '$s'
index = text[1:-2]
# Decrement this by 1 because HQ's indexing starts at 0 and ours starts
# at 1
new_index = int(index) - 1
return '${' + str(new_index) + '}'
def unescape_quotes(text):
text = re.sub(r'\\"', '"', text)
text = re.sub(r"\\'", "'", text)
return text
# for running this script independently of the rest of the deploy scripts
def main():
if len(sys.argv) > 2:
filename = sys.argv[0]
arg_count = len(sys.argv) - 1
print("{} only accepts one argument, {} provided".format(filename,
arg_count))
sys.exit(0)
version_string = sys.argv[1]
update_translations(version_string)
if __name__ == "__main__":
main()