تێبینی: دوای پاشەکەوتکردن، پێویستە کاشی وێبگەڕەکەت پاک بکەیتەوە تا گۆڕانکارییەکان ببینیت. بۆ گووگڵ کڕۆم، فایەرفۆکس، مایکرۆسۆفت ئێج و سافاری: پەنجە لەسەر دوگمەی ⇧ Shift ڕاگرە و کرتە لەسەر Reload بکە. بۆ وردەکاری و ڕێنمایییەکان لەسەر وێبگەڕەکانی تر، بڕوانە ئێرە.
//لە ویکیپیدیای عەرەبییەوە وەرگیراوە
//[[:en:User:Ebraminio/ArticleTranslator.js]]; [[ويكيبيديا:الميدان/تقنية/05/2012#مترجم]]
// <nowiki>
/*jslint regexp: true */
/*browser: true*/
/*global $: false, wgNamespaceNumber: false, wgAction: false, mw: false,
  wgScriptPath: false, wgPageContentLanguage: false, window: false */

if (window.globalTranslatorConfigs === undefined) {
    var globalTranslatorConfigs = {
        'homeWiki': window.homeWiki,
        'fromLang': window.fromLang,
        'translatorBarFormat': window.translatorBarFormat,
        'templateTranslatorText': window.templateTranslatorText,
        'removeLinksAliasesText': window.removeLinksAliasesText,
        'doneText': window.doneText
    };
}

var translatorConfigs = {
    'homeWiki': 'ckb',
    'fromLang': 'en',
    'translatorBarFormat': '$1وەرگێڕانی$2 بەستەر $3&nbsp;⇒&nbsp;$4',
    'templateTranslatorText': 'وەرگێڕانی داڕێژەکان',
    'removeLinksAliasesText': 'شاردنەوەی ناونیشانەکانی بەستەرەکان',
    'doneText': 'کرا',
    'enableTemplateTranslation': true,
    'removeLinksAliases': true,
    'enableNeedingShow': false,
    'name': 'ناوی پەڕەکە',
    'interwikiCount': 'ژمارەی بەستەرەکانی زمان تێیدا',
    'linkedTo': 'ژمارەی بەستەرەکان',
    'listOfUnavailablePagesOn': 'پەڕەکان نەدۆزرانەوە لەناو '
};

$.extend(translatorConfigs, globalTranslatorConfigs);

// getting the last translator preference from the cookie
if ($.cookie('homeWiki') !== null) {
    translatorConfigs.homeWiki = $.cookie('homeWiki');
}

if ($.cookie('fromLang') !== null) {
    translatorConfigs.fromLang = $.cookie('fromLang');
}
//

