Skip to content

Commit c4d1402

Browse files
committed
upgrade translation fetcher to transifex API v3
see https://www.transifex.com/blog/2020/transifex-api-version-3/
1 parent 3d63811 commit c4d1402

File tree

4 files changed

+86
-91
lines changed

4 files changed

+86
-91
lines changed

dist/locales/br.min.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

dist/locales/index.min.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"af":{"rtl":false,"pct":0.04},"ak":{"rtl":false,"pct":0},"am":{"rtl":false,"pct":0},"ar":{"rtl":true,"pct":1},"ar-AA":{"rtl":true,"pct":0.01},"as":{"rtl":false,"pct":0},"ast":{"rtl":false,"pct":0.14},"ay":{"rtl":false,"pct":0},"az":{"rtl":false,"pct":0},"ba":{"rtl":false,"pct":0},"be":{"rtl":false,"pct":0.19},"bg":{"rtl":false,"pct":0.42},"bn":{"rtl":false,"pct":0.06},"bo":{"rtl":false,"pct":0},"br":{"rtl":false,"pct":0.57},"bs":{"rtl":false,"pct":0.02},"ca":{"rtl":false,"pct":0.51},"ckb":{"rtl":true,"pct":0.04},"cs":{"rtl":false,"pct":1},"cv":{"rtl":false,"pct":0},"cy":{"rtl":false,"pct":0.02},"da":{"rtl":false,"pct":0.46},"de":{"rtl":false,"pct":1},"de-AT":{"rtl":false,"pct":0},"de-CH":{"rtl":false,"pct":0},"dv":{"rtl":true,"pct":0.01},"ee":{"rtl":false,"pct":0},"el":{"rtl":false,"pct":0.34},"en":{"rtl":false,"pct":1},"en-AU":{"rtl":false,"pct":0},"en-CA":{"rtl":false,"pct":0},"en-GB":{"rtl":false,"pct":0.22},"en-IE":{"rtl":false,"pct":0},"en-IN":{"rtl":false,"pct":0},"en-NZ":{"rtl":false,"pct":0},"en-US":{"rtl":false,"pct":1},"eo":{"rtl":false,"pct":0.69},"es":{"rtl":false,"pct":1},"et":{"rtl":false,"pct":0.18},"eu":{"rtl":false,"pct":0.05},"fa":{"rtl":true,"pct":0.56},"fa-IR":{"rtl":true,"pct":0},"ff":{"rtl":false,"pct":0},"fi":{"rtl":false,"pct":0.38},"fil":{"rtl":false,"pct":0},"fr":{"rtl":false,"pct":0.99},"fr-FR":{"rtl":false,"pct":0.09},"fy":{"rtl":false,"pct":0.01},"ga":{"rtl":false,"pct":0},"gan":{"rtl":false,"pct":0},"gl":{"rtl":false,"pct":0.56},"grt":{"rtl":false,"pct":0},"gu":{"rtl":false,"pct":0.01},"ha":{"rtl":false,"pct":0},"he":{"rtl":true,"pct":0.66},"he-IL":{"rtl":true,"pct":0},"hi":{"rtl":false,"pct":0.01},"hr":{"rtl":false,"pct":0.16},"hu":{"rtl":false,"pct":0.93},"hy":{"rtl":false,"pct":0.03},"ia":{"rtl":false,"pct":0},"id":{"rtl":false,"pct":0.07},"ig":{"rtl":false,"pct":0},"is":{"rtl":false,"pct":0.31},"it":{"rtl":false,"pct":0.59},"ja":{"rtl":false,"pct":0.99},"jam":{"rtl":false,"pct":0},"jv":{"rtl":false,"pct":0},"ka":{"rtl":false,"pct":0},"kbd":{"rtl":false,"pct":0},"kha":{"rtl":false,"pct":0},"ki":{"rtl":false,"pct":0},"kk":{"rtl":false,"pct":0},"km":{"rtl":false,"pct":0.01},"kn":{"rtl":false,"pct":0.06},"ko":{"rtl":false,"pct":0.37},"ks":{"rtl":false,"pct":0},"ku":{"rtl":false,"pct":0},"ky":{"rtl":false,"pct":0},"lb":{"rtl":false,"pct":0.17},"lg":{"rtl":false,"pct":0},"lij":{"rtl":false,"pct":0},"ln":{"rtl":false,"pct":0},"lo":{"rtl":false,"pct":0},"lt":{"rtl":false,"pct":0.14},"lus":{"rtl":false,"pct":0},"lv":{"rtl":false,"pct":0.24},"mg":{"rtl":false,"pct":0.06},"mi":{"rtl":false,"pct":0},"mk":{"rtl":false,"pct":0.37},"ml":{"rtl":false,"pct":0.01},"mn":{"rtl":false,"pct":0},"mr":{"rtl":false,"pct":0},"ms":{"rtl":false,"pct":0.12},"my":{"rtl":false,"pct":0},"nb":{"rtl":false,"pct":0},"nd":{"rtl":false,"pct":0},"ne":{"rtl":false,"pct":0.01},"nl":{"rtl":false,"pct":0.72},"nl-BE":{"rtl":false,"pct":0},"nl-NL":{"rtl":false,"pct":0},"nn":{"rtl":false,"pct":0.02},"no":{"rtl":false,"pct":0.48},"nr":{"rtl":false,"pct":0},"nso":{"rtl":false,"pct":0},"nv":{"rtl":false,"pct":0},"ny":{"rtl":false,"pct":0},"oc":{"rtl":false,"pct":0},"om":{"rtl":false,"pct":0},"or":{"rtl":false,"pct":0},"pa":{"rtl":false,"pct":0},"pa-PK":{"rtl":true,"pct":0.12},"pap":{"rtl":false,"pct":0},"pl":{"rtl":false,"pct":0.75},"ps":{"rtl":true,"pct":0},"pt":{"rtl":false,"pct":0.62},"pt-BR":{"rtl":false,"pct":0.56},"qu":{"rtl":false,"pct":0},"rm":{"rtl":false,"pct":0},"ro":{"rtl":false,"pct":0.12},"ru":{"rtl":false,"pct":0.48},"rw":{"rtl":false,"pct":0},"sat":{"rtl":false,"pct":0.03},"sc":{"rtl":false,"pct":0},"sd":{"rtl":false,"pct":0},"sg":{"rtl":false,"pct":0},"si":{"rtl":false,"pct":0.02},"sk":{"rtl":false,"pct":0.54},"sl":{"rtl":false,"pct":0.15},"sm":{"rtl":false,"pct":0},"sn":{"rtl":false,"pct":0},"so":{"rtl":false,"pct":0.01},"sq":{"rtl":false,"pct":0.07},"sr":{"rtl":false,"pct":0.36},"ss":{"rtl":false,"pct":0},"st":{"rtl":false,"pct":0},"su":{"rtl":false,"pct":0},"sv":{"rtl":false,"pct":0.9},"sw":{"rtl":false,"pct":0},"ta":{"rtl":false,"pct":0.08},"te":{"rtl":false,"pct":0.02},"tg":{"rtl":false,"pct":0},"th":{"rtl":false,"pct":0.01},"ti":{"rtl":false,"pct":0},"tk":{"rtl":false,"pct":0},"tl":{"rtl":false,"pct":0.03},"tn":{"rtl":false,"pct":0},"tr":{"rtl":false,"pct":0.66},"ts":{"rtl":false,"pct":0},"tt":{"rtl":false,"pct":0},"tum":{"rtl":false,"pct":0},"ug":{"rtl":true,"pct":0},"uk":{"rtl":false,"pct":1},"ur":{"rtl":true,"pct":0.05},"uz":{"rtl":false,"pct":0},"ve":{"rtl":false,"pct":0},"vi":{"rtl":false,"pct":0.86},"wo":{"rtl":false,"pct":0},"xh":{"rtl":false,"pct":0},"yo":{"rtl":false,"pct":0},"yue":{"rtl":false,"pct":0.1},"zh":{"rtl":false,"pct":0.02},"zh-CN":{"rtl":false,"pct":0.74},"zh-HK":{"rtl":false,"pct":0.31},"zh-TW":{"rtl":false,"pct":0.91},"zu":{"rtl":false,"pct":0}}
1+
{"af":{"rtl":false,"pct":0.22},"ak":{"rtl":false,"pct":0},"am":{"rtl":false,"pct":0.02},"ar":{"rtl":true,"pct":0.93},"ar-AA":{"rtl":true,"pct":0},"as":{"rtl":false,"pct":0},"ast":{"rtl":false,"pct":0.27},"ay":{"rtl":false,"pct":0},"az":{"rtl":false,"pct":0},"ba":{"rtl":false,"pct":0},"be":{"rtl":false,"pct":0},"bg":{"rtl":false,"pct":0.22},"bn":{"rtl":false,"pct":0.05},"bo":{"rtl":false,"pct":0},"br":{"rtl":false,"pct":0.35},"bs":{"rtl":false,"pct":0.14},"ca":{"rtl":false,"pct":0.63},"ckb":{"rtl":true,"pct":0.05},"cs":{"rtl":false,"pct":0.98},"cv":{"rtl":false,"pct":0},"cy":{"rtl":false,"pct":0.01},"da":{"rtl":false,"pct":0.61},"de":{"rtl":false,"pct":1},"de-AT":{"rtl":false,"pct":0},"de-CH":{"rtl":false,"pct":0},"dv":{"rtl":true,"pct":0.02},"ee":{"rtl":false,"pct":0},"el":{"rtl":false,"pct":0.67},"en":{"rtl":false,"pct":1},"en-AU":{"rtl":false,"pct":0.02},"en-CA":{"rtl":false,"pct":0.04},"en-GB":{"rtl":false,"pct":0.31},"en-IE":{"rtl":false,"pct":0},"en-IN":{"rtl":false,"pct":0},"en-NZ":{"rtl":false,"pct":0.02},"en-US":{"rtl":false,"pct":1},"eo":{"rtl":false,"pct":0.87},"es":{"rtl":false,"pct":0.99},"et":{"rtl":false,"pct":0.37},"eu":{"rtl":false,"pct":0.17},"fa":{"rtl":true,"pct":0.74},"fa-IR":{"rtl":true,"pct":0},"ff":{"rtl":false,"pct":0},"fi":{"rtl":false,"pct":0.62},"fil":{"rtl":false,"pct":0},"fr":{"rtl":false,"pct":0.98},"fr-FR":{"rtl":false,"pct":0},"fy":{"rtl":false,"pct":0.02},"ga":{"rtl":false,"pct":0},"gan":{"rtl":false,"pct":0},"gl":{"rtl":false,"pct":0.61},"grt":{"rtl":false,"pct":0},"gu":{"rtl":false,"pct":0},"ha":{"rtl":false,"pct":0},"he":{"rtl":true,"pct":0.82},"he-IL":{"rtl":true,"pct":0},"hi":{"rtl":false,"pct":0.02},"hr":{"rtl":false,"pct":0.34},"hu":{"rtl":false,"pct":0.81},"hy":{"rtl":false,"pct":0.03},"ia":{"rtl":false,"pct":0},"id":{"rtl":false,"pct":0.24},"ig":{"rtl":false,"pct":0},"is":{"rtl":false,"pct":0.34},"it":{"rtl":false,"pct":0.78},"ja":{"rtl":false,"pct":0.86},"jam":{"rtl":false,"pct":0},"jv":{"rtl":false,"pct":0},"ka":{"rtl":false,"pct":0},"kbd":{"rtl":false,"pct":0},"kha":{"rtl":false,"pct":0},"ki":{"rtl":false,"pct":0},"kk":{"rtl":false,"pct":0},"km":{"rtl":false,"pct":0},"kn":{"rtl":false,"pct":0.08},"ko":{"rtl":false,"pct":0.63},"ks":{"rtl":false,"pct":0},"ku":{"rtl":false,"pct":0.01},"ky":{"rtl":false,"pct":0},"lb":{"rtl":false,"pct":0},"lg":{"rtl":false,"pct":0},"lij":{"rtl":false,"pct":0},"ln":{"rtl":false,"pct":0},"lo":{"rtl":false,"pct":0},"lt":{"rtl":false,"pct":0.29},"lus":{"rtl":false,"pct":0},"lv":{"rtl":false,"pct":0.22},"mg":{"rtl":false,"pct":0},"mi":{"rtl":false,"pct":0},"mk":{"rtl":false,"pct":0.99},"ml":{"rtl":false,"pct":0},"mn":{"rtl":false,"pct":0},"mr":{"rtl":false,"pct":0},"ms":{"rtl":false,"pct":0.14},"my":{"rtl":false,"pct":0},"nb":{"rtl":false,"pct":0},"nd":{"rtl":false,"pct":0},"ne":{"rtl":false,"pct":0.02},"nl":{"rtl":false,"pct":0.94},"nl-BE":{"rtl":false,"pct":0},"nl-NL":{"rtl":false,"pct":0},"nn":{"rtl":false,"pct":0.05},"no":{"rtl":false,"pct":0.72},"nr":{"rtl":false,"pct":0},"nso":{"rtl":false,"pct":0},"nv":{"rtl":false,"pct":0},"ny":{"rtl":false,"pct":0},"oc":{"rtl":false,"pct":0},"om":{"rtl":false,"pct":0},"or":{"rtl":false,"pct":0},"pa":{"rtl":false,"pct":0},"pa-PK":{"rtl":true,"pct":0.11},"pap":{"rtl":false,"pct":0},"pl":{"rtl":false,"pct":0.87},"ps":{"rtl":true,"pct":0},"pt":{"rtl":false,"pct":0.96},"pt-BR":{"rtl":false,"pct":0.85},"qu":{"rtl":false,"pct":0},"rm":{"rtl":false,"pct":0},"ro":{"rtl":false,"pct":0.28},"ru":{"rtl":false,"pct":0.61},"rw":{"rtl":false,"pct":0},"sat":{"rtl":false,"pct":0},"sc":{"rtl":false,"pct":0},"sd":{"rtl":false,"pct":0},"sg":{"rtl":false,"pct":0},"si":{"rtl":false,"pct":0},"sk":{"rtl":false,"pct":0.71},"sl":{"rtl":false,"pct":0.34},"sm":{"rtl":false,"pct":0},"sn":{"rtl":false,"pct":0},"so":{"rtl":false,"pct":0.04},"sq":{"rtl":false,"pct":0.02},"sr":{"rtl":false,"pct":0.39},"ss":{"rtl":false,"pct":0},"st":{"rtl":false,"pct":0},"su":{"rtl":false,"pct":0},"sv":{"rtl":false,"pct":0.88},"sw":{"rtl":false,"pct":0},"ta":{"rtl":false,"pct":0.24},"te":{"rtl":false,"pct":0.02},"tg":{"rtl":false,"pct":0},"th":{"rtl":false,"pct":0.21},"ti":{"rtl":false,"pct":0},"tk":{"rtl":false,"pct":0},"tl":{"rtl":false,"pct":0.04},"tn":{"rtl":false,"pct":0},"tr":{"rtl":false,"pct":0.8},"ts":{"rtl":false,"pct":0},"tt":{"rtl":false,"pct":0},"tum":{"rtl":false,"pct":0},"ug":{"rtl":true,"pct":0},"uk":{"rtl":false,"pct":0.99},"ur":{"rtl":true,"pct":0},"uz":{"rtl":false,"pct":0},"ve":{"rtl":false,"pct":0},"vi":{"rtl":false,"pct":0.86},"wo":{"rtl":false,"pct":0},"xh":{"rtl":false,"pct":0},"yo":{"rtl":false,"pct":0},"yue":{"rtl":false,"pct":0.28},"zh":{"rtl":false,"pct":0.06},"zh-CN":{"rtl":false,"pct":0.89},"zh-HK":{"rtl":false,"pct":0.57},"zh-TW":{"rtl":false,"pct":1},"zu":{"rtl":false,"pct":0}}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@
7676
"@ideditor/temaki": "~5.2.0",
7777
"@mapbox/maki": "^8.0.0",
7878
"@openstreetmap/id-tagging-schema": "^5.0.1",
79+
"@transifex/api": "^4.2.5",
7980
"autoprefixer": "^10.0.1",
80-
"btoa": "^1.2.1",
8181
"chai": "^4.3.4",
8282
"chalk": "^4.1.2",
8383
"cldr-core": "^41.0.0",

