Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: localeTools.py

Issue 29556601: Issue 5777 - Update crowdin interface (Closed)
Patch Set: Addressed Vasily's comments Created Sept. 28, 2017, 3:52 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: localeTools.py
diff --git a/localeTools.py b/localeTools.py
index 140f22c1f7bb8298ce12bf7c1d4547a47de346a4..92d7a87bf793d39c1868c3cc696a952f1ee7a904 100644
--- a/localeTools.py
+++ b/localeTools.py
@@ -7,6 +7,7 @@ import os
import sys
import codecs
import json
+import urlparse
import urllib
import urllib2
from StringIO import StringIO
@@ -92,6 +93,45 @@ chromeLocales = [
'zh-TW',
]
+CROWDIN_AP_URL = 'https://api.crowdin.com/api/project/{}/{}'
+
+
+def crowdin_url(project_name, action, key, get={}):
+ """Create a valid url for a crowdin endpoint."""
+ url = CROWDIN_AP_URL.format(project_name, action)
+ get['key'] = key
+ get['json'] = 1
+
+ scheme, netloc, path, params, query, fragment = urlparse.urlparse(url)
+
+ query = urlparse.parse_qs(query)
+ query.update(get)
+
+ return urlparse.urlunparse((
+ scheme, netloc, path, params, urllib.urlencode(query), fragment
+ ))
+
+
+def crowdin_request(project_name, action, key, get={}, post_data=None,
+ headers={}, raw=False):
+ """Perform a call to crowdin and raise an Exception on failure."""
+ request = urllib2.Request(
+ crowdin_url(project_name, action, key, get),
+ post_data,
+ headers,
+ )
+
+ try:
+ result = urllib2.urlopen(request).read()
+ except urllib2.HTTPError as e:
+ raise Exception('Server returned HTTP Error {}:\n{}'.format(e.code,
+ e.read()))
+
+ if not raw:
+ return json.loads(result)
+
+ return result
+
class OrderedDict(dict):
def __init__(self):
@@ -297,23 +337,22 @@ def setupTranslations(localeConfig, projectName, key):
locales.add(mapLocale('BCP-47', match2.group(1)))
allowed = set()
- allowedLocales = json.load(urllib2.urlopen(
- 'https://crowdin.com/languages/languages_list?callback='
- ))
+ allowedLocales = crowdin_request(projectName, 'supported-languages', key)
+
for locale in allowedLocales:
- allowed.add(locale['code'])
+ allowed.add(locale['crowdin_code'])
if not allowed.issuperset(locales):
print "Warning, following locales aren't allowed by server: " + ', '.join(locales - allowed)
locales = list(locales & allowed)
locales.sort()
params = urllib.urlencode([('languages[]', locale) for locale in locales])
- result = urllib2.urlopen('http://api.crowdin.net/api/project/%s/edit-project?key=%s' % (projectName, key), params).read()
- if result.find('<success') < 0:
- raise Exception('Server indicated that the operation was not successful\n' + result)
+ crowdin_request(projectName, 'edit-project', key, post_data=params)
-def postFiles(files, url):
+
+def crowdin_prepare_upload(files):
+ """Create a post body and matching headers, which Crowdin can handle."""
boundary = '----------ThIs_Is_tHe_bouNdaRY_$'
body = ''
for file, data in files:
@@ -325,16 +364,18 @@ def postFiles(files, url):
body += '--%s--\r\n' % boundary
body = body.encode('utf-8')
- request = urllib2.Request(url, StringIO(body))
- request.add_header('Content-Type', 'multipart/form-data; boundary=%s' % boundary)
- request.add_header('Content-Length', len(body))
- result = urllib2.urlopen(request).read()
- if result.find('<success') < 0:
- raise Exception('Server indicated that the operation was not successful\n' + result)
+ return (
+ StringIO(body),
+ {
+ 'Content-Type': ('multipart/form-data; ; charset=utf-8; '
Sebastian Noack 2017/09/28 20:25:21 This seems incorrect, multipart/form-data doesn't
+ 'boundary=' + boundary),
+ 'Content-Length': len(body)
+ }
+ )
def updateTranslationMaster(localeConfig, metadata, dir, projectName, key):
- result = json.load(urllib2.urlopen('http://api.crowdin.net/api/project/%s/info?key=%s&json=1' % (projectName, key)))
+ result = crowdin_request(projectName, 'info', key)
existing = set(map(lambda f: f['name'], result['files']))
add = []
@@ -362,14 +403,18 @@ def updateTranslationMaster(localeConfig, metadata, dir, projectName, key):
add.append((newName, data))
if len(add):
- titles = urllib.urlencode([('titles[%s]' % name, re.sub(r'\.json', '', name)) for name, data in add])
- postFiles(add, 'http://api.crowdin.net/api/project/%s/add-file?key=%s&type=chrome&%s' % (projectName, key, titles))
+ data = {'titles[{}]'.format(name): re.sub(r'\.json', '', name)
+ for name, data in add}
+ data['type'] = 'chrome'
+ data, headers = crowdin_prepare_upload(add)
+ crowdin_request(projectName, 'add-file', key, post_data=data,
+ headers=headers)
if len(update):
- postFiles(update, 'http://api.crowdin.net/api/project/%s/update-file?key=%s' % (projectName, key))
+ data, headers = crowdin_prepare_upload(update)
+ crowdin_request(projectName, 'update-file', key, post_data=data,
+ headers=headers)
for file in existing:
- result = urllib2.urlopen('http://api.crowdin.net/api/project/%s/delete-file?key=%s&file=%s' % (projectName, key, file)).read()
- if result.find('<success') < 0:
- raise Exception('Server indicated that the operation was not successful\n' + result)
+ crowdin_request(projectName, 'delete-file', key, {'file': file})
def uploadTranslations(localeConfig, metadata, dir, locale, projectName, key):
@@ -392,17 +437,22 @@ def uploadTranslations(localeConfig, metadata, dir, locale, projectName, key):
if data:
files.append((newName, data))
if len(files):
- postFiles(files, 'http://api.crowdin.net/api/project/%s/upload-translation?key=%s&language=%s' % (
- projectName, key, mapLocale(localeConfig['name_format'], locale))
- )
+ language = mapLocale(localeConfig['name_format'], locale)
+ data, headers = crowdin_prepare_upload(files)
+ crowdin_request(projectName, 'upload-translation', key,
+ {'language': language}, post_data=data,
+ headers=headers)
def getTranslations(localeConfig, projectName, key):
- result = urllib2.urlopen('http://api.crowdin.net/api/project/%s/export?key=%s' % (projectName, key)).read()
- if result.find('<success') < 0:
- raise Exception('Server indicated that the operation was not successful\n' + result)
+ """Download all available translations from crowdin.
+
+ Trigger crowdin to build the available export, wait for crowdin to
+ finish the job and download the generated zip afterwards.
+ """
+ crowdin_request(projectName, 'export', key)
- result = urllib2.urlopen('http://api.crowdin.net/api/project/%s/download/all.zip?key=%s' % (projectName, key)).read()
+ result = crowdin_request(projectName, 'download/all.zip', key, raw=True)
zip = ZipFile(StringIO(result))
dirs = {}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld