15
15
// *****************************************************************************
16
16
17
17
import * as bent from 'bent' ;
18
+ import { RateLimiter } from 'limiter' ;
18
19
19
20
const post = bent ( 'POST' , 'json' , 200 ) ;
20
21
// 50 is the maximum amount of translations per request
21
22
const deeplLimit = 50 ;
23
+ const rateLimiter = new RateLimiter ( {
24
+ tokensPerInterval : 10 ,
25
+ interval : 'second' ,
26
+ fireImmediately : true
27
+ } ) ;
22
28
23
29
export async function deepl (
24
30
parameters : DeeplParameters
@@ -30,12 +36,11 @@ export async function deepl(
30
36
while ( textArray . length > 0 ) {
31
37
textChunks . push ( textArray . splice ( 0 , deeplLimit ) ) ;
32
38
}
33
- const responses : DeeplResponse [ ] = await Promise . all ( textChunks . map ( chunk => {
39
+ const responses : DeeplResponse [ ] = await Promise . all ( textChunks . map ( async chunk => {
34
40
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 ) ;
39
44
} ) ) ;
40
45
const mergedResponse : DeeplResponse = { translations : [ ] } ;
41
46
for ( const response of responses ) {
@@ -47,6 +52,22 @@ export async function deepl(
47
52
return mergedResponse ;
48
53
}
49
54
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
+
50
71
/**
51
72
* Coerces the target language into a form expected by Deepl.
52
73
*
0 commit comments