Skip to content

Commit 1a690eb

Browse files
committed
Add script to push translations source to transifex
1 parent 425f808 commit 1a690eb

File tree

3 files changed

+107
-0
lines changed

3 files changed

+107
-0
lines changed

Diff for: i18n/en.json

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"theia": {
3+
"core": {
4+
"common": {
5+
"example": "This is an example translatable string",
6+
"another-example": "This is another example translatable string"
7+
}
8+
}
9+
}
10+
}

Diff for: package.json

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"test": "lerna run test",
4444
"download:plugins": "theia download:plugins",
4545
"update:version": "node ./scripts/update-version.js",
46+
"i18n:push": "node ./scripts/i18n/transifex-push.js ./i18n/en.json",
4647
"i18n:pull": "node ./scripts/i18n/transifex-pull.js ./i18n/"
4748
},
4849
"lint-staged": {

Diff for: scripts/i18n/transifex-push.js

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// @ts-check
2+
3+
const transifex = require('./transifex');
4+
const fetch = require('node-fetch');
5+
const fs = require('fs');
6+
const shell = require('shelljs');
7+
const util = require('util');
8+
9+
const uploadSourceFile = async (organization, project, resource, filePath) => {
10+
const url = transifex.url('resource_strings_async_uploads');
11+
const data = {
12+
data: {
13+
attributes: {
14+
callback_url: null,
15+
content: fs.readFileSync(filePath).toString('base64'),
16+
content_encoding: 'base64'
17+
},
18+
relationships: {
19+
resource: {
20+
data: {
21+
id: util.format('o:%s:p:%s:r:%s', organization, project, resource),
22+
type: 'resources'
23+
}
24+
}
25+
},
26+
type: 'resource_strings_async_uploads'
27+
}
28+
};
29+
30+
const headers = transifex.authHeader();
31+
headers['Content-Type'] = 'application/vnd.api+json';
32+
const json = await fetch(url, { method: 'POST', headers, body: JSON.stringify(data) })
33+
.catch(err => {
34+
shell.echo(err);
35+
shell.exit(1);
36+
})
37+
.then(res => res.json());
38+
39+
return json['data']['id'];
40+
};
41+
42+
const getSourceUploadStatus = async (uploadId) => {
43+
const url = transifex.url(util.format('resource_strings_async_uploads/%s', uploadId));
44+
// The download request status must be asked from time to time, if it's
45+
// still pending we try again using exponentional backoff starting from 2.5 seconds.
46+
let backoffMs = 2500;
47+
const headers = transifex.authHeader();
48+
while (true) {
49+
const json = await fetch(url, { headers })
50+
.catch(err => {
51+
shell.echo(err);
52+
shell.exit(1);
53+
})
54+
.then(res => res.json());
55+
56+
const status = json['data']['attributes']['status'];
57+
if (status === 'succeeded') {
58+
return
59+
} else if (status === 'pending' || status === 'processing') {
60+
await new Promise(r => setTimeout(r, backoffMs));
61+
backoffMs = backoffMs * 2;
62+
// Retry the upload request status again
63+
continue
64+
} else if (status === 'failed') {
65+
const errors = [];
66+
json['data']['attributes']['errors'].forEach(err => {
67+
errors.push(util.format('%s: %s', err.code, err.details));
68+
});
69+
throw util.format('Download request failed: %s', errors.join(', '));
70+
}
71+
throw 'Download request failed in an unforeseen way';
72+
}
73+
}
74+
75+
(async () => {
76+
const { organization, project, resource } = await transifex.credentials();
77+
const sourceFile = process.argv[2];
78+
if (!sourceFile) {
79+
shell.echo('Translation source file not specified');
80+
shell.exit(1);
81+
}
82+
83+
const uploadId = await uploadSourceFile(organization, project, resource, sourceFile)
84+
.catch(err => {
85+
shell.echo(err);
86+
shell.exit(1);
87+
});
88+
89+
await getSourceUploadStatus(uploadId)
90+
.catch(err => {
91+
shell.echo(err);
92+
shell.exit(1);
93+
});
94+
95+
shell.echo("Translation source file uploaded");
96+
})()

0 commit comments

Comments
 (0)