// 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,
        progressCount,
        itemsCount,
        ajaxUrl;

    function getOrigin() {
        var result = window.location.protocol + '//' + window.location.host;
        if (window.location.port !== '') {
            result = result + ':' + window.location.port;
        }
        return result;
    }

    function getOriginOfWikiLang(lang) {
        return getOrigin().replace(wgPageContentLanguage, lang);
    }

    function setAjaxUrl() {
        var tailOfApiUrl = '/api.php?action=query&prop=langlinks&redirects=&format=json&lllimit=500&titles=';
        if (translatorConfigs.enableNeedingShow === true) {
            tailOfApiUrl = '/api.php?action=query&prop=langlinks|links&redirects=&format=json&pllimit=500&lllimit=500&titles=';
        }
        ajaxUrl = getOriginOfWikiLang(translatorConfigs.fromLang) + wgScriptPath + tailOfApiUrl;
    }

    function getSelectedTextLinks() {
        // borrowed from: http://stackoverflow.com/questions/4220478 :)
        var selection,
            selectionAncestor,
            range,
            allWithinRangeParent,
            allSelected,
            i,
            el;

        // if `window.getSelection` is not defined (on IE) return nothing.
        if (window.getSelection === undefined) {
            return [];
        }
        selection = window.getSelection();

        // if nothing is selected, return empty array
        if (selection.isCollapsed) {
            return [];
        }

        range = selection.getRangeAt(0);
        selectionAncestor = range.commonAncestorContainer;
        if (selectionAncestor.getElementsByTagName === undefined) { // if it is not a formal HTML selection
            return [];
        }
        allWithinRangeParent = selectionAncestor.getElementsByTagName('a');

        allSelected = [];
        for (i = 0; (el = allWithinRangeParent[i]) !== undefined; i += 1) {
            // The second parameter says to include the element 
            // even if it's not fully selected
            if (selection.containsNode(el, true)) {
                allSelected.push(el);
            }
        }
        return allSelected;
    }


    /*jslint unparam: true*/ // I don't want use key parameter in closures!
    function increaseProgressCount() {
        progressCount = progressCount + 1;
        $('#translatorProgress').attr('value', progressCount);

        if (progressCount === itemsCount) {
            $('#translatorProgress').hide('slow');
            $('#translatorStatus').css('font-weight', 'bold').text(translatorConfigs.doneText).show('slow');
            $( ".translatorAddedcontent" ).prev().css( "color", "lightblue" );
            if (translatorConfigs.enableNeedingShow) {
                var links = [],
                    result,
                    linksCount,
                    titleExistance = {},
                    title;
                $('.translatorNeededLink').each(function (k, v) {
                    title = $(v).attr('data-title');
                    if (titleExistance[title] === true) {
                        return;
                    }
                    titleExistance[title] = true;
                    linksCount = $(v).attr('data-links-to-count');
                    if (parseInt(linksCount, 10) === 500) {
                        linksCount = '500+';
                    }
                    links.push([title, parseInt($(v).attr('data-interwikis'), 10), linksCount]);
                });
                links = links.sort(function (x, y) { return y[1] - x[1]; });
                result = '<table class="wikitable sortable" ><tr><th>' + translatorConfigs.name + '</th><th>' + translatorConfigs.interwikiCount + '</th><th>' + translatorConfigs.linkedTo + '</th></tr>' + links.map(function (x) { return '<tr><td>' + x[0] + '</td><td>' + x[1] + '</td><td>' + x[2] + '</tr>'; }).join('') + '</table>';
                $('#translatorPlusContainer').remove();
                $('<li style="line-height: 1.25;" id="translatorPlusContainer">' + translatorConfigs.listOfUnavailablePagesOn + ' ' + translatorConfigs.homeWiki + '.wiki:\n<div style="white-space: pre-line;">' + result + '</div></li>').appendTo('#translatorBar');
            }
        }
    }

    function queryTranslationFromData(data) {
        var languageLinks,
            linksToCount = 0,
            translation;

        if (data.query === undefined || data.query.pages === undefined) {
            return null;
        }
        $.each(data.query.pages, function (key, value) { // for retrieving first object index
            languageLinks = value.langlinks;
            if (value.links !== undefined) {
                linksToCount = value.links.length;
            }
        });
        if (languageLinks === undefined) {
            return null;
        }
        $.each(languageLinks, function (key, value) { // we can also use .filter here
            if (value.lang === translatorConfigs.homeWiki) {
                translation = value['*'];
            }
        });
        return {
            translation: translation,
            linksToCount: linksToCount,
            interwikis: languageLinks.length
        };
    }
    /*jslint unparam: false*/

    function commonAjaxRunner(title, translatorFunction) {
        $.ajax({
            url: ajaxUrl + encodeURIComponent(title),
            complete: function () {
                increaseProgressCount();
            },
            success: function (data) {
                var translation = queryTranslationFromData(data);
                if (translation !== null) {
                    translatorFunction(translation);
                }
            },
            dataType: 'jsonp'
        });
    }

    function addTranslationToNode(node, translation) {
        if (translation.translation !== undefined) {
            node.after('<span class="translatorAddedcontent">' + '(<a href="' + getOriginOfWikiLang(translatorConfigs.homeWiki) + mw.util.getUrl(translation.translation) + '">' + translation.translation + '</a>)</span>');
        } else if (translatorConfigs.enableNeedingShow === true) {
            node.after('<span class="translatorAddedcontent">(<span style="color: red;" class="translatorNeededLink" data-title="' + node.attr('title') + '" data-interwikis="' + translation.interwikis + '" data-links-to-count="' + translation.linksToCount + '">' + translation.interwikis + '</span>)</span>');
        }
    }

    function translateFromLanguageLinkNode(title, node) {
        commonAjaxRunner(title, function (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 + (translatorConfigs.removeLinksAliases ? '' : '$2') + '$3'
        ));
    }

    function translateFromLanguageLinks(title) {
        commonAjaxRunner(title, function (translation) {
            if (translation.translation !== undefined) {
                addTranslationToTextareaLink(title, translation.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) {
        commonAjaxRunner('Template:' + title, function (translation) {
            if (translation.translation !== undefined) {
                addTranslationToTextareaTemplateLink(title, translation.translation.replace(/^.*?:/, ''));
            }
        });
    }

    function parseUrl(url) {
        if (url === undefined) {
            return undefined;
        }
        var match = url.match(/\/wiki\/([^#]*)/);
        if (match === null) {
            match = url.match(/\/w\/index\.php\?title=([^&#]*).*redlink=1/);
        }

        if (match !== null) {
            return decodeURI(match[1]); // returns () matched text
        }
        return undefined;
    }

    function getLinkTitle(link) { // previously it was link.attr("title")
        return parseUrl(link.attr('href'));
    }

    this.run = function () {
        setAjaxUrl();
        progressCount = 0;
        itemsCount = 0;
        $('#translatorStatus').hide(0);
        $('#translatorProgress').removeAttr('max').removeAttr('value');
        $('.translatorAddedcontent').remove()

        var links,
            templates,
            i,
            title;

        if (mw.config.get('wgAction') === 'view' || mw.config.get('wgAction') === 'purge' || mw.config.get('wgAction') === 'historysubmit') {
            links = getSelectedTextLinks();
            if (links.length === 0) {
                links = $('#bodyContent a');
            }
            $(links).filter('a').each(function () {
                var iter = $(this),
                    title = getLinkTitle(iter);
                if (title !== undefined) {
                    itemsCount = itemsCount + 1;
                    translateFromLanguageLinkNode(title, iter);
                }
            });
            $('#translatorProgress').show().attr('max', itemsCount);
        } else if (mw.config.get('wgAction') === 'edit' || mw.config.get('wgAction') === 'submit') {
            $('#wpTextbox2').remove(); // remove translation textarea if exists

            if (translatorConfigs.fromLang === wgPageContentLanguage) {
                translationTextArea = $('#wpTextbox1').clone().attr({
                    'id': 'wpTextbox2'
                }).css({ // new color for translation textarea
                    'background-color': 'whitesmoke'
                }).val($('#wpTextbox1').val()); // this something that clone must do
                $('#wpTextbox1').before(translationTextArea); // put translation textarea before old
            } else {
                translationTextArea = $('#wpTextbox1');
            }

            // for links
            links = translationTextArea.val().match(/\[\[.*?\]\]/g);
            templates = translationTextArea.val().match(/\{\{.*?[\n\|\}]/g);

            itemsCount = -1;
            if (links !== null) {
                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);
                }

                if (itemsCount === -1) {
                    itemsCount = 0;
                }
                itemsCount = itemsCount + links.length;
            }

            if (templates !== null && translatorConfigs.enableTemplateTranslation === true) {
                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);
                }

                if (itemsCount === -1) {
                    itemsCount = 0;
                }
                itemsCount = itemsCount + templates.length;
            }

            if (itemsCount !== -1) {
                $('#translatorProgress').show().attr('max', itemsCount);
            }
        }
    };
}

var translator = new Translator();
$(function () {
    "use strict";

    function initializeEditorFor(forEditable, inputForEditable, setVariableClosure) {
        $(forEditable).click(function (event) {
            event.preventDefault();
            $(forEditable).hide();
            $(inputForEditable).css('width', '2em').show().val($(forEditable).text());
        });

        $(inputForEditable).keyup(function (event) {
            var selectedLanugage = $(this).val();
            if (event.keyCode === 13) {
                $(this).focusout(); // on enter
            } else if (event.keyCode === 27) {
                $(forEditable).show(); // on escape
                $(inputForEditable).hide().val(selectedLanugage);
            }
        }).focusout(function () {
            var selectedLanugage = $(this).val();
            if (/...?/.test(selectedLanugage)) {
                setVariableClosure(selectedLanugage);
                $(forEditable).html(selectedLanugage);
            }
            $(forEditable).show();
            $(inputForEditable).hide();
        });
    }

    $('#translatorBar').remove();
    var html = '<li style="unicode-bidi: normal;" id="translatorBar">' + translatorConfigs.translatorBarFormat;
    if (mw.config.get('wgAction') === "edit" || mw.config.get('wgAction') === "submit") {
        html = html + ' <input type="checkbox" name="enableTemplateTranslation" id="enableTemplateTranslation"><label for="enableTemplateTranslation">' + translatorConfigs.templateTranslatorText + '</label>';
        html = html + ' <input type="checkbox" name="removeLinksAliases" id="removeLinksAliases"><label for="removeLinksAliases">' + translatorConfigs.removeLinksAliasesText + '</label>';
    }

    html = html + '&nbsp;&nbsp;<span id="translatorStatus"></span><progress id="translatorProgress" style="display: none;font-size:5px">دەبێت...</progress></li>';

    html = html.replace('$1', '(<a id="translator-equ" href="#"">=</a><span id="translator-equ-links"></span>) <a id="translator-button" href="#"> ');
    html = html.replace('$2', '</a><sup><a id="translator-plus" href="#">+</a></sup>');
    html = html.replace('$3', '<a id="translator-from" href="#">' + translatorConfigs.fromLang + '</a><input style="display: none" id="translator-from-input">');
    html = html.replace('$4', '<a id="translator-to" href="#">' + translatorConfigs.homeWiki + '</a><input style="display: none" id="translator-to-input">');

    $('#p-tb > div > ul').append(html);

    $('#translator-button').click(function (event) {
        event.preventDefault();
        translatorConfigs.enableNeedingShow = false;
        translator.run();
    });
    
    $('#translator-equ').click(function (event) {
        event.preventDefault();
        $('#translator-equ-links').html('<a target="_blank" href="//translate.google.com/translate_t?sl=' + translatorConfigs.fromLang + '&tl=' + translatorConfigs.homeWiki + '&q=' + mw.config.get('wgTitle') + '">گووگڵ ترانزلەیت</a> | <a target="_blank" href=\'//www.google.com/search?q="' + mw.config.get('wgTitle') + '"&lr=lang_' + translatorConfigs.homeWiki + '\'>گەڕان بەناو زمانی ئامانج</a>');
    });

    $('#translator-plus').click(function (event) {
        event.preventDefault();
        translatorConfigs.enableNeedingShow = true;
        translator.run();
    });

    initializeEditorFor('#translator-to', '#translator-to-input', function (value) {
        translatorConfigs.homeWiki = value;
        $.cookie("homeWiki", value);
    });

    initializeEditorFor('#translator-from', '#translator-from-input', function (value) {
        translatorConfigs.fromLang = value;
        $.cookie("fromLang", value);
    });

    $('#enableTemplateTranslation').attr('checked', translatorConfigs.enableTemplateTranslation).click(function () {
        translatorConfigs.enableTemplateTranslation = this.checked;
    });

    $('#removeLinksAliases').attr('checked', translatorConfigs.removeLinksAliases).click(function () {
        translatorConfigs.removeLinksAliases = this.checked;
    });
});

mw.util.addCSS("#translator-equ, #translator-plus {font-weight: bold; font-family: verdana;} .translatorAddedcontent {font-size: small; padding-left: 5px; unicode-bidi: plaintext;font-family: serif;    color: red;}");