Greasy Fork is available in English.

Magic Twitter translate with DeepL

Adds external translation with DeepL

اعتبارا من 09-03-2021. شاهد أحدث إصدار.

// ==UserScript==
// @name         Magic Twitter translate with DeepL
// @namespace    https://github.com/magicoflolis
// @version      0.5
// @description  Adds external translation with DeepL
// @author       Magic of Lolis
// @match        https://twitter.com/*
// @grant        none
// @require      https://code.jquery.com/jquery-3.5.1.min.js
// ==/UserScript==

( () => {
    'use strict';

    let injected = null,
        injectInterval = null,
        waitForHeadNodeInterval = null;
    function isHTML(str) {
        let doc = new DOMParser().parseFromString(str, "text/html");
        return Array.from(doc.body.childNodes).some(node => node.nodeType === 1);
    }

    function injectDeeplTranslationButton() {
        let translateButton = $("div[lang]").eq(0).siblings().eq(0).children("span"),
            deeplbtn = $("div[lang]").eq(0).siblings().eq(1).children("span"),
            translateBio = $('div[data-testid="UserDescription"]').eq(0).siblings().eq(0).children("span"),
            deeplBio = $('div[data-testid="UserDescription"]').eq(0).siblings().eq(1).children("span"),
            deepbtn = () => {
                let tweetContainer = translateButton.parent().siblings(),
                    tweetLang = tweetContainer.attr("lang"),
                    tweetContent = "",
                    deeplButton = translateButton.parent().clone().appendTo(translateButton.parent().parent());
                tweetContainer.children("span").each((index,item) => {
                    let tweetPart = $(item).html().trim();
                    if(tweetPart && tweetPart != "" && !isHTML(tweetPart)) {
                        tweetContent += " " + tweetPart;
                    }
                });
                deeplButton.children("span").html("Translate with DeepL");
                deeplButton.hover(function() {
                    $(this).css("text-decoration", "underline");
                }, function() {
                    $(this).css("text-decoration", "none");
                });
                deeplButton.on("click", () => {
                    window.open(`https://www.deepl.com/translator#${tweetLang}/en/${tweetContent}`,'_blank');
                })
            },
            biobtn = () => {
                let bioContainer = translateBio.parent().siblings(),
                    bioLang = bioContainer.attr("lang"),
                    bioContent = "",
                    deeplButton = translateBio.parent().clone().appendTo(translateBio.parent().parent());
                bioContainer.children("span").each((index,item) => {
                    let bioPart = $(item).html().trim();
                    if(bioPart && bioPart != "" && !isHTML(bioPart)) {
                        bioContent += " " + bioPart;
                    }
                });
                deeplButton.children("span").html("Translate with DeepL");
                deeplButton.hover(function() {
                    $(this).css("text-decoration", "underline");
                }, function() {
                    $(this).css("text-decoration", "none");
                });
                deeplButton.on("click", () => {
                    window.open(`https://www.deepl.com/translator#${bioLang}/en/${bioContent}`,'_blank');
                })
            };
            (deeplbtn.length != 1 && translateButton.length > 0) ? deepbtn() : false;
            (deeplBio.length != 1 && translateBio.length > 0) ? biobtn() : false;
            injected = true;
            clearInterval(injectInterval);
            injectInterval = null;
    }

    function addObserverIfHeadNodeAvailable() {
        const target = $("head > title")[0],
        MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver,
        observer = new MutationObserver((mutations) => {
            mutations.forEach( () => {
                injected = null;
                injectInterval = setInterval(injectDeeplTranslationButton, 100);
            });
        });
        if(!target) {
            return;
        }
        clearInterval(waitForHeadNodeInterval);
        observer.observe(target, { subtree: true, characterData: true, childList: true });
    }
    waitForHeadNodeInterval = setInterval(addObserverIfHeadNodeAvailable, 100);
})();