From 09c09e9ec1f61fa3fb8ac88b6cb5f3db2eafe4ac Mon Sep 17 00:00:00 2001 From: Henrixounez Date: Fri, 27 Dec 2024 16:27:24 +0100 Subject: [PATCH 1/4] feat: omit placeholders plugin option --- providers/deepl/README.md | 2 ++ providers/deepl/lib/__tests__/deepl.test.js | 21 ++++++++++++++++++++ providers/deepl/lib/index.js | 22 +++++++++++++++++++-- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/providers/deepl/README.md b/providers/deepl/README.md index d958809e..d356b6ed 100644 --- a/providers/deepl/README.md +++ b/providers/deepl/README.md @@ -21,6 +21,8 @@ module.exports = { // use uppercase here! EN: 'EN-US', }, + // controls if placeholder text inside double curly brackets should be omitted from translation + omitPlaceholders: false, apiOptions: { // see for supported options. // note that tagHandling Mode cannot be set this way. diff --git a/providers/deepl/lib/__tests__/deepl.test.js b/providers/deepl/lib/__tests__/deepl.test.js index d3eb191f..b57ba412 100644 --- a/providers/deepl/lib/__tests__/deepl.test.js +++ b/providers/deepl/lib/__tests__/deepl.test.js @@ -395,6 +395,27 @@ describe('deepl provider', () => { await expect(deeplProvider.usage()).resolves.toBeTruthy() }) + it('omits placeholders when option used', async () => { + server.use(http.post(`${DEEPL_PAID_API}/translate`, translateHandler)) + + const deeplProvider = provider.init({ + apiKey: authKey, + omitPlaceholders: true, + }) + + // given + const params = { + sourceLocale: 'en', + targetLocale: 'de', + text: 'Some text with a placeholder {{placeholder}} in it and an {{other}} one', + } + // when + const result = await deeplProvider.translate(params) + + // then + expect(result).toEqual([params.text]) + }) + describe('api options used', () => { const registerHandlerEnforceParams = ( requiredParams, diff --git a/providers/deepl/lib/index.js b/providers/deepl/lib/index.js index ad403bac..f92c2884 100644 --- a/providers/deepl/lib/index.js +++ b/providers/deepl/lib/index.js @@ -31,6 +31,7 @@ module.exports = { typeof providerOptions.apiOptions === 'object' ? providerOptions.apiOptions : {} + const omitPlaceholders = providerOptions.omitPlaceholders || false const client = new deepl.Translator(apiKey, { serverUrl: apiUrl, @@ -77,12 +78,23 @@ module.exports = { let textArray = Array.isArray(input) ? input : [input] + let placeholderTexts = []; + + if (omitPlaceholders) { + textArray = textArray.map((text) => + text.replace(/{{(.*?)}}/g, (match) => { + placeholderTexts.push(match) + return `` + }) + ) + } + const { chunks, reduceFunction } = chunksService.split(textArray, { maxLength: DEEPL_API_MAX_TEXTS, maxByteSize: DEEPL_API_ROUGH_MAX_REQUEST_SIZE, }) - const result = reduceFunction( + let result = reduceFunction( await Promise.all( chunks.map(async (texts) => { const result = await rateLimitedTranslate.withOptions( @@ -101,7 +113,13 @@ module.exports = { }) ) ) - + + if (omitPlaceholders) { + result = result.map((text) => + text.replace(//g, (_, id) => placeholderTexts[id]) + ) + } + if (format === 'jsonb') { return formatService.htmlToBlock(result) } From 46f468ed9889c25f0358ee3cec925ea30dcd5048 Mon Sep 17 00:00:00 2001 From: Henrixounez Date: Wed, 19 Mar 2025 14:39:10 +0100 Subject: [PATCH 2/4] feat: handle multiple glossaries --- providers/deepl/lib/index.js | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/providers/deepl/lib/index.js b/providers/deepl/lib/index.js index f92c2884..a0f7e72f 100644 --- a/providers/deepl/lib/index.js +++ b/providers/deepl/lib/index.js @@ -45,6 +45,22 @@ module.exports = { const rateLimitedTranslate = limiter.wrap(client.translateText.bind(client)) + let availableGlossaries = []; + let lastGlossariesFetch = new Date(); + + const fetchGlossaries = async () => { + availableGlossaries = await client.listGlossaries(); + lastGlossariesFetch = new Date(); + } + const findGlossary = providerOptions.findGlossary || ((glossaries, sourceLocale, targetLocale) => { + return glossaries.find((glossary) => + glossary.sourceLang === sourceLocale && glossary.targetLang === targetLocale + ); + }); + + if (providerOptions.fetchGlossaries) + fetchGlossaries(); + return { /** * @param {{ @@ -94,6 +110,14 @@ module.exports = { maxByteSize: DEEPL_API_ROUGH_MAX_REQUEST_SIZE, }) + let glossary = undefined; + + if (providerOptions.fetchGlossaries) { + if (new Date() - lastGlossariesFetch > (providerOptions.fetchGlossariesIntervalMs || 3600000)) + await fetchGlossaries(); + glossary = findGlossary(availableGlossaries, sourceLocale, targetLocale); + } + let result = reduceFunction( await Promise.all( chunks.map(async (texts) => { @@ -107,7 +131,7 @@ module.exports = { texts, parseLocale(sourceLocale, localeMap, 'source'), parseLocale(targetLocale, localeMap, 'target'), - { ...apiOptions, tagHandling } + { ...apiOptions, tagHandling, glossary: glossary?.glossaryId } ) return result.map((value) => value.text) }) From 5d74f54605a65faeafb9f610d1a91578365d0f61 Mon Sep 17 00:00:00 2001 From: Laurane Sevin Date: Wed, 19 Mar 2025 14:39:51 +0100 Subject: [PATCH 3/4] feat: omit placeholder tags in translation --- providers/deepl/lib/index.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/providers/deepl/lib/index.js b/providers/deepl/lib/index.js index a0f7e72f..427d89f3 100644 --- a/providers/deepl/lib/index.js +++ b/providers/deepl/lib/index.js @@ -32,6 +32,7 @@ module.exports = { ? providerOptions.apiOptions : {} const omitPlaceholders = providerOptions.omitPlaceholders || false + const omitTags = providerOptions.omitTags || false const client = new deepl.Translator(apiKey, { serverUrl: apiUrl, @@ -95,6 +96,7 @@ module.exports = { let textArray = Array.isArray(input) ? input : [input] let placeholderTexts = []; + let placeholderTags = []; if (omitPlaceholders) { textArray = textArray.map((text) => @@ -105,6 +107,15 @@ module.exports = { ) } + if (omitTags) { + textArray = textArray.map((text) => + text.replace(/<\/?[^>]+(>|$)/g, (match) => { + placeholderTags.push(match) + return `` + }) + ) + } + const { chunks, reduceFunction } = chunksService.split(textArray, { maxLength: DEEPL_API_MAX_TEXTS, maxByteSize: DEEPL_API_ROUGH_MAX_REQUEST_SIZE, @@ -144,6 +155,12 @@ module.exports = { ) } + if (omitTags) { + result = result.map((text) => + text.replace(//g, (_, id) => placeholderTags[id]) + ) + } + if (format === 'jsonb') { return formatService.htmlToBlock(result) } From 2366bd39476ad330ec6ca87cf065592a142efcd7 Mon Sep 17 00:00:00 2001 From: Henrixounez Date: Wed, 27 Aug 2025 17:05:07 +0200 Subject: [PATCH 4/4] fix: omit placeholder / tags mismatch --- providers/deepl/lib/index.js | 18 +++++++++--------- providers/deepl/package.json | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/providers/deepl/lib/index.js b/providers/deepl/lib/index.js index e04a0b5a..5f669196 100644 --- a/providers/deepl/lib/index.js +++ b/providers/deepl/lib/index.js @@ -102,20 +102,20 @@ module.exports = { let placeholderTexts = []; let placeholderTags = []; - if (omitPlaceholders) { + if (omitTags) { textArray = textArray.map((text) => - text.replace(/{{(.*?)}}/g, (match) => { - placeholderTexts.push(match) - return `` + text.replace(/<\/?[^>]+(>|$)/g, (match) => { + placeholderTags.push(match) + return `` }) ) } - if (omitTags) { + if (omitPlaceholders) { textArray = textArray.map((text) => - text.replace(/<\/?[^>]+(>|$)/g, (match) => { - placeholderTags.push(match) - return `` + text.replace(/{{(.*?)}}/g, (match) => { + placeholderTexts.push(match) + return `` }) ) } @@ -144,7 +144,7 @@ module.exports = { glossary = findGlossary(availableGlossaries, sourceLocale, targetLocale)?.glossaryId || glossary; } - const result = reduceFunction( + let result = reduceFunction( await Promise.all( chunks.map(async (texts) => { const result = await rateLimitedTranslate.withOptions( diff --git a/providers/deepl/package.json b/providers/deepl/package.json index 6b21fc4c..edafacb2 100644 --- a/providers/deepl/package.json +++ b/providers/deepl/package.json @@ -1,6 +1,6 @@ { - "name": "strapi-provider-translate-deepl", - "version": "1.2.7", + "name": "strapi-provider-translate-deepl-lokki", + "version": "1.2.9", "description": "DeepL provider for translate plugin in Strapi 4", "keywords": [ "strapi",