handlebars-i18n-cli 1.0.4 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/coveralls.yml +35 -18
- package/.github/workflows/node.js.yml +2 -2
- package/README.md +384 -52
- package/bin/i18n-collect +36 -2
- package/bin/i18n-deepl +71 -0
- package/de.json +72 -0
- package/en.json +5 -0
- package/fi.json +5 -0
- package/my.json +23 -0
- package/package.json +27 -16
- package/src/i18n-collect.js +162 -289
- package/src/i18n-deepl.js +304 -0
- package/src/index.js +4 -0
- package/test/handlebars-i18n-cli.test.mjs +472 -0
- package/tsconfig.json +20 -0
- package/types/i18n-collect.d.ts +5 -0
- package/types/i18n-collect.d.ts.map +1 -0
- package/types/i18n-deepl.d.ts +44 -0
- package/types/i18n-deepl.d.ts.map +1 -0
- package/types/index.d.ts +7 -0
- package/types/index.d.ts.map +1 -0
- package/want.md +18 -0
- package/src/deepl-free-api-key.json +0 -3
- package/src/deepl-pro-api-key.json +0 -3
- package/test/handlebars-i18n-cli.test.js +0 -174
- package/test/test-generated/test-12.json +0 -8
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for ./src/i18n-collect.js & ./src/i18n-deepl.js
|
|
3
|
+
*
|
|
4
|
+
* usage:
|
|
5
|
+
* $ npm test
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as chai from 'chai';
|
|
9
|
+
import sinon from 'sinon';
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
import fst from 'async-file-tried';
|
|
12
|
+
import chaiAsPromised from 'chai-as-promised';
|
|
13
|
+
import sinonChai from 'sinon-chai';
|
|
14
|
+
import axios from 'axios';
|
|
15
|
+
import deepl from 'deepl-node'; // Assuming deepl is imported in the module
|
|
16
|
+
import {stdout} from 'test-console';
|
|
17
|
+
|
|
18
|
+
const {assert, expect} = chai;
|
|
19
|
+
chai.use(chaiAsPromised);
|
|
20
|
+
chai.use(sinonChai);
|
|
21
|
+
|
|
22
|
+
import {
|
|
23
|
+
i18nCollect,
|
|
24
|
+
setAuthKey,
|
|
25
|
+
getSupportedLanguages,
|
|
26
|
+
translateTexts,
|
|
27
|
+
translateToJSON
|
|
28
|
+
} from '../src/index.js';
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
/****************************************
|
|
32
|
+
* setAuthKey
|
|
33
|
+
****************************************/
|
|
34
|
+
describe('i18n-deepl setAuthKey', () => {
|
|
35
|
+
|
|
36
|
+
let writeFileStub;
|
|
37
|
+
|
|
38
|
+
beforeEach(function () {
|
|
39
|
+
// Stub the fs.writeFile function
|
|
40
|
+
writeFileStub = sinon.stub(fs, 'writeFile');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
afterEach(function () {
|
|
44
|
+
// Restore the original fs.writeFile function
|
|
45
|
+
sinon.restore();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('[A-1] setAuthKey should throw an error if the key is not a string', async function () {
|
|
49
|
+
const invalidKey = 12345; // Example of a non-string key
|
|
50
|
+
await expect(setAuthKey(invalidKey)).to.be.rejectedWith('Provided argument is not a valid DeepL auth key.');
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('[A-2] setAuthKey should throw an error if the key is an empty string', async function () {
|
|
54
|
+
const invalidKey = ''; // Example of an empty string key
|
|
55
|
+
await expect(setAuthKey(invalidKey)).to.be.rejectedWith('Provided argument is not a valid DeepL auth key.');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('[A-3] setAuthKey should return true if the key is valid and the file is written successfully', async function () {
|
|
59
|
+
// Mock fst.writeFile to resolve successfully
|
|
60
|
+
sinon.stub(fst, 'writeFile').resolves([true, null]);
|
|
61
|
+
const result = await setAuthKey('valid-key');
|
|
62
|
+
expect(result).to.be.true;
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('[A-4] setAuthKey should throw an error if fs.writeFile fails', async function () {
|
|
66
|
+
// Mock fst.writeFile to simulate a failure
|
|
67
|
+
sinon.stub(fst, 'writeFile').resolves([null, new Error('Write error')]);
|
|
68
|
+
await expect(setAuthKey('valid-key')).to.be.rejectedWith('Failed to write file .env');
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
/****************************************
|
|
75
|
+
* getSupportedLanguages
|
|
76
|
+
****************************************/
|
|
77
|
+
|
|
78
|
+
describe('i18n-deepl getSupportedLanguages', function () {
|
|
79
|
+
|
|
80
|
+
let axiosGetStub;
|
|
81
|
+
|
|
82
|
+
beforeEach(function () {
|
|
83
|
+
// Stub axios.get to control its behavior in tests
|
|
84
|
+
axiosGetStub = sinon.stub(axios, 'get');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
afterEach(function () {
|
|
88
|
+
// Restore the original behavior of axios.get after each test
|
|
89
|
+
sinon.restore();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('[B-1] getSupportedLanguages should throw an error when no authKey is provided', async function () {
|
|
93
|
+
await expect(getSupportedLanguages()).to.be.rejectedWith('Invalid argument authKey provided.');
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('[B-2] getSupportedLanguages should fetch supported languages when authKey is valid', async function () {
|
|
97
|
+
// Mock the response for the axios.get request
|
|
98
|
+
const mockResponse = {data: [{language: 'EN'}, {language: 'DE'}]};
|
|
99
|
+
axiosGetStub.resolves(mockResponse);
|
|
100
|
+
// make the call
|
|
101
|
+
const result = await getSupportedLanguages('valid-auth-key');
|
|
102
|
+
// Assert that the function returns the expected result
|
|
103
|
+
expect(result).to.deep.equal(mockResponse.data);
|
|
104
|
+
expect(axiosGetStub.calledOnce).to.be.true;
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('[B-3] getSupportedLanguages should throw an error when axios request fails', async function () {
|
|
108
|
+
// Mock a failed axios.get request
|
|
109
|
+
axiosGetStub.rejects(new Error('Error fetching supported languages: Network error'));
|
|
110
|
+
await expect(getSupportedLanguages('valid-auth-key'))
|
|
111
|
+
.to.be.rejectedWith('Error fetching supported languages: Network error');
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
/****************************************
|
|
117
|
+
* translateTexts
|
|
118
|
+
****************************************/
|
|
119
|
+
describe('i18n-deepl translateTexts', () => {
|
|
120
|
+
let authKey, texts, sourceLang, targetLang, options, translatorStub;
|
|
121
|
+
|
|
122
|
+
beforeEach(() => {
|
|
123
|
+
authKey = 'valid-auth-key';
|
|
124
|
+
texts = ['Hello', 'World'];
|
|
125
|
+
sourceLang = 'EN';
|
|
126
|
+
targetLang = 'FR';
|
|
127
|
+
options = {formality: 'informal'};
|
|
128
|
+
|
|
129
|
+
// Mock deepl.Translator
|
|
130
|
+
translatorStub = sinon.stub(new deepl.Translator(authKey));
|
|
131
|
+
sinon.stub(deepl, 'Translator').returns(translatorStub);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
afterEach(() => {
|
|
135
|
+
sinon.restore(); // Reset all stubs/mocks/spies between tests
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('[C-1] translateTexts should throw an error if authKey is not a string', async () => {
|
|
139
|
+
try {
|
|
140
|
+
await translateTexts(12345, texts, sourceLang, targetLang, options);
|
|
141
|
+
} catch (error) {
|
|
142
|
+
expect(error.message).to.equal('Invalid argument authKey provided.');
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('[C-2] translateTexts should call deepl.Translator with correct authKey', async () => {
|
|
147
|
+
translatorStub.translateText.resolves(['Bonjour', 'Monde']);
|
|
148
|
+
|
|
149
|
+
await translateTexts(authKey, texts, sourceLang, targetLang, options);
|
|
150
|
+
|
|
151
|
+
expect(deepl.Translator).to.have.been.calledWith(authKey);
|
|
152
|
+
expect(translatorStub.translateText).to.have.been.calledWith(texts, sourceLang, targetLang, options);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('[C-3] translateTexts should return translated texts from deepl.Translator', async () => {
|
|
156
|
+
const translatedTexts = ['Bonjour', 'Monde'];
|
|
157
|
+
translatorStub.translateText.resolves(translatedTexts);
|
|
158
|
+
|
|
159
|
+
const result = await translateTexts(authKey, texts, sourceLang, targetLang, options);
|
|
160
|
+
|
|
161
|
+
expect(result).to.deep.equal(translatedTexts);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('[C-4] translateTexts should throw an error when deepl.Translator.translateText fails', async () => {
|
|
165
|
+
const error = new Error('API Error');
|
|
166
|
+
translatorStub.translateText.rejects(error);
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
await translateTexts(authKey, texts, sourceLang, targetLang, options);
|
|
170
|
+
} catch (err) {
|
|
171
|
+
expect(err.message).to.equal('API Error');
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
/****************************************
|
|
178
|
+
* translateToJSON
|
|
179
|
+
****************************************/
|
|
180
|
+
describe('i18n-deepl translateToJSON', () => {
|
|
181
|
+
|
|
182
|
+
afterEach(() => {
|
|
183
|
+
sinon.restore(); // Restore mocks after each test
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it('[D-1] translateToJSON should translate a JSON file and write the translated result to a target file', async () => {
|
|
187
|
+
|
|
188
|
+
// Mock reading the JSON source file
|
|
189
|
+
const mockJsonData = {greeting: "Hello"};
|
|
190
|
+
sinon.stub(fst, 'readJson').resolves([mockJsonData, null]);
|
|
191
|
+
|
|
192
|
+
// Mock DeepL translation result
|
|
193
|
+
const mockTranslationResult = [{text: "Hallo"}];
|
|
194
|
+
sinon.stub(deepl.Translator.prototype, 'translateText').resolves(mockTranslationResult);
|
|
195
|
+
|
|
196
|
+
// Mock writing the translated result to a target file
|
|
197
|
+
const writeJsonMock = sinon.stub(fst, 'writeJson').resolves([true, null]);
|
|
198
|
+
|
|
199
|
+
// Execute the function
|
|
200
|
+
const result = await translateToJSON(
|
|
201
|
+
'authKey',
|
|
202
|
+
'src.json',
|
|
203
|
+
'target.json',
|
|
204
|
+
'de',
|
|
205
|
+
'en',
|
|
206
|
+
{},
|
|
207
|
+
null,
|
|
208
|
+
false,
|
|
209
|
+
false
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
// Assertions
|
|
213
|
+
expect(result).to.be.true;
|
|
214
|
+
expect(writeJsonMock).to.have.been.calledWith('target.json', {greeting: 'Hallo'});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('[D-2] translateToJSON should log the translation result but not write the file when dryRun is true', async () => {
|
|
218
|
+
|
|
219
|
+
// Mock reading the JSON source file
|
|
220
|
+
const mockJsonData = {greeting: "Hello"};
|
|
221
|
+
sinon.stub(fst, 'readJson').resolves([mockJsonData, null]);
|
|
222
|
+
|
|
223
|
+
// Mock DeepL translation result
|
|
224
|
+
const mockTranslationResult = [{text: "Hallo"}];
|
|
225
|
+
sinon.stub(deepl.Translator.prototype, 'translateText').resolves(mockTranslationResult);
|
|
226
|
+
|
|
227
|
+
// Mock writing (it should NOT be called)
|
|
228
|
+
const writeJsonMock = sinon.stub(fst, 'writeJson');
|
|
229
|
+
|
|
230
|
+
// Spy on console.log to check if it's called
|
|
231
|
+
const logSpy = sinon.spy(console, 'log');
|
|
232
|
+
|
|
233
|
+
// Execute the function
|
|
234
|
+
const result = await translateToJSON(
|
|
235
|
+
'authKey',
|
|
236
|
+
'src.json',
|
|
237
|
+
'target.json',
|
|
238
|
+
'de',
|
|
239
|
+
'en',
|
|
240
|
+
{},
|
|
241
|
+
null,
|
|
242
|
+
null,
|
|
243
|
+
true,
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
// Assertions
|
|
247
|
+
expect(result).to.be.true;
|
|
248
|
+
expect(writeJsonMock).not.to.have.been.called;
|
|
249
|
+
expect(logSpy).to.have.been.calledWith({greeting: 'Hallo'});
|
|
250
|
+
|
|
251
|
+
// Restore console.log spy
|
|
252
|
+
logSpy.restore();
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it('[D-3] translateToJSON should throw an error if the target file already exists', async () => {
|
|
256
|
+
|
|
257
|
+
// Mock reading the JSON source file
|
|
258
|
+
const mockJsonData = {greeting: "Hello"};
|
|
259
|
+
sinon.stub(fst, 'readJson').resolves([mockJsonData, null]);
|
|
260
|
+
|
|
261
|
+
// Mock DeepL translation result
|
|
262
|
+
const mockTranslationResult = [{text: "Hallo"}];
|
|
263
|
+
sinon.stub(deepl.Translator.prototype, 'translateText').resolves(mockTranslationResult);
|
|
264
|
+
|
|
265
|
+
// Mock file existence and realpathSync
|
|
266
|
+
sinon.stub(fst, 'exists').resolves(true);
|
|
267
|
+
|
|
268
|
+
try {
|
|
269
|
+
const result = await translateToJSON(
|
|
270
|
+
'authKey',
|
|
271
|
+
'my.json',
|
|
272
|
+
'target.json',
|
|
273
|
+
'de',
|
|
274
|
+
'en'
|
|
275
|
+
);
|
|
276
|
+
} catch (err) {
|
|
277
|
+
|
|
278
|
+
expect(err.message).to.include('The target file "target.json" already exists.');
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it('[D-4] translateToJSON should translate a nested structure in the JSON file and insert into the target', async () => {
|
|
283
|
+
// Mock reading the JSON source file with a nested structure
|
|
284
|
+
const mockJsonData = {nested: {greeting: "Hallo Welt"}};
|
|
285
|
+
sinon.stub(fst, 'readJson').resolves([mockJsonData, null]);
|
|
286
|
+
|
|
287
|
+
// Mock DeepL translation result
|
|
288
|
+
const mockTranslationResult = [{text: "Hello World"}];
|
|
289
|
+
sinon.stub(deepl.Translator.prototype, 'translateText').resolves(mockTranslationResult);
|
|
290
|
+
|
|
291
|
+
// Mock writing the translated result
|
|
292
|
+
const writeJsonMock = sinon.stub(fst, 'writeJson').resolves([true, null]);
|
|
293
|
+
|
|
294
|
+
// Execute the function
|
|
295
|
+
const result = await translateToJSON(
|
|
296
|
+
'authKey',
|
|
297
|
+
'src.json',
|
|
298
|
+
'target-2.json',
|
|
299
|
+
'de',
|
|
300
|
+
'en',
|
|
301
|
+
{},
|
|
302
|
+
'nested',
|
|
303
|
+
false,
|
|
304
|
+
false);
|
|
305
|
+
|
|
306
|
+
// Assertions
|
|
307
|
+
expect(result).to.be.true;
|
|
308
|
+
expect(writeJsonMock).to.have.been.calledWith('target-2.json', {"greeting": "Hello World"});
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
it('[D-5] translateToJSON should throw an error if DeepL API call fails', async () => {
|
|
313
|
+
// Mock reading the JSON source file
|
|
314
|
+
const mockJsonData = {greeting: "Hello"};
|
|
315
|
+
sinon.stub(fst, 'readJson').resolves([mockJsonData, null]);
|
|
316
|
+
|
|
317
|
+
// Mock DeepL API failure
|
|
318
|
+
sinon.stub(deepl.Translator.prototype, 'translateText').rejects(new Error('API Error'));
|
|
319
|
+
|
|
320
|
+
try {
|
|
321
|
+
await translateToJSON(
|
|
322
|
+
'authKey',
|
|
323
|
+
'src.json',
|
|
324
|
+
'target.json',
|
|
325
|
+
'de',
|
|
326
|
+
'en'
|
|
327
|
+
);
|
|
328
|
+
} catch (err) {
|
|
329
|
+
expect(err.message).to.equal('API Error');
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
/****************************************
|
|
336
|
+
* i18n-collect
|
|
337
|
+
****************************************/
|
|
338
|
+
describe('i18n-collect', () => {
|
|
339
|
+
|
|
340
|
+
afterEach(function () {
|
|
341
|
+
// Restore the original behavior of axios.get after each test
|
|
342
|
+
sinon.restore();
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
const templSimple = 'test/test-assets/simple.html';
|
|
346
|
+
const customSimple = 'test/test-assets/custom-func.html';
|
|
347
|
+
|
|
348
|
+
it('[E-1] i18nCollect shall be a function', () => {
|
|
349
|
+
assert.isFunction(i18nCollect);
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
it('[E-2] ERROR: i18nCollect shall error when called without argument', async () => {
|
|
353
|
+
expect(i18nCollect()).to.be.rejectedWith(Error);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
it('[E-3] ERROR: i18nCollect shall error when called without a second argument', async () => {
|
|
357
|
+
expect(i18nCollect(templSimple)).to.be.rejectedWith(Error);
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
it('[E-4] WARN: i18nCollect shall log when a given file does not contain strings for translation', async () => {
|
|
361
|
+
const inspect = stdout.inspect();
|
|
362
|
+
try {
|
|
363
|
+
await i18nCollect('test/test-assets/empty.html', 'test/test-generated/empty.json');
|
|
364
|
+
} catch (e) {
|
|
365
|
+
console.log(e);
|
|
366
|
+
}
|
|
367
|
+
inspect.restore();
|
|
368
|
+
assert.deepEqual(inspect.output, [
|
|
369
|
+
'Now processing test/test-assets/empty.html\n',
|
|
370
|
+
'No strings for translation found, no files written.\n'
|
|
371
|
+
]);
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
it('[E-5] LOG: i18nCollect shall log myKey and myVar (with additional text) for language "en" when called with argument --log', async () => {
|
|
375
|
+
const fileNo = 5; // we use the no. of the test here
|
|
376
|
+
const inspect = stdout.inspect();
|
|
377
|
+
try {
|
|
378
|
+
await i18nCollect('test/test-assets/simple.html', `test/test-generated/test-${fileNo}.json`, {log: true});
|
|
379
|
+
} catch (e) {
|
|
380
|
+
throw (e);
|
|
381
|
+
}
|
|
382
|
+
inspect.restore();
|
|
383
|
+
assert.deepEqual(inspect.output, [
|
|
384
|
+
`Now processing test/test-assets/simple.html\n`,
|
|
385
|
+
`{\n \"translations\": {\n \"en\": {\n \"myKey\": \"en of myKey with variables {{myVar}}\"\n }\n }\n}\n`
|
|
386
|
+
],
|
|
387
|
+
'The logged output did not match the expected result.');
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
it('[E-6] ALPHABETICAL: i18nCollect shall log keys for language "en" in alphabetical order when called with argument --alphabetical and --log', async () => {
|
|
391
|
+
const fileNo = 6;
|
|
392
|
+
const inspect = stdout.inspect();
|
|
393
|
+
await i18nCollect('test/test-assets/multiple.html', `test/test-generated/test-${fileNo}.json`, {
|
|
394
|
+
alphabetical: true,
|
|
395
|
+
log: true
|
|
396
|
+
});
|
|
397
|
+
inspect.restore();
|
|
398
|
+
assert.deepEqual(inspect.output, [
|
|
399
|
+
'Now processing test/test-assets/multiple.html\n',
|
|
400
|
+
'{\n \"translations\": {\n \"en\": {\n \"a\": {\n \"a\": \"en of a.a\",\n \"b\": \"en of a.b\"\n },\n \"b\": \"en of b\"\n }\n }\n}\n'
|
|
401
|
+
]);
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
it('[E-7] EMPTY: i18nCollect shall log myKey and myVar (no text) for language "en" when called with argument --empty and --log', async () => {
|
|
405
|
+
const fileNo = 8;
|
|
406
|
+
const inspect = stdout.inspect();
|
|
407
|
+
await i18nCollect(templSimple, `test/test-generated/test-${fileNo}.json`, {empty: true, log: true});
|
|
408
|
+
inspect.restore();
|
|
409
|
+
assert.deepEqual(inspect.output, [
|
|
410
|
+
`Now processing ${templSimple}\n`,
|
|
411
|
+
'{\n \"translations\": {\n \"en\": {\n \"myKey\": \"{{myVar}}\"\n }\n }\n}\n'
|
|
412
|
+
]);
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
it('[E-8] LNG: i18nCollect shall log myKey and myVar for language "de", "fr", and "es" when called with arguments --lng=de,fr,es and --log', async () => {
|
|
416
|
+
const fileNo = 8;
|
|
417
|
+
const inspect = stdout.inspect();
|
|
418
|
+
await i18nCollect(templSimple, `test/test-generated/test-${fileNo}.json`, {lng: ["de", "fr", "es"], log: true});
|
|
419
|
+
inspect.restore();
|
|
420
|
+
assert.deepEqual(inspect.output, [
|
|
421
|
+
`Now processing ${templSimple}\n`,
|
|
422
|
+
'{\n \"translations\": {\n \"de\": {\n \"myKey\": \"de of myKey with variables {{myVar}}\"\n },\n \"fr\": {\n \"myKey\": \"fr of myKey with variables {{myVar}}\"\n },\n \"es\": {\n \"myKey\": \"es of myKey with variables {{myVar}}\"\n }\n }\n}\n'
|
|
423
|
+
]);
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
it('[E-9] SEPARATE FILES: i18nCollect shall log for three single files when called with arguments --lng=de,fr,es -sf and --log', async () => {
|
|
427
|
+
const fileNo = 9;
|
|
428
|
+
const inspect = stdout.inspect();
|
|
429
|
+
await i18nCollect(templSimple, `test/test-generated/test-${fileNo}.json`, {
|
|
430
|
+
lng: ["de", "fr", "es"],
|
|
431
|
+
log: true,
|
|
432
|
+
separateLngFiles: true
|
|
433
|
+
});
|
|
434
|
+
inspect.restore();
|
|
435
|
+
assert.deepEqual(inspect.output, [
|
|
436
|
+
`Now processing ${templSimple}\n`,
|
|
437
|
+
"{\n \"de\": {\n \"myKey\": \"de of myKey with variables {{myVar}}\"\n }\n}\n",
|
|
438
|
+
`\u001b[34mWrote language keys for 'de' to test/test-generated/test-${fileNo}.de.json\u001b[0m\n`,
|
|
439
|
+
"{\n \"fr\": {\n \"myKey\": \"fr of myKey with variables {{myVar}}\"\n }\n}\n",
|
|
440
|
+
`\u001b[34mWrote language keys for 'fr' to test/test-generated/test-${fileNo}.fr.json\u001b[0m\n`,
|
|
441
|
+
"{\n \"es\": {\n \"myKey\": \"es of myKey with variables {{myVar}}\"\n }\n}\n",
|
|
442
|
+
`\u001b[34mWrote language keys for 'es' to test/test-generated/test-${fileNo}.es.json\u001b[0m\n`
|
|
443
|
+
]);
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
it('[E-10] CUSTOM TRANSLATION FUNC: i18nCollect shall log myOtherKey when called with arguments --translFunc=_t and --log', async () => {
|
|
447
|
+
const fileNo = 10;
|
|
448
|
+
const inspect = stdout.inspect();
|
|
449
|
+
await i18nCollect(customSimple, `test/test-generated/test-${fileNo}.json`, {translFunc: "_t", log: true});
|
|
450
|
+
inspect.restore();
|
|
451
|
+
assert.deepEqual(inspect.output, [
|
|
452
|
+
`Now processing ${customSimple}\n`,
|
|
453
|
+
"{\n \"translations\": {\n \"en\": {\n \"myOtherKey\": \"en of myOtherKey\"\n }\n }\n}\n",
|
|
454
|
+
]);
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
it('[E-11] UPDATE: i18nCollect shall log for extending existing file when called with arguments --update and --log', async () => {
|
|
458
|
+
const fileNo = 10;
|
|
459
|
+
const inspect = stdout.inspect();
|
|
460
|
+
try {
|
|
461
|
+
await i18nCollect(templSimple, `test/test-generated/test-${fileNo}.json`, {update: true, log: true});
|
|
462
|
+
} catch(e) {
|
|
463
|
+
console.log (e)
|
|
464
|
+
}
|
|
465
|
+
inspect.restore();
|
|
466
|
+
assert.deepEqual(inspect.output, [
|
|
467
|
+
`Now processing ${templSimple}\n`,
|
|
468
|
+
"{\n \"translations\": {\n \"en\": {\n \"myKey\": \"en of myKey with variables {{myVar}}\",\n \"myOtherKey\": \"en of myOtherKey\"\n }\n }\n}\n"
|
|
469
|
+
]);
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
});
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2015",
|
|
4
|
+
"module": "CommonJS",
|
|
5
|
+
"lib": ["ES2015", "DOM"],
|
|
6
|
+
"allowJs": true,
|
|
7
|
+
"emitDeclarationOnly": true,
|
|
8
|
+
"declaration": true,
|
|
9
|
+
"declarationMap": true,
|
|
10
|
+
"outDir": "./types",
|
|
11
|
+
"strict": true
|
|
12
|
+
},
|
|
13
|
+
"include": ["src/**/*"],
|
|
14
|
+
"exclude": [
|
|
15
|
+
"bin",
|
|
16
|
+
"coverage",
|
|
17
|
+
"types",
|
|
18
|
+
"node_modules",
|
|
19
|
+
"test"] // Specifies folders or patterns to exclude
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n-collect.d.ts","sourceRoot":"","sources":["../src/i18n-collect.js"],"names":[],"mappings":"AA0RA;;0CAE0C;AAE1C,0FA8IC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/****************************************
|
|
2
|
+
* PUBLIC INTERFACE
|
|
3
|
+
****************************************/
|
|
4
|
+
/**
|
|
5
|
+
* Write th DeepL auth key to .env file
|
|
6
|
+
*
|
|
7
|
+
* @param key
|
|
8
|
+
* @param path
|
|
9
|
+
* @returns {Promise<boolean>}
|
|
10
|
+
*/
|
|
11
|
+
export function setAuthKey(key: any, path?: string): Promise<boolean>;
|
|
12
|
+
/**
|
|
13
|
+
* Function to fetch supported languages from the DeepL API
|
|
14
|
+
*
|
|
15
|
+
* @param authKey
|
|
16
|
+
* @returns {Promise<*>}
|
|
17
|
+
*/
|
|
18
|
+
export function getSupportedLanguages(authKey: any): Promise<any>;
|
|
19
|
+
/**
|
|
20
|
+
* Translate a string or an array of strings using the DeepL API
|
|
21
|
+
*
|
|
22
|
+
* @param authKey
|
|
23
|
+
* @param texts
|
|
24
|
+
* @param sourceLang
|
|
25
|
+
* @param targetLang
|
|
26
|
+
* @param options
|
|
27
|
+
* @returns {Promise<TextResult|TextResult[]>}
|
|
28
|
+
*/
|
|
29
|
+
export function translateTexts(authKey: any, texts: any, sourceLang: any, targetLang: any, options: any): Promise<TextResult | TextResult[]>;
|
|
30
|
+
/** read a json file, translate it with the Deepl API, write the result as json file
|
|
31
|
+
*
|
|
32
|
+
* @param authKey
|
|
33
|
+
* @param JsonSrc
|
|
34
|
+
* @param JsonTarget
|
|
35
|
+
* @param targetLangCode
|
|
36
|
+
* @param sourceNested
|
|
37
|
+
* @param sourceLangCode
|
|
38
|
+
* @param log
|
|
39
|
+
* @param dryRun
|
|
40
|
+
* @param deeplOpts
|
|
41
|
+
* @returns {Promise<boolean>}
|
|
42
|
+
*/
|
|
43
|
+
export function translateToJSON(authKey: any, JsonSrc: any, JsonTarget: any, sourceLangCode: any, targetLangCode: any, deeplOpts: any, sourceNested: any, log: any, dryRun: any): Promise<boolean>;
|
|
44
|
+
//# sourceMappingURL=i18n-deepl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n-deepl.d.ts","sourceRoot":"","sources":["../src/i18n-deepl.js"],"names":[],"mappings":"AA2HA;;0CAE0C;AAE1C;;;;;;GAMG;AACH,qDAFa,OAAO,CAAC,OAAO,CAAC,CAW5B;AAED;;;;;GAKG;AACH,qDAFa,OAAO,CAAC,GAAC,CAAC,CAiBtB;AAED;;;;;;;;;GASG;AACH,0GAFa,OAAO,CAAC,UAAU,GAAC,UAAU,EAAE,CAAC,CAW5C;AAGD;;;;;;;;;;;;GAYG;AACH,kLAFa,OAAO,CAAC,OAAO,CAAC,CA8F5B"}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { i18nCollect } from './i18n-collect.js';
|
|
2
|
+
import { setAuthKey } from './i18n-deepl.js';
|
|
3
|
+
import { getSupportedLanguages } from './i18n-deepl.js';
|
|
4
|
+
import { translateTexts } from './i18n-deepl.js';
|
|
5
|
+
import { translateToJSON } from './i18n-deepl.js';
|
|
6
|
+
export { i18nCollect, setAuthKey, getSupportedLanguages, translateTexts, translateToJSON };
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":"4BAA0B,mBAAmB;2BACoC,iBAAiB;sCAAjB,iBAAiB;+BAAjB,iBAAiB;gCAAjB,iBAAiB"}
|
package/want.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
- isolate function from cli
|
|
2
|
+
- use commander
|
|
3
|
+
- make auto translation
|
|
4
|
+
|
|
5
|
+
API Key
|
|
6
|
+
0d520e59-eea9-24e7-908f-b2184b3039bb:fx
|
|
7
|
+
|
|
8
|
+
```shell
|
|
9
|
+
i18n-deepl setAuth 0d520e59-eea9-24e7-908f-b2184b3039bb:fx
|
|
10
|
+
```
|
|
11
|
+
```shell
|
|
12
|
+
i18n-deepl translate de.json en.json en
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
i18n-deepl translate de.json en.json en --auth-key=0d520e59-eea9-24e7-908f-b2184b3039bb:fx
|
|
17
|
+
|
|
18
|
+
i18n-deepl translate de.json de.json fr --source-sub=translations.de
|