scripts/update_locales.js

Lines changed: 83 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -3,44 +3,31 @@
33
const chalk = require('chalk');
44
const fs = require('fs');
55
const fetch = require('node-fetch');
6-
const btoa = require('btoa');
76
const YAML = require('js-yaml');
7+
const transifexApi = require('@transifex/api').transifexApi;
88

99
const resourceIds = ['core', 'imagery', 'community'];
1010
const reviewedOnlyLangs = ['vi'];
1111
const outdir = 'dist/locales/';
12-
const apiroot = 'https://www.transifex.com/api/2';
13-
const projectURL = `${apiroot}/project/id-editor`;
1412

1513
const languageNames = require('./language_names.js');
1614

1715

1816
// Transifex doesn't allow anonymous downloading
19-
let auth;
20-
/* eslint-disable no-process-env */
2117
if (process.env.transifex_password) {
2218
// Deployment scripts may prefer environment variables
23-
auth = {
24-
user: process.env.transifex_user || 'api',
25-
password: process.env.transifex_password
26-
};
19+
/* eslint-disable no-process-env */
20+
transifexApi.setup({ auth: process.env.transifex_password });
21+
/* eslint-enable no-process-env */
2722
} else {
2823
// Credentials can be stored in transifex.auth as a json object. This file is gitignored.
29-
// You can use an API key instead of your password: https://docs.transifex.com/api/introduction#authentication
30-
// in which case for user parameter value should be: "api"
24+
// You must use an API key as your password: You can generate one at
25+
// https://www.transifex.com/user/settings/api/.
3126
// {
32-
// "user": "username",
33-
// "password": "password"
27+
// "password": "<api_key>"
3428
// }
35-
auth = JSON.parse(fs.readFileSync('./transifex.auth', 'utf8'));
29+
transifexApi.setup({ auth: JSON.parse(fs.readFileSync('./transifex.auth', 'utf8')).password });
3630
}
37-
/* eslint-enable no-process-env */
38-
39-
const fetchOpts = {
40-
headers: {
41-
'Authorization': 'Basic ' + btoa(auth.user + ':' + auth.password),
42-
}
43-
};
4431

