-
Notifications
You must be signed in to change notification settings - Fork 15
/
index.js
103 lines (86 loc) · 2.77 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
'use strict'
const deepl = require('deepl-node')
const Bottleneck = require('bottleneck/es5')
const {
DEEPL_PRIORITY_DEFAULT,
DEEPL_API_MAX_TEXTS,
DEEPL_API_ROUGH_MAX_REQUEST_SIZE,
} = require('./constants')
const { parseLocale } = require('./parse-locale')
const { getService } = require('./get-service')
/**
* Module dependencies
*/
module.exports = {
provider: 'deepl',
name: 'DeepL',
init(providerOptions = {}) {
const apiKey = process.env.DEEPL_API_KEY || providerOptions.apiKey
const apiUrl = process.env.DEEPL_API_URL || providerOptions.apiUrl
const client = new deepl.Translator(apiKey, {
serverUrl: apiUrl,
})
const limiter = new Bottleneck({
minTime: process.env.NODE_ENV == 'test' ? 10 : 200,
maxConcurrent: 5,
})
const rateLimitedTranslate = limiter.wrap(client.translateText.bind(client))
return {
/**
* @param {{
* text:string|string[],
* sourceLocale: string,
* targetLocale: string,
* priority: number,
* format?: 'plain'|'markdown'|'html'
* }} options all translate options
* @returns {string[]} the input text(s) translated
*/
async translate({ text, priority, sourceLocale, targetLocale, format }) {
if (!text) {
return []
}
if (!sourceLocale || !targetLocale) {
throw new Error('source and target locale must be defined')
}
const chunksService = getService('chunks')
const formatService = getService('format')
const tagHandlingMode = format === 'plain' ? undefined : 'html'
let textArray = Array.isArray(text) ? text : [text]
if (format === 'markdown') {
textArray = formatService.markdownToHtml(textArray)
}
const { chunks, reduceFunction } = chunksService.split(textArray, {
maxLength: DEEPL_API_MAX_TEXTS,
maxByteSize: DEEPL_API_ROUGH_MAX_REQUEST_SIZE,
})
const result = reduceFunction(
await Promise.all(
chunks.map(async (texts) => {
const result = await rateLimitedTranslate.withOptions(
{
priority:
typeof priority == 'number'
? priority
: DEEPL_PRIORITY_DEFAULT,
},
texts,
parseLocale(sourceLocale),
parseLocale(targetLocale),
{ tagHandlingMode }
)
return result.map((value) => value.text)
})
)
)
if (format === 'markdown') {
return formatService.htmlToMarkdown(result)
}
return result
},
async usage() {
return (await client.getUsage()).character
},
}
},
}