Skip to content

Commit 55906b2

Browse files
committed
docs: Add example showing bulk text and file translation
1 parent e355d15 commit 55906b2

6 files changed

Lines changed: 179 additions & 0 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*.js
2+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Hello, world!
2+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This is a test.

examples/bulk-translation/index.ts

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import * as fs from 'fs';
2+
import * as deepl from 'deepl-node';
3+
import pLimit from 'p-limit';
4+
import * as path from 'path';
5+
6+
// Sets a global concurrency limit of 10 for the translation requests
7+
// This is an external library to simplify this example, if you don't
8+
// want to use it, you will need to implement your own concurrency
9+
// control logic.
10+
const limit = pLimit(10);
11+
12+
class ResultOrError<T> {
13+
constructor(public result: T | null, public error: Error | null) {}
14+
}
15+
16+
// Example function to translate an array of texts into multiple target languages
17+
// This currently uses source language detection, a source language could also be set for each text.
18+
// In the output array, result[i][j] is the translation of texts[i] into targetLangs[j].
19+
async function bulkTextTranslate(
20+
deeplClient: deepl.DeepLClient,
21+
texts: string[],
22+
targetLangs: deepl.TargetLanguageCode[],
23+
): Promise<ResultOrError<deepl.TextResult>[][]> {
24+
const allPromises: Promise<ResultOrError<deepl.TextResult>>[][] = [];
25+
const wrappedTranslateText = async (text: string, targetLang: deepl.TargetLanguageCode) => {
26+
try {
27+
const result = await deeplClient.translateText(text, null, targetLang);
28+
return new ResultOrError<deepl.TextResult>(result, null);
29+
} catch (error) {
30+
return new ResultOrError<deepl.TextResult>(null, error);
31+
}
32+
};
33+
for (const text of texts) {
34+
const promisesForText: Promise<ResultOrError<deepl.TextResult>>[] = [];
35+
for (const targetLang of targetLangs) {
36+
promisesForText.push(limit(() => wrappedTranslateText(text, targetLang)));
37+
}
38+
allPromises.push(promisesForText);
39+
}
40+
41+
// This is not optimal for performance, you likely want to enqueue the requested translations
42+
// instead and dynamically take them from the queue, but this is a simple example.
43+
const results: ResultOrError<deepl.TextResult>[][] = [];
44+
for (const promisesForText of allPromises) {
45+
const resultsForText = await Promise.all(promisesForText);
46+
results.push(resultsForText);
47+
}
48+
// This returns a 2D array where each sub-array corresponds to the translations of a single text
49+
// Another way would be to return an array of objects with the target language and the associated translation.
50+
return results;
51+
}
52+
53+
// Example function to translate an array of texts into multiple target languages
54+
// This currently uses source language detection, a source language could also be set for each text.
55+
// In the output array, result[i][j] is the status of inputFiles[i] being translated into targetLangs[j].
56+
async function bulkDocumentTranslate(
57+
deeplClient: deepl.DeepLClient,
58+
inputFiles: string[],
59+
outputDir: string,
60+
targetLangs: deepl.TargetLanguageCode[],
61+
): Promise<ResultOrError<deepl.DocumentStatus>[][]> {
62+
const allPromises: Promise<ResultOrError<deepl.DocumentStatus>>[][] = [];
63+
const wrappedTranslateDocument = async (
64+
inputFile: string | Buffer | fs.ReadStream | fs.promises.FileHandle,
65+
outputFile: string | fs.WriteStream | fs.promises.FileHandle,
66+
targetLang: deepl.TargetLanguageCode,
67+
) => {
68+
try {
69+
const result = await deeplClient.translateDocument(
70+
inputFile,
71+
outputFile,
72+
null /** sourceLang */,
73+
targetLang,
74+
);
75+
return new ResultOrError<deepl.DocumentStatus>(result, null);
76+
} catch (error) {
77+
return new ResultOrError<deepl.DocumentStatus>(null, error);
78+
}
79+
};
80+
inputFiles.forEach((inputFile) => {
81+
const promisesForDocument: Promise<ResultOrError<deepl.DocumentStatus>>[] = [];
82+
targetLangs.forEach((targetLang) => {
83+
promisesForDocument.push(
84+
limit(() =>
85+
wrappedTranslateDocument(
86+
inputFile,
87+
path.join(outputDir, `${path.parse(inputFile).name}-${targetLang}.txt`),
88+
targetLang,
89+
),
90+
),
91+
);
92+
});
93+
allPromises.push(promisesForDocument);
94+
});
95+
96+
// This is not optimal for performance, you likely want to enqueue the requested translations
97+
// instead and dynamically take them from the queue, but this is a simple example.
98+
const results: ResultOrError<deepl.DocumentStatus>[][] = [];
99+
for (const promisesForDocument of allPromises) {
100+
const resultsForDocument = await Promise.all(promisesForDocument);
101+
results.push(resultsForDocument);
102+
}
103+
return results;
104+
}
105+
106+
const authKey = process.env['DEEPL_AUTH_KEY'];
107+
if (authKey === undefined) throw new Error('DEEPL_AUTH_KEY environment variable not defined');
108+
const serverUrl = process.env['DEEPL_SERVER_URL'];
109+
const deeplClient = new deepl.DeepLClient(authKey, { serverUrl: serverUrl });
110+
111+
(async () => {
112+
try {
113+
console.log(await deeplClient.getUsage());
114+
115+
const targetLangs: deepl.TargetLanguageCode[] = ['fr', 'de', 'es'];
116+
const texts = ['Hello, world!', 'This is a test.', 'DeepL is great!'];
117+
const results = await bulkTextTranslate(deeplClient, texts, targetLangs);
118+
for (const resultRow of results) {
119+
for (const result of resultRow) {
120+
if (result.error) {
121+
console.error(`Error translating text: ${result.error.message}`);
122+
} else {
123+
console.log(result.result.text);
124+
}
125+
}
126+
}
127+
const inputFiles = ['example1.txt', 'example2.txt'];
128+
const outputDir = './output';
129+
const docResults = await bulkDocumentTranslate(
130+
deeplClient,
131+
inputFiles,
132+
outputDir,
133+
targetLangs,
134+
);
135+
for (const resultsPerDocument of docResults) {
136+
for (const result of resultsPerDocument) {
137+
if (result.error) {
138+
console.error(`Error translating document: ${result.error.message}`);
139+
} else {
140+
console.log(
141+
`Translated document: Status ${result.result.status} - Billed ${result.result.billedCharacters} characters`,
142+
);
143+
}
144+
}
145+
}
146+
} catch (error) {
147+
console.log(error);
148+
process.exit(1);
149+
}
150+
})();
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "deepl-node-example-typescript",
3+
"description": "Example for deepl-node using TypeScript",
4+
"type": "module",
5+
"dependencies": {
6+
"@types/node": "^18.11.9",
7+
"deepl-node": "file:../..",
8+
"p-limit": "^6.2.0"
9+
},
10+
"main": "index.ts",
11+
"scripts": {
12+
"build": "tsc -p tsconfig.json"
13+
},
14+
"devDependencies": {
15+
"typescript": ">=3.0 && <5.1"
16+
}
17+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"compilerOptions": {
3+
"module": "es2015",
4+
"moduleResolution": "node",
5+
"target": "es6"
6+
}
7+
}

0 commit comments

Comments
 (0)