Nessun oggetto della modifica
Etichetta: Annullato
Nessun oggetto della modifica
Etichetta: Annullato
Riga 1: Riga 1:
/* ======================= CommonTranslate.js (solo via proxy) ======================= */
/* ======================= CommonTranslate.js (versione stabile precedente) ======================= */
console.log("🔄 Caricamento CommonTranslate.js…");
console.log("🔄 Caricamento CommonTranslate.js…");


// Evita ricarichi multipli
// Evita doppio caricamento
if (window.__CommonTranslateLoaded) {
if (window.__CommonTranslateLoaded) {
   console.warn("⚠️ CommonTranslate.js è già stato caricato.");
   console.warn("⚠️ CommonTranslate.js è già stato caricato.");
Riga 8: Riga 8:
   window.__CommonTranslateLoaded = true;
   window.__CommonTranslateLoaded = true;


   // URL del proxy lato server (non mettere la chiave nel browser!)
   // Manteniamo la vecchia struttura con pulsante
  const PROXY_URL = "/w/proxy.php";
 
  // Modello di default (puoi cambiarlo qui o da window.openaiModel)
   const DEFAULT_MODEL = (window.openaiModel || "gpt-4o");
   const DEFAULT_MODEL = (window.openaiModel || "gpt-4o");
  const LINGUA_ORIGINE = document.documentElement.lang || "en";


   // Lingua di origine (fallback)
   // 🔑 QUI usi ancora la chiave diretta (come avevi prima) → se preferisci il proxy si cambia solo questo pezzo
   const LINGUA_ORIGINE = document.documentElement.lang || "en";
   const API_URL = "https://api.openai.com/v1/chat/completions";
  const API_KEY = window.apiKey || "INSERISCI_LA_TUA_API_KEY";


   console.log("✅ CommonTranslate.js pronto (via proxy). Modello:", DEFAULT_MODEL);
   console.log("✅ CommonTranslate.js caricato. Modello:", DEFAULT_MODEL);


  /* ======================= UTILITIES ======================= */
   function getEditor() {
   function getEditor() {
     return document.getElementById("wpTextbox1");
     return document.getElementById("wpTextbox1");
   }
   }
   function getSelectedTextInfo() {
   function getSelectedTextInfo() {
     const area = getEditor();
     const area = getEditor();
Riga 31: Riga 30:
     return { text, start, end };
     return { text, start, end };
   }
   }
   function segmentaTesto(testo, maxChars = 3000) {
   function segmentaTesto(testo, maxChars = 3000) {
    // Segmenti “morbidi” a limite caratteri su spazio
     const re = new RegExp(`.{1,${maxChars}}(?=\\s|$)`, "gs");
     const re = new RegExp(`.{1,${maxChars}}(?=\\s|$)`, "gs");
     return testo.match(re) || [];
     return testo.match(re) || [];
   }
   }


  // Chiamata singolo blocco al proxy
   async function traduciBlocco(blocco, lingua, model = DEFAULT_MODEL) {
   async function traduciBloccoProxy(blocco, lingua, model = DEFAULT_MODEL) {
     try {
     try {
       const res = await fetch(PROXY_URL, {
       const res = await fetch(API_URL, {
         method: "POST",
         method: "POST",
         headers: { "Content-Type": "application/json" },
         headers: {
          "Content-Type": "application/json",
          "Authorization": `Bearer ${API_KEY}`
        },
         body: JSON.stringify({
         body: JSON.stringify({
           model,
           model,
Riga 62: Riga 63:
       const data = await res.json();
       const data = await res.json();
       if (!res.ok) {
       if (!res.ok) {
         const msg = data?.error || `HTTP ${res.status}`;
         const msg = data?.error?.message || `HTTP ${res.status}`;
         throw new Error(msg);
         throw new Error(msg);
       }
       }
       const content = data?.choices?.[0]?.message?.content ?? "";
       return data?.choices?.[0]?.message?.content ?? "[Traduzione vuota]";
      return content || "[Traduzione vuota]";
     } catch (err) {
     } catch (err) {
       console.error("❌ Errore da proxy:", err);
       console.error("❌ Errore traduzione:", err);
       return "[Errore Traduzione via proxy]";
       return "[Errore Traduzione]";
     }
     }
   }
   }
Riga 83: Riga 83:
     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}…`);
       const tradotto = await traduciBloccoProxy(blocchi[i], lingua);
       const tradotto = await traduciBlocco(blocchi[i], lingua);
       risultato += tradotto.trim() + "\n\n";
       risultato += tradotto.trim() + "\n\n";
     }
     }
Riga 99: Riga 99:
     }
     }


    // Notifica a MediaWiki
     area.dispatchEvent(new Event("input", { bubbles: true }));
     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.");
   }
   }


  /* ======================= FLOW PRINCIPALE ======================= */
   async function traduciTesto() {
   async function traduciTesto() {
     const area = getEditor();
     const area = getEditor();
Riga 114: Riga 112:
     }
     }


    // Solo selezione o tutto?
     const { text: selezione } = getSelectedTextInfo();
     const { text: selezione } = getSelectedTextInfo();
     const conferma = confirm(
     const conferma = confirm(
       "📝 Vuoi tradurre SOLO il testo selezionato?\n\n✅ OK = solo selezione\n❌ Annulla = tutto il testo"
       "Vuoi tradurre SOLO il testo selezionato?\n\n✅ OK = solo selezione\n❌ Annulla = tutto il testo"
     );
     );
     if (conferma && !selezione) {
     if (conferma && !selezione) {
       alert("⚠️ Nessuna selezione. Premi Annulla per tradurre tutto il testo.");
       alert("⚠️ Nessuna selezione trovata.");
       return;
       return;
     }
     }
Riga 129: Riga 126:
     }
     }


    // Lingua destinazione
     const lingua = prompt("🌍 Scegli lingua di traduzione (es: it, en, fr, es, de):", "it");
     const lingua = prompt(
      "🌍 Scegli la lingua di traduzione (es: it, en, fr, es, de):",
      "it"
    );
     if (!lingua) return;
     if (!lingua) return;


    // Segmentazione e invio
     const blocchi = segmentaTesto(testo);
     const blocchi = segmentaTesto(testo);
     console.log("🧩 Segmentazione:", blocchi.length, "blocchi");
     console.log("🧩 Segmenti:", blocchi.length);
     await inviaTraduzione(blocchi, lingua, !conferma);
     await inviaTraduzione(blocchi, lingua, !conferma);
   }
   }


   /* ======================= UI: PULSANTE ======================= */
   // Pulsante sotto editor
  // Aggiunge un bottone sotto l’editor
   function addTranslateButton() {
   function addTranslateButton() {
     const area = getEditor();
     const area = getEditor();
Riga 152: Riga 143:
     btn.id = "btnCommonTranslate";
     btn.id = "btnCommonTranslate";
     btn.className = "mw-ui-button";
     btn.className = "mw-ui-button";
     btn.textContent = "🧠 Traduci contenuto (via proxy)";
     btn.textContent = "🧠 Traduci contenuto";
     btn.style.margin = "8px 0";
     btn.style.margin = "8px 0";
     btn.addEventListener("click", traduciTesto);
     btn.addEventListener("click", traduciTesto);
Riga 159: Riga 150:
   }
   }


  // jQuery ready + fallback
   if (typeof $ !== "undefined") {
   if (typeof $ !== "undefined") {
     $(addTranslateButton);
     $(addTranslateButton);

Versione delle 14:17, 18 ago 2025

/* ======================= CommonTranslate.js (versione stabile precedente) ======================= */
console.log("🔄 Caricamento CommonTranslate.js…");

// Evita doppio caricamento
if (window.__CommonTranslateLoaded) {
  console.warn("⚠️ CommonTranslate.js è già stato caricato.");
} else {
  window.__CommonTranslateLoaded = true;

  // Manteniamo la vecchia struttura con pulsante
  const DEFAULT_MODEL = (window.openaiModel || "gpt-4o");
  const LINGUA_ORIGINE = document.documentElement.lang || "en";

  // 🔑 QUI usi ancora la chiave diretta (come avevi prima) → se preferisci il proxy si cambia solo questo pezzo
  const API_URL = "https://api.openai.com/v1/chat/completions";
  const API_KEY = window.apiKey || "INSERISCI_LA_TUA_API_KEY";

  console.log("✅ CommonTranslate.js caricato. Modello:", DEFAULT_MODEL);

  function getEditor() {
    return document.getElementById("wpTextbox1");
  }

  function getSelectedTextInfo() {
    const area = getEditor();
    if (!area) return { text: "", start: 0, end: 0 };
    const start = area.selectionStart;
    const end = area.selectionEnd;
    const text = area.value.slice(start, end);
    return { text, start, end };
  }

  function segmentaTesto(testo, maxChars = 3000) {
    const re = new RegExp(`.{1,${maxChars}}(?=\\s|$)`, "gs");
    return testo.match(re) || [];
  }

  async function traduciBlocco(blocco, lingua, model = DEFAULT_MODEL) {
    try {
      const res = await fetch(API_URL, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "Authorization": `Bearer ${API_KEY}`
        },
        body: JSON.stringify({
          model,
          messages: [
            {
              role: "system",
              content:
                "You are a professional MediaWiki translator. Translate preserving templates, links, headings, lists and any wiki syntax. Do not add explanations."
            },
            {
              role: "user",
              content: `Translate the following text from ${LINGUA_ORIGINE} to ${lingua}:\n\n${blocco}`
            }
          ],
          temperature: 0
        })
      });

      const data = await res.json();
      if (!res.ok) {
        const msg = data?.error?.message || `HTTP ${res.status}`;
        throw new Error(msg);
      }
      return data?.choices?.[0]?.message?.content ?? "[Traduzione vuota]";
    } catch (err) {
      console.error("❌ Errore traduzione:", err);
      return "[Errore Traduzione]";
    }
  }

  async function inviaTraduzione(blocchi, lingua, sostituisciTutto) {
    const area = getEditor();
    if (!area) {
      alert("❌ Campo editor non trovato (wpTextbox1).");
      return;
    }

    let risultato = "";
    for (let i = 0; i < blocchi.length; i++) {
      console.log(`🚀 Invio blocco ${i + 1}/${blocchi.length}…`);
      const tradotto = await traduciBlocco(blocchi[i], lingua);
      risultato += tradotto.trim() + "\n\n";
    }
    risultato = risultato.trim();

    if (sostituisciTutto) {
      area.value = risultato;
    } else {
      const { start, end } = getSelectedTextInfo();
      const prima = area.value.slice(0, start);
      const dopo = area.value.slice(end);
      area.value = prima + risultato + dopo;
      area.selectionStart = start;
      area.selectionEnd = start + risultato.length;
    }

    area.dispatchEvent(new Event("input", { bubbles: true }));
    area.dispatchEvent(new Event("change", { bubbles: true }));

    console.log("✅ Traduzione completata.");
  }

  async function traduciTesto() {
    const area = getEditor();
    if (!area) {
      alert("❌ Editor non trovato.");
      return;
    }

    const { text: selezione } = getSelectedTextInfo();
    const conferma = confirm(
      "Vuoi tradurre SOLO il testo selezionato?\n\n✅ OK = solo selezione\n❌ Annulla = tutto il testo"
    );
    if (conferma && !selezione) {
      alert("⚠️ Nessuna selezione trovata.");
      return;
    }
    const testo = conferma ? selezione : area.value;
    if (!testo.trim()) {
      alert("⚠️ Niente da tradurre.");
      return;
    }

    const lingua = prompt("🌍 Scegli lingua di traduzione (es: it, en, fr, es, de):", "it");
    if (!lingua) return;

    const blocchi = segmentaTesto(testo);
    console.log("🧩 Segmenti:", blocchi.length);
    await inviaTraduzione(blocchi, lingua, !conferma);
  }

  // Pulsante sotto editor
  function addTranslateButton() {
    const area = getEditor();
    if (!area) return;
    if (document.getElementById("btnCommonTranslate")) return;

    const btn = document.createElement("button");
    btn.id = "btnCommonTranslate";
    btn.className = "mw-ui-button";
    btn.textContent = "🧠 Traduci contenuto";
    btn.style.margin = "8px 0";
    btn.addEventListener("click", traduciTesto);

    area.parentNode.insertBefore(btn, area.nextSibling);
  }

  if (typeof $ !== "undefined") {
    $(addTranslateButton);
  } else {
    document.addEventListener("DOMContentLoaded", addTranslateButton);
  }
}