Merge lp:~raoul-snyman/openlp/ios-remote-i18n-script into lp:~danielborges93/openlp/ios-remote

Proposed by Raoul Snyman
Status: Merged
Approved by: Daniel Borges
Approved revision: 61
Merged at revision: 60
Proposed branch: lp:~raoul-snyman/openlp/ios-remote-i18n-script
Merge into: lp:~danielborges93/openlp/ios-remote
Diff against target: 216 lines (+187/-0)
1 file modified
scripts/translation_utils.py (+187/-0)
To merge this branch: bzr merge lp:~raoul-snyman/openlp/ios-remote-i18n-script
Reviewer Review Type Date Requested Status
Daniel Borges Approve
Review via email: mp+317800@code.launchpad.net

This proposal supersedes a proposal from 2017-02-20.

Description of the change

Add a script to help with translation files. This script needs Python 3 to work.

To run the script, you need to open a terminal and go to the "scripts" directory. Then run it like this:

 $ /path/to/python3 translation_utils.py

If you want to know which arguments there are, run the script with the --help option (shorthand is -h):

 $ python3 translation_utils.py --help

To only download and use 100% complete translations, use the --only-complete option (shorthand is -c):

 $ python3 translation_utls.py --only-complete

To post a comment you must log in.
Revision history for this message
Daniel Borges (danielborges93) wrote :

Xcode system uses a hyphen to identify regional languages, like pt-BR. The script downloads the languages using an underscore, like pt_BR.

