Usuari:Forat Negre/softcatala-traductor.js
Aparença
El codi que afegiu en aquesta pàgina podria tenir contingut maliciós que comprometi el vostre compte. Si no esteu segur si el codi a afegir és segur, pregunteu abans en la Taverna. El codi s'executarà en mostrar una previsualització d'aquesta pàgina. |
Nota: Després de desar, heu de netejar la memòria cau del navegador per veure els canvis. En la majoria de navegadors amb Windows o Linux, premeu Ctrl+F5 o bé premeu Shift i cliqueu el botó "Actualitza" (Ctrl i "Actualitza" amb Internet Explorer). Vegeu més informació i instruccions per a cada navegador a Viquipèdia:Neteja de la memòria cau.
//<nowiki>
/* softcatala-traductor.js
--------------------------------
Versió actual: 1.2
Autors: Forat Negre, Wecoc
--------------------------------
>> Introducció
Aquest codi afegeix un botó "Softcatalà" a la pàgina de traducció d'articles.
Utilitza el traductor neuronal de Softcatalà per traduir cada paràgraf.
Podeu trobar el traductor al següent enllaç
https://www.softcatala.org/traductor/
>> Registre de canvis
Versió 1.0 [14 de juliol 2022]
* Botó principal afegit a la barra dreta de la pàgina
* Traducció disponible en tots els idiomes del traductor Softcatalà
Versió 1.1 [16 de juliol 2022]
* Solucionat error intern d'obtenció del paràgraf actual
Versió 1.2 [19 de juliol 2022]
* Traducció bàsica de format implementada [negreta, enllaços, referències...]
* Afegit mode "Testing mode" per poder fer proves de traducció sense risc
* Solucionat error intern de memòria cau
>> Coses pendents / Errors
* Només permet traducció si tens activat "Copia el contingut original"
*/
/* Carregar el codi només a la pàgina de traduccions */
$(function() {
setTimeout(function() {
if (window.location.href.includes("Special:ContentTranslation")) {
importSoftcatalaButton();
}
}, 5000);
});
function importSoftcatalaButton() {
// ------------------------------------------------------
// Defineix aquí si vols utilitzar el mode de proves
// En fer-ho, elimina el botó "Publica" i mostra les funcions emprades a la consola
var testingMode = false;
// ------------------------------------------------------
if (testingMode) {
console.log("Import Softcatalà Button");
document.querySelector('.ve-ui-toolbar-group-publish').style.display = "none";
}
/* Definir CSS personalitzat */
var css = '.softcatala_button {' +
' background: #777;' +
' color: #bbb;' +
' cursor: pointer;' +
' user-select: none;' +
' padding: 10px;' +
' font-weight: 700;' +
' font-size: 16px;' +
' }' +
' .softcatala_button.active {' +
' background: #c81e2b;' +
' color: #fff;' +
' }' +
' .softcatala_button.active:hover {' +
' background: #e7414e;' +
' }' +
' .softcatala_button.disabled, .ve-cx-toolbar-mt .ve-cx-toolbar-mt-title {' +
' display: none;' +
' }';
/* Importar el CSS a la pàgina actual */
var head = document.head || document.getElementsByTagName('head')[0],
style = document.createElement('style');
style.type = 'text/css';
style.appendChild(document.createTextNode(css));
head.appendChild(style);
/* Crear botó Softcatalà */
var toolbar = document.querySelector('.ve-cx-toolbar-mt'); if (!toolbar) return;
var softcatala_button = document.createElement("div");
$(softcatala_button).addClass("softcatala_button");
softcatala_button.innerText = "Softcatalà";
toolbar.insertBefore(softcatala_button, toolbar.firstChild);
/* Si el traductor no té la llengua disponible, desactivar el botó */
var sourceLanguage = mw.cx.sourceLanguage, targetLanguage = mw.cx.targetLanguage;
var availableLangs = {
/* Principals */
'ca':'cat', // Català
'en':'en', // Anglès
'de':'deu', // Alemany
'oc':'oc', // Occità
'ro':'ron', // Romanès
'fr':'fr', // Francès
'pt':'pt', // Portuguès
'an':'arg', // Aragonès
'nl':'nld', // Neerlandès
'it':'ita', // Italià
/* Altres */
'es':'spa', // Espanyol
'simple':'en' // Anglès simplificat
};
sourceLanguage = availableLangs[sourceLanguage];
targetLanguage = availableLangs[targetLanguage];
if (!sourceLanguage || !targetLanguage) {
softcatala_button.addClass("disabled");
}
/* Obtenir el traductor seleccionat */
function readCurrentTranslator() {
var c = document.querySelector('.oo-ui-toolGroup-tools .oo-ui-tool-active');
var veTarget = mw.cx.tools.IssueTrackingTool.prototype.getVeTarget();
var tools = Object.keys(veTarget.actionsToolbar.target.mtToolbar.tools);
for (var t in tools) {
if (c.classList.contains("oo-ui-tool-name-" + tools[t])) return tools[t];
}
return undefined;
}
/* Activar el botó només en mode "Copia el contingut original" */
function updateSoftcatalaButton() {
setTimeout(function() {
var button = document.querySelector('.softcatala_button');
if (readCurrentTranslator() == "source") {
$(button).addClass("active");
} else {
$(button).removeClass("active");
}
updateSoftcatalaButton();
}, 100);
}
updateSoftcatalaButton();
/* Funció de clicar el botó */
softcatala_button.addEventListener("click", function(e) {
/* Si el botó està desactivat o inactiu, no fer res */
if (this.classList.contains("disabled")) return;
if (readCurrentTranslator() != "source") return;
/* Anar a la secció del text corresponent */
var activeNodes = document.querySelectorAll('.ve-ce-activeNode-active'),
targetNode = activeNodes[activeNodes.length - 1],
sectionId = targetNode.id,
sectionNumber = sectionId.match(/cxTargetSection(\d*)/)[1],
sourceNode = document.getElementById("cxSourceSection" + sectionNumber),
neuronal_json_url = 'https://api.softcatala.org/v2/nmt/translate/';
/* Obtenir el contingut a traduir per cada paràgraf */
var sourceChildren = sourceNode.firstChild.children;
var targetChildren = targetNode.firstChild.children;
var blockMode = true;
if (sourceChildren.length == targetChildren.length) {
if (targetChildren.length > 0) {
if (targetChildren[0].className.includes("cx-segment")) {
blockMode = false;
}
}
}
/* Si el nombre de paràgrafs coincideix, fer-ho per parts */
var waitForTranslation = [];
if (!blockMode) {
for (var i = 0; i < sourceChildren.length; i++) {
waitForTranslation.push(i);
applySoftcatalaTranslation(i, sourceChildren[i].cloneNode(true), blockMode);
}
/* Si el nombre de paràgrafs no coincideix, aplicar en un únic bloc */
} else {
waitForTranslation.push(0);
applySoftcatalaTranslation(0, sourceNode.cloneNode(true), blockMode);
}
/* Up cop feta la traducció, guardar-la a la memòria cau */
setTimeout(saveTranslationToQueue(), 200);
/* Obtenir traducció de SoftCatalà mitjançant Ajax */
function applySoftcatalaTranslation(spanIndex, source, blockMode) {
if (testingMode) console.log("Apply Softcatala Translation");
if (blockMode) {
var blocks = source.firstChild.children;
for (var i = 0; i < blocks.length; i++) {
filterFormatFromSource(blocks[i]);
}
} else {
filterFormatFromSource(source);
}
var content = source.innerText;
$.ajax({
url: neuronal_json_url,
type: "POST",
data : {
'langpair': sourceLanguage + "|" + targetLanguage,
'q': content,
'savetext': false
},
dataType: 'json',
spanIndex: spanIndex,
success : function(data) {
if (data.responseStatus == 200) {
var result = data.responseData.translatedText, target;
if (blockMode) {
target = targetNode.firstChild;
} else {
target = targetChildren[this.spanIndex];
}
applyFormatFromProvider(result, "Apertium", target, this.spanIndex, blockMode);
}
}
});
}
/* Versió de l'Ajax lliure per traduir text independent de l'article */
function applySoftcatalaTranslationText(content) {
if (testingMode) console.log("Apply Softcatala Translation Text");
return $.ajax({
url: neuronal_json_url,
type: "POST",
data : {
'langpair': sourceLanguage + "|" + targetLanguage,
'q': content,
'savetext': false
},
dataType: 'json',
});
}
/* Guardar els canvis a la memòria cau */
function saveTranslationToQueue() {
setTimeout(function() {
if (waitForTranslation.length == 0) {
if (testingMode) console.log("Save Translation To Queue");
var veTarget = mw.cx.tools.IssueTrackingTool.prototype.getVeTarget();
var section = veTarget.getTargetSectionNodeFromSectionNumber(sectionNumber);
veTarget.setSectionContent(section, targetNode.outerHTML, "source");
veTarget.emit('changeContentSource', sectionNumber);
} else {
saveTranslationToQueue();
}
}, 100);
}
/* Filtrar el format innecessari per la traducció (referències i altres elements) */
function filterFormatFromSource(source) {
if (testingMode) console.log("Filter Format From Source");
var removePool = [];
for (var i = 0; i < source.children.length; i++) {
var child = source.children[i];
var readableLocalNames = ["b", "i", "a"];
if (!readableLocalNames.includes(child.localName)) {
removePool.push(child);
}
}
for (var r in removePool) { source.removeChild(removePool[r]); }
}
/* Aplicar el format utilitzant la traducció d'Apertium de referència, ja que Softcatalà no té aquesta opció */
function applyFormatFromProvider(content, provider, target, spanIndex, blockMode) {
if (testingMode) console.log("Apply Format From Provider");
var veTarget = mw.cx.tools.IssueTrackingTool.prototype.getVeTarget(), result = {content: content};
veTarget.translateSection("cxSourceSection" + sectionNumber, "Apertium").then(function(data) {
var segments = $('.cx-segment', data), s, c, currentSegment;
if (!blockMode) {
if (segments.length > 1) {
currentSegment = segments[spanIndex];
} else {
currentSegment = segments[0];
}
if (currentSegment !== undefined) {
for (c = 0; c < currentSegment.children.length; c++) {
applyFormatToChild(currentSegment.children[c], result);
}
}
} else {
for (s = 0; s < segments.length; s++) {
for (c = 0; c < segments[s].children.length; c++) {
applyFormatToChild(segments[s].children[c], result);
}
}
}
setTimeout(function() {
result.content += " ";
target.innerHTML = result.content;
waitForTranslation.splice(waitForTranslation.indexOf(spanIndex));
}, 1000);
});
}
/* Aplicar el format cas per cas */
function applyFormatToChild(child, result) {
var readableLocalNames = ["b", "i", "a"];
if (readableLocalNames.includes(child.localName)) {
locateTargetFormat(result, child);
} else {
result.content += child.outerHTML;
}
}
/* Localitzar estils de text */
function locateTargetFormat(result, translatedSource) {
if (testingMode) console.log("Locate Target Format");
var source = document.getElementById(translatedSource.id);
applySoftcatalaTranslationText(source.innerText).then(function(data) {
if (data.responseStatus == 200) {
var newText = data.responseData.translatedText;
var regex = new RegExp("(\\s|^)(\\w*(" + newText + ")\\w*)(\\s|$)", "im");
var match = result.content.match(regex);
if (match) {
var matchedText = match[2];
translatedSource.innerText = matchedText;
result.content = result.content.replace(matchedText, translatedSource.outerHTML);
}
}
});
}
});
}
//</nowiki>