MediaWiki:CommonTranslate.js: differenze tra le versioni
Nessun oggetto della modifica Etichetta: Annullato |
Nessun oggetto della modifica Etichetta: Ripristino manuale |
||
| (5 versioni intermedie di uno stesso utente non sono mostrate) | |||
| Riga 1: | Riga 1: | ||
/* ======================= CommonTranslate.js ( | /* ======================= CommonTranslate.js (versione con proxy, stesso flusso) ======================= */ | ||
console.log("🔄 Caricamento CommonTranslate. | console.log("🔄 Caricamento CommonTranslate.js..."); | ||
/ | // ✅ Evita ricaricamento multiplo | ||
if (window.CommonTranslateLoaded) { | if (window.CommonTranslateLoaded) { | ||
console.warn("⚠️ CommonTranslate.js è già stato caricato."); | |||
} else { | } else { | ||
window.CommonTranslateLoaded = true; | |||
// ✅ Lingua origine (fallback su html lang o en) | |||
window.linguaOrigine = document.documentElement.lang || "en"; | |||
// ❌ Niente API key nel browser | |||
// ✅ Definisci solo il modello (verrà usato dal proxy; se vuoto userà il default server) | |||
window.openaiModel = window.openaiModel || "gpt-4o"; | |||
// ✅ Endpoint proxy sul server (cameriere) | |||
window.OPENAI_PROXY_URL = "/dashboard/api/openai_project_gpt.php"; | |||
console.log("✅ CommonTranslate.js caricato correttamente (via proxy)."); | |||
} | } | ||
/* ======================= | /* ======================= Funzione principale ======================= */ | ||
async function traduciTesto() { | async function traduciTesto() { | ||
const area = document.getElementById("wpTextbox1"); | const area = document.getElementById("wpTextbox1"); | ||
if (!area) { alert(" | if (!area) { alert("❌ Editor non trovato."); return; } | ||
const start = area.selectionStart; | const start = area.selectionStart; | ||
const end = area.selectionEnd; | const end = area.selectionEnd; | ||
const | const testoSelezionato = area.value.slice(start, end).trim(); | ||
const tutto = ! | const tutto = !testoSelezionato; | ||
// | // ✅ Chiedi cosa tradurre | ||
const | const conferma = confirm("📝 Vuoi tradurre SOLO il testo selezionato?\n\n✅ OK = solo selezione\n❌ Annulla = tutto il testo"); | ||
if ( | if (conferma && !testoSelezionato) { | ||
alert("⚠️ Nessuna | alert("⚠️ Nessuna parte selezionata. Se vuoi tradurre tutto, premi Annulla."); | ||
return; | return; | ||
} | } | ||
// | const testo = tutto ? area.value : testoSelezionato; | ||
const | if (!testo.trim()) { alert("⚠️ Niente da tradurre."); return; } | ||
"🌍 Scegli la lingua di traduzione | |||
// ✅ STEP 1: Lingua | |||
const lingueDisponibili = ["it", "en", "fr", "es", "de"]; | |||
let linguaScelta = prompt( | |||
"🌍 Scegli la lingua di traduzione:\n\nit = Italiano\nen = Inglese\nfr = Francese\nes = Spagnolo\nde = Tedesco", | |||
"it" | "it" | ||
); | ); | ||
if (! | if (!linguaScelta) { | ||
console.warn("⚠️ Nessuna lingua selezionata."); | |||
return; | |||
} | |||
// | // ✅ STEP 2: Segmentazione | ||
const blocchi = segmentaTesto(testo); | const blocchi = segmentaTesto(testo); | ||
console.log(`🧩 Segmentazione: ${blocchi.length} blocchi`); | console.log(`🧩 Segmentazione: ${blocchi.length} blocchi trovati`); | ||
if (tutto) { | if (tutto) { | ||
// 🔍 STEP 3: Analisi segmentazione + popup | |||
const errori = analizzaErroriSegmentazione(blocchi); | const errori = analizzaErroriSegmentazione(blocchi); | ||
sostituisciTestoSegmentato(blocchi, errori); | sostituisciTestoSegmentato(blocchi, errori); | ||
mostraPopupConferma(blocchi, errori, | mostraPopupConferma(blocchi, errori, [linguaScelta], tutto); | ||
return; // la traduzione | return; // ⛔️ blocco qui: la traduzione partirà dal popup | ||
} | } | ||
// | // ✅ STEP 3: Traduzione (passa il parametro `tutto`) | ||
const tradotto = await inviaTraduzione(blocchi, | const tradotto = await inviaTraduzione(blocchi, linguaScelta, tutto); | ||
// | // ✅ STEP 4: Inserimento nel campo editor | ||
if (tutto) { | if (tutto) { | ||
area.value = tradotto; | area.value = tradotto; | ||
| Riga 60: | Riga 73: | ||
const prima = area.value.slice(0, start); | const prima = area.value.slice(0, start); | ||
const dopo = area.value.slice(end); | const dopo = area.value.slice(end); | ||
area.value | area.value = prima + tradotto + dopo; | ||
area.selectionStart = start; | area.selectionStart = start; | ||
area.selectionEnd = start + tradotto.length; | area.selectionEnd = start + tradotto.length; | ||
} | } | ||
// | // ✅ STEP 5: Notifica | ||
area.dispatchEvent(new Event("input", | area.dispatchEvent(new Event("input", { bubbles: true })); | ||
area.dispatchEvent(new Event("change", { bubbles: true })); | area.dispatchEvent(new Event("change", { bubbles: true })); | ||
console.log("✅ Traduzione completata e inserita."); | console.log("✅ Traduzione completata e inserita correttamente."); | ||
} | } | ||
/* ======================= | /* ======================= Funzioni di supporto ======================= */ | ||
function segmentaTesto(testo, | function ottieniTestoDaEditor() { | ||
const area = document.getElementById("wpTextbox1"); | |||
const | return area ? area.value.trim() : null; | ||
} | |||
function ottieniTestoSelezionato() { | |||
const area = document.getElementById("wpTextbox1"); | |||
if (!area) return null; | |||
return area.value.substring(area.selectionStart, area.selectionEnd).trim() || null; | |||
} | |||
function segmentaTesto(testo, maxToken = 3000) { | |||
console.log("📌 Segmentazione in corso con max", maxToken, "tokens..."); | |||
const blocchi = testo.match(new RegExp(`.{1,${maxToken}}(?=\\s|$)`, "gs")) || []; | |||
return blocchi; | |||
} | } | ||
function analizzaErroriSegmentazione(blocchi) { | function analizzaErroriSegmentazione(blocchi) { | ||
let errori = []; | |||
const count = (s, | blocchi.forEach((blocco, i) => { | ||
let err = []; | |||
const count = (s, c) => (s.match(new RegExp(`\\${c}`, 'g')) || []).length; | |||
const parentesi = [["[", "]"], ["{", "}"], ["<", ">"]]; | |||
parentesi.forEach(([open, close]) => { | |||
let openCount = count(blocco, open); | |||
if ( | let closeCount = count(blocco, close); | ||
if (openCount !== closeCount) { | |||
err.push(`Parentesi ${open}${close} non bilanciate: ${openCount} ${open}, ${closeCount} ${close}`); | |||
} | |||
}); | }); | ||
if ( | if (err.length > 0) { | ||
errori.push({ index: i + 1, dettagli: err }); | |||
} | |||
}); | }); | ||
return | return errori; | ||
} | } | ||
function sostituisciTestoSegmentato(blocchi, errori) { | function sostituisciTestoSegmentato(blocchi, errori) { | ||
const area = document.getElementById("wpTextbox1"); | const area = document.getElementById("wpTextbox1"); | ||
if (!area) return; | if (!area) { | ||
const | console.warn("⚠️ Campo wpTextbox1 non trovato per sostituzione."); | ||
const err = errori.find( | return; | ||
const | } | ||
return `${ | const blocchiSegnalati = blocchi.map((b, i) => { | ||
}).join("\n\n==============================\n\n") | const err = errori.find(e => e.index === i + 1); | ||
const erroreText = err ? `⚠️ ERRORI:\n- ${err.dettagli.join("\n- ")}\n\n` : ""; | |||
console.log("✍️ Testo segmentato | return `${erroreText}🔹 BLOCCO ${i + 1}\n` + b; | ||
}); | |||
area.value = blocchiSegnalati.join("\n\n==============================\n\n"); | |||
console.log("✍️ Testo segmentato sostituito nel campo wpTextbox1"); | |||
} | } | ||
function mostraPopupConferma(blocchi, errori, | function mostraPopupConferma(blocchi, errori, lingueDaTradurre, tutto) { | ||
const popup = document.createElement("div"); | const popup = document.createElement("div"); | ||
popup.id = "popup-conferma-traduzione"; | popup.id = "popup-conferma-traduzione"; | ||
popup.style = ` | popup.style = ` | ||
position: fixed; bottom: 20px; right: 20px; | position: fixed; bottom: 20px; right: 20px; | ||
background: | background: white; padding: 15px; border: 2px solid #444; | ||
box-shadow: 4px 4px 10px rgba(0,0,0,.3); z-index: 9999; | box-shadow: 4px 4px 10px rgba(0,0,0,0.3); z-index: 9999; | ||
resize: both; overflow: auto; cursor: move; | |||
`; | `; | ||
popup.innerHTML = ` | popup.innerHTML = ` | ||
<b>✅ Segmentazione completata</b><br> | <b>✅ Segmentazione completata</b><br> | ||
🧠 Token stimati: ~${blocchi.length * 3000}<br> | |||
${errori.length ? `<span style= | 💰 Costo approssimativo: ~$${(blocchi.length * 3000 * 0.00002).toFixed(2)}<br> | ||
<button id="btn-invia-traduzione">✅ Invia | ${errori.length > 0 ? `❗ <span style='color:red;'>${errori.length} errori rilevati. Procedere comunque?</span><br>` : `<span style='color:green;'>✅ Nessun errore rilevato</span><br>`} | ||
<button | <button id="btn-invia-traduzione">✅ Invia</button> | ||
<button onclick="this.parentNode.remove()">❌ Annulla</button> | |||
`; | `; | ||
document.body.appendChild(popup); | document.body.appendChild(popup); | ||
dragElement(popup); | |||
document.getElementById("btn-invia-traduzione").onclick = async () => { | document.getElementById("btn-invia-traduzione").onclick = async () => { | ||
popup.remove(); | popup.remove(); | ||
try { await inviaTraduzione(blocchi, | console.log("📤 Invio confermato: avvio traduzione…"); | ||
catch (e) { | try { | ||
console.error("❌ Errore invio traduzione:", e); | await inviaTraduzione(blocchi, lingueDaTradurre[0], tutto); | ||
alert("Errore durante | } catch (e) { | ||
console.error("❌ Errore nell'invio della traduzione:", e); | |||
alert("Errore durante l'invio a OpenAI (via proxy):\n" + e.message); | |||
} | } | ||
}; | }; | ||
} | } | ||
/* ======================= | function dragElement(elmnt) { | ||
let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; | |||
elmnt.onmousedown = dragMouseDown; | |||
function dragMouseDown(e) { | |||
e = e || window.event; e.preventDefault(); | |||
pos3 = e.clientX; pos4 = e.clientY; | |||
document.onmouseup = closeDragElement; | |||
document.onmousemove = elementDrag; | |||
} | |||
function elementDrag(e) { | |||
e = e || window.event; e.preventDefault(); | |||
pos1 = pos3 - e.clientX; pos2 = pos4 - e.clientY; | |||
pos3 = e.clientX; pos4 = e.clientY; | |||
elmnt.style.top = (elmnt.offsetTop - pos2) + "px"; | |||
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px"; | |||
} | |||
function closeDragElement() { | |||
document.onmouseup = null; | |||
document.onmousemove = null; | |||
} | |||
} | |||
/* ======================= Invio traduzione (usa il CAMERIERE) ======================= */ | |||
async function inviaTraduzione(blocchi, lingua, tutto = true) { | async function inviaTraduzione(blocchi, lingua, tutto = true) { | ||
const | const model = window.openaiModel || "gpt-4o"; | ||
let testoTradotto = ""; | |||
console.log("🧪 Avvio inviaTraduzione() via proxy"); | |||
console.log(" | console.log("📦 Blocchi ricevuti:", blocchi.length, "| 🌍 Lingua:", lingua); | ||
for (let i = 0; i < blocchi.length; i++) { | for (let i = 0; i < blocchi.length; i++) { | ||
console.log(`🚀 Invio blocco ${i + 1}/${blocchi.length}…`); | console.log(`🚀 Invio blocco ${i + 1}/${blocchi.length}…`); | ||
let tradotto = await traduciBloccoProxy(blocchi[i], lingua, model); | |||
testoTradotto += (tradotto || "[Errore Traduzione]") + "\n\n"; | |||
} | } | ||
const | const area = document.getElementById("wpTextbox1"); | ||
if (!area) { console.warn("❌ Campo wpTextbox1 non trovato!"); return ""; } | |||
const start = area.selectionStart; | |||
const end = area.selectionEnd; | |||
if (tutto) { | if (tutto) { | ||
area.value = | area.value = testoTradotto.trim(); | ||
} else { | } else { | ||
const prima = area.value.slice(0, start); | const prima = area.value.slice(0, start); | ||
const dopo = area.value.slice(end); | const dopo = area.value.slice(end); | ||
area.value | area.value = prima + testoTradotto.trim() + dopo; | ||
area.selectionStart = start; | area.selectionStart = start; | ||
area.selectionEnd = start + | area.selectionEnd = start + testoTradotto.trim().length; | ||
} | } | ||
area.dispatchEvent(new Event("input", | area.dispatchEvent(new Event("input", { bubbles: true })); | ||
area.dispatchEvent(new Event("change", { bubbles: true })); | area.dispatchEvent(new Event("change", { bubbles: true })); | ||
console.log("✅ Traduzione completata."); | console.log("✅ Traduzione completata."); | ||
return | return testoTradotto.trim(); | ||
} | } | ||
async function traduciBloccoProxy(blocco, lingua) { | /* ======================= Traduzione BLOCCO → via proxy ======================= */ | ||
async function traduciBloccoProxy(blocco, lingua, model) { | |||
try { | |||
const istruzioni = [ | |||
"You are a professional MediaWiki translator.", | |||
"Translate the text preserving templates, links, headings, lists and any wiki syntax.", | |||
"Do not add comments or explanations.", | |||
`Source language: ${window.linguaOrigine}. Target language: ${lingua}.` | |||
].join(" "); | |||
const prompt = `${istruzioni}\n\n--- TEXT START ---\n${blocco}\n--- TEXT END ---`; | |||
const res = await fetch(window.OPENAI_PROXY_URL, { | |||
const res = await fetch( | |||
method: "POST", | method: "POST", | ||
headers: { "Content-Type": "application/json" }, | headers: { "Content-Type": "application/json" }, | ||
body: JSON.stringify({ | body: JSON.stringify({ prompt, model }) | ||
}); | }); | ||
const data = await res.json().catch(() => ({})); | const data = await res.json().catch(() => ({})); | ||
if (!res.ok || data.status | if (!res.ok || data.status === "error") { | ||
const msg = data?.error || `HTTP ${res.status}`; | const msg = data?.error || `HTTP ${res.status}`; | ||
console.error("❌ Errore da proxy:", msg); | |||
return "[Errore Traduzione]"; | |||
} | } | ||
return data.result || ""; | |||
return | |||
} catch (err) { | } catch (err) { | ||
console.error("❌ Errore | console.error("❌ Errore durante traduzione (proxy):", err); | ||
return "[Errore Traduzione]"; | return "[Errore Traduzione]"; | ||
} | } | ||
} | } | ||
/* ======================= | /* ======================= Pulsante sotto editor ======================= */ | ||
$(function () { | $(function () { | ||
if (!document.getElementById("wpTextbox1")) return; | |||
if ( | if (document.getElementById("pulsanteTraduci")) return; | ||
$("#wpTextbox1").after('<button id="pulsanteTraduci" class="btn">🧠 Traduci contenuto</button>'); | |||
$("#pulsanteTraduci").on("click", traduciTesto); | |||
}); | }); | ||
Versione attuale delle 11:54, 6 dic 2025
/* ======================= CommonTranslate.js (versione con proxy, stesso flusso) ======================= */
console.log("🔄 Caricamento CommonTranslate.js...");
// ✅ Evita ricaricamento multiplo
if (window.CommonTranslateLoaded) {
console.warn("⚠️ CommonTranslate.js è già stato caricato.");
} else {
window.CommonTranslateLoaded = true;
// ✅ Lingua origine (fallback su html lang o en)
window.linguaOrigine = document.documentElement.lang || "en";
// ❌ Niente API key nel browser
// ✅ Definisci solo il modello (verrà usato dal proxy; se vuoto userà il default server)
window.openaiModel = window.openaiModel || "gpt-4o";
// ✅ Endpoint proxy sul server (cameriere)
window.OPENAI_PROXY_URL = "/dashboard/api/openai_project_gpt.php";
console.log("✅ CommonTranslate.js caricato correttamente (via proxy).");
}
/* ======================= Funzione principale ======================= */
async function traduciTesto() {
const area = document.getElementById("wpTextbox1");
if (!area) { alert("❌ Editor non trovato."); return; }
const start = area.selectionStart;
const end = area.selectionEnd;
const testoSelezionato = area.value.slice(start, end).trim();
const tutto = !testoSelezionato;
// ✅ Chiedi cosa tradurre
const conferma = confirm("📝 Vuoi tradurre SOLO il testo selezionato?\n\n✅ OK = solo selezione\n❌ Annulla = tutto il testo");
if (conferma && !testoSelezionato) {
alert("⚠️ Nessuna parte selezionata. Se vuoi tradurre tutto, premi Annulla.");
return;
}
const testo = tutto ? area.value : testoSelezionato;
if (!testo.trim()) { alert("⚠️ Niente da tradurre."); return; }
// ✅ STEP 1: Lingua
const lingueDisponibili = ["it", "en", "fr", "es", "de"];
let linguaScelta = prompt(
"🌍 Scegli la lingua di traduzione:\n\nit = Italiano\nen = Inglese\nfr = Francese\nes = Spagnolo\nde = Tedesco",
"it"
);
if (!linguaScelta) {
console.warn("⚠️ Nessuna lingua selezionata.");
return;
}
// ✅ STEP 2: Segmentazione
const blocchi = segmentaTesto(testo);
console.log(`🧩 Segmentazione: ${blocchi.length} blocchi trovati`);
if (tutto) {
// 🔍 STEP 3: Analisi segmentazione + popup
const errori = analizzaErroriSegmentazione(blocchi);
sostituisciTestoSegmentato(blocchi, errori);
mostraPopupConferma(blocchi, errori, [linguaScelta], tutto);
return; // ⛔️ blocco qui: la traduzione partirà dal popup
}
// ✅ STEP 3: Traduzione (passa il parametro `tutto`)
const tradotto = await inviaTraduzione(blocchi, linguaScelta, tutto);
// ✅ STEP 4: Inserimento nel campo editor
if (tutto) {
area.value = tradotto;
} else {
const prima = area.value.slice(0, start);
const dopo = area.value.slice(end);
area.value = prima + tradotto + dopo;
area.selectionStart = start;
area.selectionEnd = start + tradotto.length;
}
// ✅ STEP 5: Notifica
area.dispatchEvent(new Event("input", { bubbles: true }));
area.dispatchEvent(new Event("change", { bubbles: true }));
console.log("✅ Traduzione completata e inserita correttamente.");
}
/* ======================= Funzioni di supporto ======================= */
function ottieniTestoDaEditor() {
const area = document.getElementById("wpTextbox1");
return area ? area.value.trim() : null;
}
function ottieniTestoSelezionato() {
const area = document.getElementById("wpTextbox1");
if (!area) return null;
return area.value.substring(area.selectionStart, area.selectionEnd).trim() || null;
}
function segmentaTesto(testo, maxToken = 3000) {
console.log("📌 Segmentazione in corso con max", maxToken, "tokens...");
const blocchi = testo.match(new RegExp(`.{1,${maxToken}}(?=\\s|$)`, "gs")) || [];
return blocchi;
}
function analizzaErroriSegmentazione(blocchi) {
let errori = [];
blocchi.forEach((blocco, i) => {
let err = [];
const count = (s, c) => (s.match(new RegExp(`\\${c}`, 'g')) || []).length;
const parentesi = [["[", "]"], ["{", "}"], ["<", ">"]];
parentesi.forEach(([open, close]) => {
let openCount = count(blocco, open);
let closeCount = count(blocco, close);
if (openCount !== closeCount) {
err.push(`Parentesi ${open}${close} non bilanciate: ${openCount} ${open}, ${closeCount} ${close}`);
}
});
if (err.length > 0) {
errori.push({ index: i + 1, dettagli: err });
}
});
return errori;
}
function sostituisciTestoSegmentato(blocchi, errori) {
const area = document.getElementById("wpTextbox1");
if (!area) {
console.warn("⚠️ Campo wpTextbox1 non trovato per sostituzione.");
return;
}
const blocchiSegnalati = blocchi.map((b, i) => {
const err = errori.find(e => e.index === i + 1);
const erroreText = err ? `⚠️ ERRORI:\n- ${err.dettagli.join("\n- ")}\n\n` : "";
return `${erroreText}🔹 BLOCCO ${i + 1}\n` + b;
});
area.value = blocchiSegnalati.join("\n\n==============================\n\n");
console.log("✍️ Testo segmentato sostituito nel campo wpTextbox1");
}
function mostraPopupConferma(blocchi, errori, lingueDaTradurre, tutto) {
const popup = document.createElement("div");
popup.id = "popup-conferma-traduzione";
popup.style = `
position: fixed; bottom: 20px; right: 20px;
background: white; padding: 15px; border: 2px solid #444;
box-shadow: 4px 4px 10px rgba(0,0,0,0.3); z-index: 9999;
resize: both; overflow: auto; cursor: move;
`;
popup.innerHTML = `
<b>✅ Segmentazione completata</b><br>
🧠 Token stimati: ~${blocchi.length * 3000}<br>
💰 Costo approssimativo: ~$${(blocchi.length * 3000 * 0.00002).toFixed(2)}<br>
${errori.length > 0 ? `❗ <span style='color:red;'>${errori.length} errori rilevati. Procedere comunque?</span><br>` : `<span style='color:green;'>✅ Nessun errore rilevato</span><br>`}
<button id="btn-invia-traduzione">✅ Invia</button>
<button onclick="this.parentNode.remove()">❌ Annulla</button>
`;
document.body.appendChild(popup);
dragElement(popup);
document.getElementById("btn-invia-traduzione").onclick = async () => {
popup.remove();
console.log("📤 Invio confermato: avvio traduzione…");
try {
await inviaTraduzione(blocchi, lingueDaTradurre[0], tutto);
} catch (e) {
console.error("❌ Errore nell'invio della traduzione:", e);
alert("Errore durante l'invio a OpenAI (via proxy):\n" + e.message);
}
};
}
function dragElement(elmnt) {
let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
elmnt.onmousedown = dragMouseDown;
function dragMouseDown(e) {
e = e || window.event; e.preventDefault();
pos3 = e.clientX; pos4 = e.clientY;
document.onmouseup = closeDragElement;
document.onmousemove = elementDrag;
}
function elementDrag(e) {
e = e || window.event; e.preventDefault();
pos1 = pos3 - e.clientX; pos2 = pos4 - e.clientY;
pos3 = e.clientX; pos4 = e.clientY;
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
}
function closeDragElement() {
document.onmouseup = null;
document.onmousemove = null;
}
}
/* ======================= Invio traduzione (usa il CAMERIERE) ======================= */
async function inviaTraduzione(blocchi, lingua, tutto = true) {
const model = window.openaiModel || "gpt-4o";
let testoTradotto = "";
console.log("🧪 Avvio inviaTraduzione() via proxy");
console.log("📦 Blocchi ricevuti:", blocchi.length, "| 🌍 Lingua:", lingua);
for (let i = 0; i < blocchi.length; i++) {
console.log(`🚀 Invio blocco ${i + 1}/${blocchi.length}…`);
let tradotto = await traduciBloccoProxy(blocchi[i], lingua, model);
testoTradotto += (tradotto || "[Errore Traduzione]") + "\n\n";
}
const area = document.getElementById("wpTextbox1");
if (!area) { console.warn("❌ Campo wpTextbox1 non trovato!"); return ""; }
const start = area.selectionStart;
const end = area.selectionEnd;
if (tutto) {
area.value = testoTradotto.trim();
} else {
const prima = area.value.slice(0, start);
const dopo = area.value.slice(end);
area.value = prima + testoTradotto.trim() + dopo;
area.selectionStart = start;
area.selectionEnd = start + testoTradotto.trim().length;
}
area.dispatchEvent(new Event("input", { bubbles: true }));
area.dispatchEvent(new Event("change", { bubbles: true }));
console.log("✅ Traduzione completata.");
return testoTradotto.trim();
}
/* ======================= Traduzione BLOCCO → via proxy ======================= */
async function traduciBloccoProxy(blocco, lingua, model) {
try {
const istruzioni = [
"You are a professional MediaWiki translator.",
"Translate the text preserving templates, links, headings, lists and any wiki syntax.",
"Do not add comments or explanations.",
`Source language: ${window.linguaOrigine}. Target language: ${lingua}.`
].join(" ");
const prompt = `${istruzioni}\n\n--- TEXT START ---\n${blocco}\n--- TEXT END ---`;
const res = await fetch(window.OPENAI_PROXY_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ prompt, model })
});
const data = await res.json().catch(() => ({}));
if (!res.ok || data.status === "error") {
const msg = data?.error || `HTTP ${res.status}`;
console.error("❌ Errore da proxy:", msg);
return "[Errore Traduzione]";
}
return data.result || "";
} catch (err) {
console.error("❌ Errore durante traduzione (proxy):", err);
return "[Errore Traduzione]";
}
}
/* ======================= Pulsante sotto editor ======================= */
$(function () {
if (!document.getElementById("wpTextbox1")) return;
if (document.getElementById("pulsanteTraduci")) return;
$("#wpTextbox1").after('<button id="pulsanteTraduci" class="btn">🧠 Traduci contenuto</button>');
$("#pulsanteTraduci").on("click", traduciTesto);
});