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.
// <nowiki>
/*jslint regexp: true, indent: 4 */
/*global $: false, wgNamespaceNumber: false, autoStart: false, wgAction: false,
  homeWiki: true, translatorFormat: true, translatorKeepLinksLables: true, wgScriptPath: true */
if (typeof homeWiki === "undefined") {
    var homeWiki = "de";
}
 
if (typeof translatorFormat === "undefined") {
    var translatorFormat = "($1: $2)";
}
 
if (typeof translatorKeepLinksLables === "undefined") {
    var translatorKeepLinksLables = false;
}
 
 
// Regexp.escape() from: http://80.68.89.23/2006/Jan/20/escape/
RegExp.escape = function (text) {
    "use strict";
    return text.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
};
 
function Translator() {
    "use strict";
 
    var translationTextArea;
 
    function queryTranslationFromData(data) {
        var xmlDocument = $(data),
            xmlQuery = 'll[lang="' + homeWiki + '"]';
        return xmlDocument.find(xmlQuery).text();
    }
 
    function addTranslationToNode(node, translation) {
        var injectionString = translatorFormat.replace("$1", homeWiki).replace("$2", translation);
        node.append(injectionString);
    }
 
    function translateFromLanguageLinkNode(title, node) {
        $.get(wgScriptPath + "/api.php?action=query&prop=langlinks&titles=" + encodeURIComponent(title) + "&redirects=&format=xml&lllimit=500", function (data) {
            var translation = queryTranslationFromData(data);
            if (translation !== "") {
                addTranslationToNode(node, translation);
            }
        });
    }
 
    // for [[Link]]s in textareas
    function addTranslationToTextareaLink(title, translation) {
        translationTextArea.val(translationTextArea.val().replace(
            new RegExp("(\\[\\[:?)" + RegExp.escape(title) + "(\\|?.*?)(\\]\\])"),
            "$1" + translation + (translatorKeepLinksLables ? "$2" : "") + "$3"
        ));
    }
 
    function translateFromLanguageLinks(title) {
        $.get(wgScriptPath + "/api.php?action=query&prop=langlinks&titles=" + encodeURIComponent(title) + "&redirects=&format=xml&lllimit=500", function (data) {
            var translation = queryTranslationFromData(data);
            if (translation !== "") {
                addTranslationToTextareaLink(title, translation);
            }
        });
    }
    // 
 
    // for {{TemplateLink}}s in textareas
    function addTranslationToTextareaTemplateLink(title, translation) {
        translationTextArea.val(translationTextArea.val().replace(
            new RegExp("(\\{\\{\\s*(?:[Tt]emplate:)?)" + RegExp.escape(title) + "([\\n\\|\\}])"),
            "$1" + translation + "$2"
        ));
    }
 
    function translateFromLanguageTemplateLinks(title) {
        $.get(wgScriptPath + "/api.php?action=query&prop=langlinks&titles=Template:" + encodeURIComponent(title) + "&redirects=&format=xml&lllimit=500", function (data) {
            var translation = queryTranslationFromData(data);
            if (translation !== "") {
                addTranslationToTextareaTemplateLink(title, translation.replace(/^.*?:/, "")); // removing local template name
            }
        });
    }
    //
 
    this.run = function () {
        if (wgAction === "view" || wgAction === "purge" || wgAction === "historysubmit") {
            $("#bodyContent a").each(function () {
                var iter = $(this),
                    title = iter.attr("title");
                if (title !== undefined) {
                    translateFromLanguageLinkNode(title, iter);
                }
            });
        } else if (wgAction === "edit" || wgAction === "submit") {
            $("#wpTextbox2").remove();
            translationTextArea = $("#wpTextbox1").clone().attr({
                "id": "wpTextbox2"
            }).css({
                "background-color": "#CCCEFF"
            });
 
            $("#wpTextbox1").before(translationTextArea);
 
            // for links
            var links = translationTextArea.val().match(/\[\[.*?\]\]/g),
                templates = translationTextArea.val().match(/\{\{.*?[\n\|\}]/g),
                i,
                title;
 
            for (i = 0; i < links.length; i = i + 1) { // equals with <code>for (i in matched)</code>
                title = links[i].replace(/\[\[:?([^\]\|]*)\|?.*?\]\]/g, "$1");
                translateFromLanguageLinks(title);
            }
 
            for (i = 0; i < templates.length; i = i + 1) { // equals with <code>for (i in matched)</code>
                title = templates[i].replace(/\{\{\s*(?:[Tt]emplate:)?(.*)\s*[\n\|\}]/g, "$1");
                translateFromLanguageTemplateLinks(title);
            }
        }
    };
}
 
var translator = new Translator();
$(function () {
    "use strict";
    if (typeof autoStart !== "undefined") {
        if (autoStart === true) {
            translator.run();
        }
    } else {
        $("h1").append(' <a style="font-size:40%" href="javascript:translator.run()">(translate links to ' + homeWiki + '!)</a>');
    }
});