Skip to content
This repository was archived by the owner on Sep 8, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 39 additions & 22 deletions packages/cms/lib/modules/openstad-global/lib/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,47 +13,64 @@ const translatorConfig = { maxRetries: 5, minTimeout: 10000 };
module.exports = (self, options) => {

self.translate = (req, res) => {
let deeplAuthKey = options.deeplKey;
let content = req.body.contents;
let origin = req.body.origin;
const deeplAuthKey = options.deeplKey;
const content = req.body.contents;
const origin = req.body.origin;
const sourceLanguageCode = req.body.sourceLanguageCode;
const destinationLanguage = req.body.targetLanguageCode;

const cacheKey = crypto.createHash('sha256').update(`${destinationLanguage}${origin}${JSON.stringify(content)}`).digest('hex');

if (!origin) {
res.status(400).send('Could not determine the page to translate');
return res.status(400).json({ error: 'Could not determine the page to translate' });
}

const destinationLanguage = req.body.targetLanguageCode;
const cacheKey = crypto.createHash('sha256').update(`${destinationLanguage}${origin}${JSON.stringify(content)}`).digest('hex');
let result = cache.get(cacheKey);
const result = cache.get(cacheKey);

if (result) {
console.log("Receiving translations from cache");
return res.json(result);
}

// content should always be a collection of dutch terms, translations to other languages are translated from dutch to (for example) english
if (destinationLanguage === 'nl') {
console.log("Target language is dutch, not translating and responding with the dutch sentences received");
return res.json(content);
}


if (deeplAuthKey) {
let translator = null;

try {
const translator = new deepl.Translator(deeplAuthKey, translatorConfig);
translator = new deepl.Translator(deeplAuthKey, translatorConfig);
} catch (error) {
console.log({ error });
return res.status(500).json({ error: 'Could not translate the page at this time' });
}

if (translator) {
translator.translateText(
content,
req.body.sourceLanguageCode,
req.body.targetLanguageCode,
)
.then(response => {
cache.set(`${cacheKey}`, response, {
life: cacheLifespan
})
return res.json(response);
})
.catch(error => console.log({ error }));
} catch (error) {
console.log({ translationError: error });
sourceLanguageCode,
destinationLanguage,
).then(response => {
cache.set(`${cacheKey}`, response, {
life: cacheLifespan
});
return res.json(response);
})
.catch(error => {
console.error({ error });
return res.status(500).json({ error: 'Error while translating the page' });
});
}
} else {
res.status(400).send('No valid key provided');
return res.status(400).json({ error: 'No valid key provided' });
}
}

