Jump to content

User:Santhosh.thottingal/mint-section-translation.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// Inject a script into Wikipedia pages to add translation links to section titles.
(function ($, mw) {
  mw.loader.load( '//en.wikipedia.org/w/index.php?title=User:Santhosh.thottingal/mint-section-translation.css&action=raw&ctype=text/css', 'text/css' );
  
  function translate(from, to, content) {
    const API_URL = 'https://translate.wmcloud.org/api/translate'
    return fetch(API_URL, {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({ 
			source_language: from,
			target_language: to,
			format: 'html',
			content: content,
		})
    })
      .then((response) => response.json())
      .then((result) => result.translation);
  }

  function insertAfter(referenceNode, newNode) {
    referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
  }

  function insertBefore(referenceNode, newNode) {
    if (referenceNode && referenceNode.parentNode) {
      referenceNode.parentNode.insertBefore(newNode, referenceNode);
    }
  }

  function createDropDown() {
    // Create a translate dropdown menu
    const translateDropdown = document.createElement("div");
    translateDropdown.classList.add("translate-dropdown");

    // Add a source language dropdown to the menu
    const sourceLanguageDropdown = document.createElement("select");
    sourceLanguageDropdown.classList.add("source");
    sourceLanguageDropdown.innerHTML = `
        <option value="en">English</option>
        <option value="es">Spanish</option>
        <option value="fr">French</option>
        <option value="hi">Hindi</option>
        <option value="ml">Malayalam</option>
        <option value="zh">Chinese</option>
      `;

    translateDropdown.appendChild(sourceLanguageDropdown);

    // Add a target language dropdown to the menu
    const targetLanguageDropdown = document.createElement("select");
    targetLanguageDropdown.classList.add("target");
    targetLanguageDropdown.innerHTML = `
        <option value="en">English</option>
        <option value="hne">Chhattisgarhi</option>
        <option selected value="es">Spanish</option>
        <option value="fr">French</option>
        <option value="hi">Hindi</option>
        <option value="ml">Malayalam</option>
        <option value="ig">Igbo</option>
        <option value="zh">Chinese</option>
      `;

    translateDropdown.appendChild(targetLanguageDropdown);

    // Add a translate button to the menu
    const translateButton = document.createElement("button");
    translateButton.textContent = "translate";
    translateButton.classList.add("btn-translate");
    translateDropdown.appendChild(translateButton);

    const resetButton = document.createElement("button");
    resetButton.textContent = "reset";
    resetButton.classList.add("btn-reset");
    translateDropdown.appendChild(resetButton);

    translateDropdown.style.display = "none";


    return translateDropdown;
  }

  function isHeaderTag(node) {
    const tagName = node.tagName.toLowerCase();
    return tagName === "h1" || tagName === "h2" || tagName === "h3" || tagName === "h4" || tagName === "h5" || tagName === "h6";
  }

  function findNextSiblingsMatchingPattern(node, pattern) {
    const siblings = [];

    let nextSibling = node.nextElementSibling;
    while (nextSibling) {
      if (isHeaderTag(nextSibling)) {
        break;
      }
      if (nextSibling.matches(pattern)) {
        siblings.push(nextSibling);
      }

      nextSibling = nextSibling.nextElementSibling;
    }

    return siblings;
  }

  function bindTranslate(section) {
    const translateIcon = document.createElement("a");
    translateIcon.textContent = "translate";
    translateIcon.classList.add("translate-trigger");
    insertBefore(Array.from(section.querySelectorAll(".mw-editsection-bracket")).pop(), translateIcon)
    const translateDropdown = createDropDown();
    insertAfter(section, translateDropdown)
    translateIcon.addEventListener("click", () => {
      if (translateDropdown.style.display === "none") {
        translateDropdown.style.display = "grid";
        // translateDropdown.style.top =
        //   translateIcon.offsetHeight + translateIcon.offsetTop + "px";
        // translateDropdown.style.left = (translateIcon.offsetLeft - translateDropdown.offsetWidth + translateIcon.offsetWidth) + "px";
      } else {
        translateDropdown.style.display = "none";
      }
    });
    const resetButton = translateDropdown.querySelector("button.btn-reset");
    resetButton.addEventListener("click", () => {
      // Get all the paragraphs in the webpage
      const paragraphs = findNextSiblingsMatchingPattern(section, "p, figure, table, ol, ul");
      // Remove old translated ones
      findNextSiblingsMatchingPattern(section, ".p-translated").forEach(e => e.remove());
      paragraphs.forEach(async (paragraph) => {
        paragraph.style.display = "";
      });
    });
    const translateButton = translateDropdown.querySelector("button.btn-translate");
    translateButton.addEventListener("click", () => {
      const sourceLanguage = translateDropdown.querySelector("select.source")
        .value;
      const targetLanguage = translateDropdown.querySelector("select.target")
        .value;

      // Get all the paragraphs in the webpage
      const paragraphs = findNextSiblingsMatchingPattern(section, "p, figure, table, ol, ul");
      // Remove old translated ones
      findNextSiblingsMatchingPattern(section, ".p-translated").forEach(e => e.remove());

      // Append a translate icon to the end of each paragraph
      paragraphs.forEach(async (paragraph) => {
        paragraph.style.display = "";
        const translatedParagraph = paragraph.cloneNode(true);
        const linkElements = translatedParagraph.querySelectorAll('a');
        for (const linkElement of linkElements) {
          if (!linkElement.hasAttribute('rel')) {
            linkElement.setAttribute('rel', 'mw:WikiLink');
          }
        }
        translatedParagraph.classList.add("p-translated");
        paragraph.style.display = "none";
        insertAfter(paragraph, translatedParagraph);
        const translation = await translate(sourceLanguage, targetLanguage, translatedParagraph.outerHTML)
        translatedParagraph.outerHTML = translation;
        translatedParagraph.setAttribute('lang', targetLanguage);
      });
    });
  }

  // Get all the paragraphs in the webpage
  const sections = document.querySelectorAll("h2, h3, h4");
  // Append a translate icon to the end of each paragraph
  sections.forEach(bindTranslate);

})(jQuery, mediaWiki);