From 986c442af7b919a71fd1b719646c934ca214ea3f Mon Sep 17 00:00:00 2001 From: Felix Wolff Date: Mon, 6 Nov 2017 16:01:58 +0100 Subject: [PATCH] chore: update tests, mocks, examples and docs --- README.md | 44 ++++++++++++++++- __tests__/deepl-translator.test.js | 47 +++++++++++++++++- example.js | 20 +++++++- src/__mocks__/fixtures/alternative-map.js | 23 +++++++++ src/__mocks__/fixtures/split-map.js | 10 ++++ .../fixtures/translation-beginning-map.js | 20 ++++++++ src/__mocks__/request-helper.js | 48 +++++++++++++++++-- 7 files changed, 205 insertions(+), 7 deletions(-) create mode 100644 src/__mocks__/fixtures/alternative-map.js create mode 100644 src/__mocks__/fixtures/translation-beginning-map.js diff --git a/README.md b/README.md index 129a974..8656558 100644 --- a/README.md +++ b/README.md @@ -66,12 +66,30 @@ translate( ) .then(res => console.log(`Translation: ${res.translation}, Resolved languages: ${res.resolvedSourceLanguage}`)) .catch(console.error); + + // Get alternatives for words in translated sentences + { + const text = 'Die Übersetzungsqualität von deepl ist erstaunlich!'; + // Translates to: 'The translation quality of deepl is amazing!' + wordAlternatives(text, 'EN', 'DE', 'The translation') + .then(res => { + console.log(`3 Alternative beginnings:`); + res.alternatives.slice(0, 3).forEach(el => console.log(el)); + // Choose third alternetive + return res.alternatives[2]; + }) + .then(beginning => { + // Request translation with selected alternative beginning + return translate(text, 'EN', 'DE', beginning); + }) + .then(res => console.log(`Alternative: ${res.translation}`)); + } ``` ## API -### translate(text, targetLanguage, sourceLanguage) -> `object` -This method translated the input text into a specified target language. Source language can be autodetected. +### translate(text, targetLanguage, sourceLanguage, beginning) -> `object` +This method translates the input text into a specified target language. Source language can be autodetected. Optionally, a sentence beginning can be given (should only be used in conjunction with `wordAlternatives`). **text** (`string`) *Input text to be translated* @@ -79,6 +97,8 @@ This method translated the input text into a specified target language. Source l **sourceLanguage** (`string`) *Language code of the input text language. Can be left out or set to `auto` for automatic language detection.* +**beginning** (`string`) *Desired beginning of the translation (should only be used in conjunction with `wordAlternatives`)* + **Returns** ```javascript { @@ -101,6 +121,26 @@ This method detects the language of the input text. } ``` +### wordAlternatives(text, targetLanguage, sourceLanguage, beginning) -> `object` +This method suggests alternative words for a translation of the input text. None of the languages can be autodetected. Normally, this method will be used after translating the input text using `translate`, because `beginning` must be the beginning of a translation. + +**text** (`string`) *Input text to be translated* + +**targetLanguage** (`string`) *Language code of the language to translate to* + +**sourceLanguage** (`string`) *Language code of the input text language* + +**beginning** (`string`) *Beginning of the translation of `text`. The method searches an alternative for the following word.* + +**Returns** +```javascript +{ + targetLanguage: 'XY', // Language code of the language that was translate to + resolvedSourceLanguage: 'YZ', // Language code of the input language + alternatives: ['an alternative', 'an other alternative'], // Array of alternative sentence beginnings +} +``` + ## License Apache License 2.0 diff --git a/__tests__/deepl-translator.test.js b/__tests__/deepl-translator.test.js index 05c7c1b..f3a1027 100644 --- a/__tests__/deepl-translator.test.js +++ b/__tests__/deepl-translator.test.js @@ -1,6 +1,10 @@ jest.mock('../src/request-helper'); -const { translate, detectLanguage } = require('../src/deepl-translator'); +const { + translate, + detectLanguage, + wordAlternatives, +} = require('../src/deepl-translator'); test('Detects english input language correctly', () => { return expect( @@ -44,6 +48,21 @@ Fifth.`, }); }); +test('Create translation with a fixed beginning', () => { + return expect( + translate( + 'Die Übersetzungsqualität von deepl ist erstaunlich!', + 'EN', + 'DE', + 'The translation performance' + ) + ).resolves.toEqual({ + resolvedSourceLanguage: 'DE', + targetLanguage: 'EN', + translation: 'The translation performance of deepl is amazing!', + }); +}); + test('Rejects on invalid target language', () => { return expect(translate('Happy birthday!')).rejects.toEqual( new Error('Invalid target language code undefined') @@ -90,3 +109,29 @@ test('Rejects when split response in incorrect format', () => { ) ); }); + +test('Get alternative beginnings of a sentence', () => { + const text = 'Die Übersetzungsqualität von deepl ist erstaunlich!'; + // Translates to: 'The translation quality of deepl is amazing!' + return expect( + wordAlternatives(text, 'EN', 'auto', 'The translation') + ).resolves.toEqual({ + targetLanguage: 'EN', + resolvedSourceLanguage: 'DE', + alternatives: [ + 'The translation quality', + 'The translation of deepl', + 'The translation performance', + ], + }); +}); + +test('Rejects when requesting alternative beginning without beginning', () => { + return expect( + wordAlternatives( + 'Die Übersetzungsqualität von deepl ist erstaunlich!', + 'EN', + 'DE' + ) + ).rejects.toEqual(new Error('Beginning cannot be undefined')); +}); diff --git a/example.js b/example.js index 8e500c8..9fb7aba 100644 --- a/example.js +++ b/example.js @@ -1,4 +1,4 @@ -const { translate, detectLanguage } = require('./index'); +const { translate, detectLanguage, wordAlternatives } = require('./index'); // Translate text with explicit source and target languages translate('Die Übersetzungsqualität von deepl ist erstaunlich!', 'EN', 'DE') @@ -28,3 +28,21 @@ translate( ) .then(res => console.log(`Translation: ${res.translation}`)) .catch(console.error); + +// Request alternative translations for a single word +{ + const text = 'Die Übersetzungsqualität von deepl ist erstaunlich!'; + // Translates to: 'The translation quality of deepl is amazing!' + wordAlternatives(text, 'EN', 'DE', 'The translation') + .then(res => { + console.log(`Alternative beginnings:`); + res.alternatives.slice(0, 3).forEach(el => console.log(el)); + // Choose third alternetive + return res.alternatives[2]; + }) + .then(beginning => { + // Request translation with selected alternative beginning + return translate(text, 'EN', 'DE', beginning); + }) + .then(res => console.log(`Alternative: ${res.translation}`)); +} diff --git a/src/__mocks__/fixtures/alternative-map.js b/src/__mocks__/fixtures/alternative-map.js new file mode 100644 index 0000000..dff2024 --- /dev/null +++ b/src/__mocks__/fixtures/alternative-map.js @@ -0,0 +1,23 @@ +module.exports = { + 'The translation': { + result: { + source_lang: 'DE', + target_lang: 'EN', + translations: [ + { + beams: [ + { + postprocessed_sentence: 'The translation quality', + }, + { + postprocessed_sentence: 'The translation of deepl', + }, + { + postprocessed_sentence: 'The translation performance', + }, + ], + }, + ], + }, + }, +}; diff --git a/src/__mocks__/fixtures/split-map.js b/src/__mocks__/fixtures/split-map.js index 4498160..4833da5 100644 --- a/src/__mocks__/fixtures/split-map.js +++ b/src/__mocks__/fixtures/split-map.js @@ -52,4 +52,14 @@ module.exports = { ], }, }, + + 'Die Übersetzungsqualität von deepl ist erstaunlich!': { + id: 1, + jsonrpc: '2.0', + result: { + lang: 'DE', + lang_is_confident: 1, + splitted_texts: [['Die Übersetzungsqualität von deepl ist erstaunlich!']], + }, + }, }; diff --git a/src/__mocks__/fixtures/translation-beginning-map.js b/src/__mocks__/fixtures/translation-beginning-map.js new file mode 100644 index 0000000..99db268 --- /dev/null +++ b/src/__mocks__/fixtures/translation-beginning-map.js @@ -0,0 +1,20 @@ +module.exports = { + 'Die Übersetzungsqualität von deepl ist erstaunlich!': { + 'The translation performance': { + result: { + source_lang: 'DE', + target_lang: 'EN', + translations: [ + { + beams: [ + { + postprocessed_sentence: + 'The translation performance of deepl is amazing!', + }, + ], + }, + ], + }, + }, + }, +}; diff --git a/src/__mocks__/request-helper.js b/src/__mocks__/request-helper.js index 15dc7d8..8d341b0 100644 --- a/src/__mocks__/request-helper.js +++ b/src/__mocks__/request-helper.js @@ -1,5 +1,7 @@ const translationMap = require('./fixtures/translation-map'); const splitMap = require('./fixtures/split-map'); +const alternativeMap = require('./fixtures/alternative-map'); +const translationBeginningMap = require('./fixtures/translation-beginning-map'); function handleSplitSentences(options, postBody) { return new Promise((resolve, reject) => { @@ -27,8 +29,48 @@ function handleTranslateJobs(options, postBody) { }); } +function handleTranslateBeginningJobs(options, postBody) { + return new Promise((resolve, reject) => { + const { + params: { + jobs: [ + { raw_en_sentence: inputText, de_sentence_beginning: beginning }, + ], + }, + } = postBody; + + process.nextTick( + () => + !translationBeginningMap[inputText][beginning] + ? reject(new Error('This input should throw up')) + : resolve(translationBeginningMap[inputText][beginning]) + ); + }); +} + +function handleAlternativeJobs(option, postBody) { + return new Promise((resolve, reject) => { + const { + params: { jobs: [{ de_sentence_beginning: beginning }] }, + } = postBody; + + process.nextTick( + () => + !alternativeMap[beginning] + ? reject(new Error('This input should throw')) + : resolve(alternativeMap[beginning]) + ); + }); +} + module.exports = (options, postBody) => { - return postBody.method === 'LMT_split_into_sentences' - ? handleSplitSentences(options, postBody) - : handleTranslateJobs(options, postBody); + if (postBody.method === 'LMT_split_into_sentences') { + return handleSplitSentences(options, postBody); + } + if (postBody.params.jobs[0].kind === 'default') { + return postBody.params.jobs[0].de_sentence_beginning === '' + ? handleTranslateJobs(options, postBody) + : handleTranslateBeginningJobs(options, postBody); + } + return handleAlternativeJobs(options, postBody); };