self.apos.app.post('/modules/openstad-global/translate', function(req, res){
self.apos.app.post('/modules/openstad-global/translate', function (req, res) {
self.translate(req, res);
});

Expand Down
28 changes: 17 additions & 11 deletions packages/cms/lib/modules/openstad-global/public/js/always.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
apos.on('ready', function() {
apos.on('ready', function () {
var nodes = [];
const selectedLanguage = sessionStorage.getItem("targetLanguageCode");
var selectedLanguage = sessionStorage.getItem("targetLanguageCode");

if(selectedLanguage && selectedLanguage !== 'nl') {
nodes = handleNode(document.body, nodes);
const nlContents = nodes.map(function(itemToTranslate) { return itemToTranslate.orgText });
/**
* The translate widget if set on the page will trigger an onchange event when it has been loaded
* thus triggering the fetching of translations. Then this one should do nothing and let the dedicated
* widget make the call.
*/
var translationWidgetOnSamePage = $('.translation-widget-select').length > 0;

if (!translationWidgetOnSamePage && selectedLanguage && selectedLanguage !== 'nl') {
nodes = handleNode(document.body, nodes);
var nlContents = nodes.map(function (itemToTranslate) { return itemToTranslate.orgText });
$.ajax({
url: '/modules/openstad-global/translate',
method: 'post',
Expand All @@ -17,30 +23,30 @@ apos.on('ready', function() {
origin: window.location.href
}),
success: function (sentences) {
sentences = sentences.map(function(sentence) { return sentence.text });
sentences = sentences.map(function (sentence) { return sentence.text });
changeTextInNodes(sentences, nodes);
},
},
});
}
});

changeTextInNodes = function (sentences, nodes) {
sentences.forEach(function(sentence, index) {
sentences.forEach(function (sentence, index) {
nodes[index].node.textContent = sentence;
});
}

handleNode = function (node, toBeTranslated) {
const childNodes = node.childNodes;
var childNodes = node.childNodes;
for (var i = 0; i < childNodes.length; i++) {
if (childNodes[i].nodeType == Node.ELEMENT_NODE) {
var nodeName = childNodes[i].nodeName.toLowerCase();
if (nodeName != 'script' && nodeName != 'style') {
handleNode(childNodes[i], toBeTranslated);
}
} else if (childNodes[i].nodeType == Node.TEXT_NODE) {
const parentElement = childNodes[i].parentElement;
const shouldTranslate = parentElement && parentElement.getAttribute('translate') !== 'no';
var parentElement = childNodes[i].parentElement;
var shouldTranslate = parentElement && parentElement.getAttribute('translate') !== 'no';

if (shouldTranslate) {
var textContent = childNodes[i].textContent;
Expand Down
8 changes: 5 additions & 3 deletions packages/cms/lib/modules/translation-widgets/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
const styleSchema = require('../../../config/styleSchema.js').default;
const crypto = require('crypto');
const deepl = require('deepl-node');
const cache = require('../../../services/cache').cache;
const cacheLifespan = 8 * 60 * 60; // set lifespan of 8 hours;
const cacheLanguagesLifespan = (24 * 60 * 60) * 7; // set lifespan of language cache to a week;
const translatorConfig = { maxRetries: 5, minTimeout: 10000 };

Expand Down Expand Up @@ -63,13 +61,17 @@ module.exports = {
supportedLanguages = languages.map((language, index) => {
language['code'] = supportedLanguages[index].code;
return language;
})
});

cache.set(`${cacheKeyForLanguages}`, supportedLanguages, {
life: cacheLanguagesLifespan
});
});
} catch(error) {
supportedLanguages = supportedLanguages.map((language, index) => {
language['text'] = supportedLanguages[index].name;
return language;
})
console.error({translationError: error});
}
} else {
Expand Down
22 changes: 15 additions & 7 deletions packages/cms/lib/modules/translation-widgets/public/js/always.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ apos.define('translation-widgets', {
var nodes = [];
var nlContents = [];

const languageSelectContainer = $('.language-select-container');
var languageSelectContainer = $('.language-select-container');

$('.translation-widget-select')
.on('change', function (e) { return changeLanguage(e) });
Expand All @@ -28,18 +28,16 @@ apos.define('translation-widgets', {
function saveLanguagePreference(targetLanguageCode) {
try{
sessionStorage.setItem("targetLanguageCode", targetLanguageCode);
console.log("Saved language preference");
} catch(quotaExceededError) {
console.log("Could not save the language preference");
}
}

changeLanguage = function (e) {
const select = e.target;
const targetLanguageCode = select.value;
var select = e.target;
var targetLanguageCode = select.value;
setSelectDisabled(select);

console.log('translate to', targetLanguageCode);

var node = document.body;

Expand All @@ -50,10 +48,12 @@ apos.define('translation-widgets', {
}

if (targetLanguageCode === 'nl') {
console.log("Language is set to the default: " + targetLanguageCode +". No need to translate");
changeTextInNodes(nlContents, nodes);
setSelectEnabled(select);
saveLanguagePreference(targetLanguageCode);
} else {
console.log('translating to', targetLanguageCode);
$.ajax({
url: '/modules/translation-widgets/submit',
method: 'POST',
Expand All @@ -72,14 +72,22 @@ apos.define('translation-widgets', {
},
error: function() {
setSelectEnabled(select);
setSelectedLanguage('nl');
}
})
}
};
}
});

function setSelectedLanguage(language) {
$('.translation-widget-select').val(language ? language : 'nl').trigger('change');
}

/**
* Makes a call to the backend to translate. This needs to happen to set the initial selection after rendering the page,
* collecting the initial values and if the language is not the default 'nl', fetching the translations
*/
apos.on('ready', function() {
const selectedLanguage = sessionStorage.getItem('targetLanguageCode');
$('.translation-widget-select').val(selectedLanguage ? selectedLanguage : 'nl').trigger('change');
setSelectedLanguage(sessionStorage.getItem('targetLanguageCode'));
});