Skip to content

Commit a497457

Browse files
jfaltermeiermsujew
andauthored
Fix translation update script (#14794)
* Fix translation update script * Use retry and rate limiter * Introduce minor delay * Limit max tokens --------- Co-authored-by: Mark Sujew <[email protected]>
1 parent cfad6e5 commit a497457

File tree

4 files changed

+30
-7
lines changed

4 files changed

+30
-7
lines changed

dev-packages/localization-manager/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"deepmerge": "^4.2.2",
3737
"fs-extra": "^4.0.2",
3838
"glob": "^7.2.0",
39+
"limiter": "^2.1.0",
3940
"tslib": "^2.6.2",
4041
"typescript": "~5.4.5"
4142
},

dev-packages/localization-manager/src/deepl-api.ts

+26-5
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,16 @@
1515
// *****************************************************************************
1616

1717
import * as bent from 'bent';
18+
import { RateLimiter } from 'limiter';
1819

1920
const post = bent('POST', 'json', 200);
2021
// 50 is the maximum amount of translations per request
2122
const deeplLimit = 50;
23+
const rateLimiter = new RateLimiter({
24+
tokensPerInterval: 10,
25+
interval: 'second',
26+
fireImmediately: true
27+
});
2228

2329
export async function deepl(
2430
parameters: DeeplParameters
@@ -30,12 +36,11 @@ export async function deepl(
3036
while (textArray.length > 0) {
3137
textChunks.push(textArray.splice(0, deeplLimit));
3238
}
33-
const responses: DeeplResponse[] = await Promise.all(textChunks.map(chunk => {
39+
const responses: DeeplResponse[] = await Promise.all(textChunks.map(async chunk => {
3440
const parameterCopy: DeeplParameters = { ...parameters, text: chunk };
35-
return post(`https://${sub_domain}.deepl.com/v2/translate`, Buffer.from(toFormData(parameterCopy)), {
36-
'Content-Type': 'application/x-www-form-urlencoded',
37-
'User-Agent': 'Theia-Localization-Manager'
38-
});
41+
const url = `https://${sub_domain}.deepl.com/v2/translate`;
42+
const buffer = Buffer.from(toFormData(parameterCopy));
43+
return postWithRetry(url, buffer, 1);
3944
}));
4045
const mergedResponse: DeeplResponse = { translations: [] };
4146
for (const response of responses) {
@@ -47,6 +52,22 @@ export async function deepl(
4752
return mergedResponse;
4853
}
4954

55+
async function postWithRetry(url: string, buffer: Buffer, attempt: number): Promise<DeeplResponse> {
56+
try {
57+
await rateLimiter.removeTokens(Math.min(attempt, 10));
58+
const response = await post(url, buffer, {
59+
'Content-Type': 'application/x-www-form-urlencoded',
60+
'User-Agent': 'Theia-Localization-Manager'
61+
});
62+
return response;
63+
} catch (e) {
64+
if ('message' in e && typeof e.message === 'string' && e.message.includes('Too Many Requests')) {
65+
return postWithRetry(url, buffer, attempt + 1);
66+
}
67+
throw e;
68+
}
69+
}
70+
5071
/**
5172
* Coerces the target language into a form expected by Deepl.
5273
*

package-lock.json

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/translation-update.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ if (hasNlsFileChanged()) {
1717
}
1818

1919
function performNlsExtract() {
20-
cp.spawnSync('npm', [
21-
'run',
20+
cp.spawnSync('npx', [
2221
'theia', 'nls-extract',
2322
'-o', './packages/core/i18n/nls.json',
2423
'-e', 'vscode',

0 commit comments

Comments
 (0)