4532
const dataShortcuts = JSON.parse(fs.readFileSync('data/shortcuts.json', 'utf8'));
4633

@@ -69,33 +56,36 @@ let coverageByLocaleCode = {};
6956
asyncMap(resourceIds, getResourceInfo, gotResourceInfo);
7057
asyncMap(resourceIds, getResource, gotResource);
7158

72-
function getResourceInfo(resourceId, callback) {
73-
let url = 'https://api.transifex.com/organizations/openstreetmap/projects/id-editor/resources/' + resourceId;
74-
fetch(url, fetchOpts)
75-
.then(res => {
76-
console.log(`${res.status}: ${url}`);
77-
return res.json();
78-
})
79-
.then(json => {
80-
callback(null, json);
81-
})
82-
.catch(err => callback(err));
59+
async function getResourceInfo(resourceId, callback) {
60+
try {
61+
const result = [];
62+
for await (const stat of transifexApi.ResourceLanguageStats.filter({
63+
project: 'o:openstreetmap:p:id-editor',
64+
resource: 'o:openstreetmap:p:id-editor:r:presets'
65+
}).all()) {
66+
result.push(stat);
67+
}
68+
console.log(`got resource language stats collection for ${resourceId}`);
69+
callback(null, result);
70+
} catch(err) {
71+
console.error(`error while getting resource language stats collection for ${resourceId}`);
72+
callback(err);
73+
}
8374
}
8475
function gotResourceInfo(err, results) {
8576
if (err) return console.log(err);
86-
results.forEach(function(info) {
87-
for (let code in info.stats) {
88-
let type = 'translated';
77+
results.forEach(info => {
78+
info.forEach(stat => {
79+
let code = stat.relationships.language.data.id.substr(2).replace(/_/g, '-');
80+
let type = 'translated_strings';
8981
if (reviewedOnlyLangs.indexOf(code) !== -1) {
90-
// reviewed_1 = reviewed, reviewed_2 = proofread
91-
type = 'reviewed_1';
82+
type = 'reviewed_strings';
9283
}
93-
let coveragePart = info.stats[code][type].percentage / results.length;
84+
let coveragePart = (stat.attributes[type] / stat.attributes.total_strings) / results.length;
9485

95-
code = code.replace(/_/g, '-');
9686
if (coverageByLocaleCode[code] === undefined) coverageByLocaleCode[code] = 0;
9787
coverageByLocaleCode[code] += coveragePart;
98-
}
88+
});
9989
});
10090
}
10191

@@ -135,7 +125,9 @@ function gotResource(err, results) {
135125
fs.writeFileSync(`${outdir}${code}.min.json`, JSON.stringify(obj));
136126

137127
getLanguageInfo(code, (err, info) => {
138-
let rtl = info && info.rtl;
128+
if (err) return console.log(err);
129+
130+
let rtl = info && info.attributes && info.attributes.rtl;
139131
// exceptions: see #4783
140132
if (code === 'ckb') {
141133
rtl = true;
@@ -145,7 +137,7 @@ function gotResource(err, results) {
145137

146138
let coverage = coverageByLocaleCode[code];
147139
if (coverage === undefined) {
148-
console.log('Could not get language coverage');
140+
console.log(`Could not get language coverage for ${code}`, coverageByLocaleCode);
149141
process.exit(1);
150142
}
151143
// we don't need high precision here, but we need to know if it's exactly 100% or not
@@ -173,12 +165,11 @@ function gotResource(err, results) {
173165
}
174166

175167

176-
function getResource(resourceId, callback) {
177-
let resourceURL = `${projectURL}/resource/${resourceId}`;
178-
getLanguages(resourceURL, (err, codes) => {
168+
async function getResource(resourceId, callback) {
169+
getLanguages((err, codes) => {
179170
if (err) return callback(err);
180171

181-
asyncMap(codes, getLanguage(resourceURL), (err, results) => {
172+
asyncMap(codes, getLanguage(resourceId), (err, results) => {
182173
if (err) return callback(err);
183174

184175
let locale = {};
@@ -229,56 +220,60 @@ function getResource(resourceId, callback) {
229220
}
230221

231222

232-
function getLanguage(resourceURL) {
233-
return (code, callback) => {
234-
code = code.replace(/-/g, '_');
235-
let url = `${resourceURL}/translation/${code}`;
236-
// fetch only reviewed strings for some languages
237-
if (reviewedOnlyLangs.indexOf(code) !== -1) {
238-
url += '?mode=reviewed';
223+
function getLanguage(resourceId) {
224+
return async (code, callback) => {
225+
try {
226+
code = code.replace(/-/g, '_');
227+
const url = await transifexApi.ResourceTranslationsAsyncDownload.download({
228+
resource: {data:{type:'resources', id:`o:openstreetmap:p:id-editor:r:${resourceId}`}},
229+
language: {data:{type:'languages', id:`l:${code}`}},
230+
// fetch only reviewed strings for some languages
231+
mode: reviewedOnlyLangs.indexOf(code) !== -1 ? 'reviewed' : 'default'
232+
});
233+
const data = await fetch(url).then(d => d.text());
234+
console.log(`got translations for ${resourceId}, language ${code}`);
235+
callback(null, YAML.load(data)[code]);
236+
} catch(err) {
237+
console.error(`error while getting translations for ${resourceId}, language ${code}`, err);
238+
callback(err);
239239
}
240-
fetch(url, fetchOpts)
241-
.then(res => {
242-
console.log(`${res.status}: ${url}`);
243-
return res.json();
244-
})
245-
.then(json => {
246-
callback(null, YAML.load(json.content)[code]);
247-
})
248-
.catch(err => callback(err));
249240
};
250241
}
251242

252243

253-
function getLanguageInfo(code, callback) {
244+
async function getLanguageInfo(code, callback) {
254245
code = code.replace(/-/g, '_');
255-
let url = `${apiroot}/language/${code}`;
256-
fetch(url, fetchOpts)
257-
.then(res => {
258-
console.log(`${res.status}: ${url}`);
259-
return res.json();
260-
})
261-
.then(json => {
262-
callback(null, json);
263-
})
264-
.catch(err => callback(err));
246+
try {
247+
const lng = await transifexApi.Language.get({
248+
code: code
249+
});
250+
console.log(`got language details for ${code}`);
251+
callback(null, lng);
252+
} catch(err) {
253+
console.error(`error while getting language details for ${code}`);
254+
callback(err);
255+
}
265256
}
266257

267258

268-
function getLanguages(resourceURL, callback) {
269-
let url = `${resourceURL}?details`;
270-
fetch(url, fetchOpts)
271-
.then(res => {
272-
console.log(`${res.status}: ${url}`);
273-
return res.json();
274-
})
275-
.then(json => {
276-
callback(null, json.available_languages
277-
.map(d => d.code.replace(/_/g, '-'))
278-
.filter(d => d !== 'en')
279-
);
280-
})
281-
.catch(err => callback(err));
259+
async function getLanguages(callback) {
260+
try {
261+
const result = [];
262+
const project = await transifexApi.Project.get({
263+
organization: 'o:openstreetmap',
264+
slug: 'id-editor'
265+
});
266+
const lngs = await project.fetch('languages');
267+
for await (const lng of lngs.all()) {
268+
if (lng.attributes.code === 'en') continue;
269+
result.push(lng.attributes.code.replace(/_/g, '-'));
270+
}
271+
console.log('got project languages');
272+
callback(null, result);
273+
} catch(err) {
274+
console.error('error while getting project languages');
275+
callback(err);
276+
}
282277
}
283278

284279

@@ -293,7 +288,7 @@ function asyncMap(inputs, func, callback) {
293288
function next() {
294289
callFunc(index++);
295290
if (index < inputs.length) {
296-
setTimeout(next, 200);
291+
setTimeout(next, 50);
297292
}
298293
}
299294

0 commit comments

Comments
 (0)