review: Needs Fixing
Revision history for this message
Daniel Borges (danielborges93) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'Remote/Resources/Settings.bundle/es.lproj'
2=== added file 'Remote/Resources/Settings.bundle/es.lproj/Root.strings'
3Binary files Remote/Resources/Settings.bundle/es.lproj/Root.strings 1970-01-01 00:00:00 +0000 and Remote/Resources/Settings.bundle/es.lproj/Root.strings 2017-02-20 19:47:03 +0000 differ
4=== added directory 'Remote/Resources/Settings.bundle/hu.lproj'
5=== added file 'Remote/Resources/Settings.bundle/hu.lproj/Root.strings'
6Binary files Remote/Resources/Settings.bundle/hu.lproj/Root.strings 1970-01-01 00:00:00 +0000 and Remote/Resources/Settings.bundle/hu.lproj/Root.strings 2017-02-20 19:47:03 +0000 differ
7=== added directory 'Remote/Resources/Settings.bundle/lt.lproj'
8=== added file 'Remote/Resources/Settings.bundle/lt.lproj/Root.strings'
9Binary files Remote/Resources/Settings.bundle/lt.lproj/Root.strings 1970-01-01 00:00:00 +0000 and Remote/Resources/Settings.bundle/lt.lproj/Root.strings 2017-02-20 19:47:03 +0000 differ
10=== added directory 'Remote/Resources/Settings.bundle/nb.lproj'
11=== added file 'Remote/Resources/Settings.bundle/nb.lproj/Root.strings'
12Binary files Remote/Resources/Settings.bundle/nb.lproj/Root.strings 1970-01-01 00:00:00 +0000 and Remote/Resources/Settings.bundle/nb.lproj/Root.strings 2017-02-20 19:47:03 +0000 differ
13=== added directory 'Remote/Resources/es.lproj'
14=== added file 'Remote/Resources/es.lproj/Localizable.strings'
15Binary files Remote/Resources/es.lproj/Localizable.strings 1970-01-01 00:00:00 +0000 and Remote/Resources/es.lproj/Localizable.strings 2017-02-20 19:47:03 +0000 differ
16=== added directory 'Remote/Resources/hu.lproj'
17=== added file 'Remote/Resources/hu.lproj/Localizable.strings'
18Binary files Remote/Resources/hu.lproj/Localizable.strings 1970-01-01 00:00:00 +0000 and Remote/Resources/hu.lproj/Localizable.strings 2017-02-20 19:47:03 +0000 differ
19=== added directory 'Remote/Resources/lt.lproj'
20=== added file 'Remote/Resources/lt.lproj/Localizable.strings'
21Binary files Remote/Resources/lt.lproj/Localizable.strings 1970-01-01 00:00:00 +0000 and Remote/Resources/lt.lproj/Localizable.strings 2017-02-20 19:47:03 +0000 differ
22=== added directory 'Remote/Resources/nb.lproj'
23=== added file 'Remote/Resources/nb.lproj/Localizable.strings'
24Binary files Remote/Resources/nb.lproj/Localizable.strings 1970-01-01 00:00:00 +0000 and Remote/Resources/nb.lproj/Localizable.strings 2017-02-20 19:47:03 +0000 differ
25=== added directory 'scripts'
26=== added file 'scripts/translation_utils.py'
27--- scripts/translation_utils.py 1970-01-01 00:00:00 +0000
28+++ scripts/translation_utils.py 2017-02-20 19:47:03 +0000
29@@ -0,0 +1,187 @@
30+#!/usr/bin/env python3
31+# -*- coding: utf-8 -*-
32+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
33+
34+###############################################################################
35+# OpenLP - Open Source Lyrics Projection #
36+# --------------------------------------------------------------------------- #
37+# Copyright (c) 2008-2017 OpenLP Developers #
38+# --------------------------------------------------------------------------- #
39+# This program is free software; you can redistribute it and/or modify it #
40+# under the terms of the GNU General Public License as published by the Free #
41+# Software Foundation; version 2 of the License. #
42+# #
43+# This program is distributed in the hope that it will be useful, but WITHOUT #
44+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
45+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
46+# more details. #
47+# #
48+# You should have received a copy of the GNU General Public License along #
49+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
50+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
51+###############################################################################
52+
53+"""
54+This script is used to maintain the translation files in OpenLP. It downloads
55+the latest translation files from the Transifex translation server, updates the
56+local translation files from both the source code and the files from Transifex,
57+and can also generate the compiled translation files.
58+
59+Create New Language
60+-------------------
61+
62+To create a new language, simply run this script with the ``-c`` command line
63+option::
64+
65+ @:~$ ./translation_utils.py -c
66+
67+Update Translation Files
68+------------------------
69+
70+The best way to update the translations is to download the files from Transifex,
71+and then update the local files using both the downloaded files and the source.
72+This is done easily via the ``-d``, ``-p`` and ``-u`` options::
73+
74+ @:~$ ./translation_utils.py -dpu
75+
76+"""
77+from argparse import ArgumentParser
78+from getpass import getpass
79+import base64
80+import glob
81+import json
82+import os
83+import sys
84+import urllib.error
85+import urllib.parse
86+import urllib.request
87+import webbrowser
88+
89+SERVER_URL = 'http://www.transifex.com/api/2/project/openlp/resource/ios-remote-11/'
90+BASE_PATH = os.path.abspath(os.path.join('..', os.path.dirname(__file__)))
91+LANG_DIR = '{lang}.lproj'
92+LOCALIZED_PATH = os.path.join(BASE_PATH, 'Remote', 'Resources')
93+SETTINGS_PATH = os.path.join(LOCALIZED_PATH, 'Settings.bundle')
94+
95+
96+verbose_mode = False
97+quiet_mode = False
98+
99+
100+def print_quiet(text, linefeed=True):
101+ """
102+ This method checks to see if we are in quiet mode, and if not prints ``text`` out.
103+
104+ :param text: The text to print.
105+ :param linefeed: Linefeed required
106+ """
107+ global quiet_mode
108+ if not quiet_mode:
109+ if linefeed:
110+ print(text)
111+ else:
112+ print(text, end=' ')
113+
114+
115+def print_verbose(text):
116+ """
117+ This method checks to see if we are in verbose mode, and if so prints ``text`` out.
118+
119+ :param text: The text to print.
120+ """
121+ global verbose_mode, quiet_mode
122+ if not quiet_mode and verbose_mode:
123+ print(' %s' % text)
124+
125+
126+def extract_settings_strings(localized_file, language):
127+ """
128+ Extract the settings strings from Localized.strings and put them into Root.strings
129+ """
130+ print_verbose('Extracting settings for {lang}'.format(lang=language))
131+ file_path = os.path.join(SETTINGS_PATH, LANG_DIR.format(lang=language))
132+ if not os.path.exists(file_path):
133+ os.makedirs(file_path)
134+ settings_file = os.path.join(file_path, 'Root.strings')
135+ with open(localized_file, 'r', encoding='utf-16') as localized, open(settings_file, 'w', encoding='utf-16') as settings:
136+ for line in localized:
137+ if line.startswith('// Root.strings') or line.startswith('"settings.'):
138+ settings.write(line)
139+
140+
141+def download_translations(username, password, is_only_complete):
142+ """
143+ This method downloads the translation files from Transifex.
144+ """
145+ print_quiet('Download translation files from Transifex')
146+ if not username:
147+ username = input('Transifex username: ')
148+ if not password:
149+ password = getpass('Transifex password: ')
150+ # First get the list of languages
151+ base64string = base64.encodebytes(('%s:%s' % (username, password)).encode())[:-1]
152+ auth_header = 'Basic %s' % base64string.decode()
153+ request = urllib.request.Request(SERVER_URL + '?details')
154+ request.add_header('Authorization', auth_header)
155+ print_verbose('Downloading list of languages from: %s' % SERVER_URL)
156+ try:
157+ json_response = urllib.request.urlopen(request)
158+ except urllib.error.HTTPError:
159+ print_quiet('Username or password incorrect.')
160+ return False
161+ json_dict = json.loads(json_response.read().decode())
162+ languages = [lang['code'] for lang in json_dict['available_languages']]
163+ print_verbose('Languages: {}'.format(', '.join(languages)))
164+ for language in languages:
165+ if is_only_complete:
166+ stats_url = SERVER_URL + 'stats/{lang}/'.format(lang=language)
167+ request = urllib.request.Request(stats_url)
168+ request.add_header('Authorization', auth_header)
169+ response = urllib.request.urlopen(request)
170+ json_dict = json.loads(response.read().decode())
171+ print_verbose('Translation completion for {}: {}'.format(language, json_dict['completed']))
172+ if json_dict['completed'] != '100%':
173+ continue
174+ lang_url = SERVER_URL + 'translation/%s/?file' % language
175+ request = urllib.request.Request(lang_url)
176+ request.add_header('Authorization', auth_header)
177+ file_path = os.path.join(LOCALIZED_PATH, LANG_DIR.format(lang=language))
178+ if not os.path.exists(file_path):
179+ os.makedirs(file_path)
180+ filename = os.path.join(file_path, 'Localizable.strings')
181+ print_verbose('Get Translation File: %s' % filename)
182+ response = urllib.request.urlopen(request)
183+ with open(filename, 'wb') as localized_file:
184+ localized_file.write(response.read())
185+ extract_settings_strings(filename, language)
186+ print_quiet(' Done.')
187+
188+
189+def main():
190+ global verbose_mode, quiet_mode, username, password, if_complete
191+ # Set up command line options.
192+ parser = ArgumentParser()
193+ parser.add_argument('-u', '--username', dest='username', metavar='USERNAME',
194+ help='Transifex username, used for authentication')
195+ parser.add_argument('-p', '--password', dest='password', metavar='PASSWORD',
196+ help='Transifex password, used for authentication')
197+ parser.add_argument('-c', '--only-complete', dest='only_complete', action='store_true',
198+ help='only download translations that are complete')
199+ parser.add_argument('-v', '--verbose', dest='verbose', action='store_true',
200+ help='show extra information while processing translations')
201+ parser.add_argument('-q', '--quiet', dest='quiet', action='store_true',
202+ help='suppress all output other than errors')
203+ args = parser.parse_args()
204+ # Create and populate the command stack
205+ verbose_mode = args.verbose
206+ quiet_mode = args.quiet
207+ # Process the commands
208+ download_translations(args.username, args.password, args.only_complete)
209+
210+
211+if __name__ == '__main__':
212+ if os.path.split(os.path.abspath('.'))[1] != 'scripts':
213+ print('You need to run this script from the scripts directory.')
214+ else:
215+ if not main():
216+ sys.exit(1)

Subscribers

People subscribed via source and target branches