User:WhitePhosphorus/js/link-ts.js

维基百科,自由的百科全书

注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google ChromeFirefoxMicrosoft EdgeSafari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。

;/** 
 * @file   Link Translator for Chinese Wikipedia
 * @author [[User:Liangent]]    // initial version ([[User:Liangent/Gadgets/Toolkit/linktranslator.uncompressed.js]])
 * @author [[User:Kovl]]        // v2015-2-6-7-52
 * @author [[User:Panintelize]] // 2016-02-06
 * @author [[User:Artoria2e5]]  // review, async, review-functional, KeepOriginalTextAuto
 * 
 * To use this script, add the following line to [[User:YourName/common.js]]:
 * importScript('User:Artoria2e5/link-ts.js')
 */

mw.loader.using(['jquery.ui']).then(function () {
$(function() {
function __lt_strarr_dedup(arr) {
    var ret = Object.create(null);
    $(arr).each(function (idx, elem) {
        ret[elem] = '';
    });
    return Object.keys(ret);
}

/**
 * @namespace UI-related text
 */
var LTUI = {
    Translate: "翻译",
    TranslateLinks: "翻译链接",
    LinkTranslator: "链接翻译器",
    TLTitle: "自动翻译从其他语言维基百科复制的文本",
    SourceLang: "目标维基的语言代码:",
    OriginalLink: "原链接:",
    NOLINKINPAGE: "此页没有链接",
    Done: "完成",
    NowikEd: "linktranslator.js与wikEd不兼容,请于页面右上角暂时禁用wikEd。",
    EditMessage: "由[[User:Artoria2e5/link-ts.js|链接翻译器]]自动翻译;",

    // OPTION
    KeepOriginalTextTsl: "以原文顯示綠鏈",
    KeepOriginalTextBlue: "以原文顯示藍鍊",
    KeepOriginalTextAuto: "保留[[link]]中的自动文字",
    CommentOriginalLink: "注释原链接",
    UseLangLink: "跨语言链接",

    // STATUS
    PARSEFAILED: "解析失败",
    ERROR: "错误",
    NOLINK: "没有链接",
    MULTIPLELINK: "多个连接",
    PAGESAME: "页面相同",
    PAGEDIFF: "页面不同",
    DONTEXIST: "页面不存在"
};

/**
 * @namespace config (defaults)
 */
var LTConf = {
	// TYPE: STRING
    SourceLang: "en",
    
    // TYPE: "checked=" attribute boolean
    // "checked" is true;
    // "" is false.
    KeepOriginalTextTsl: "checked",
    KeepOriginalTextBlue: "checked",
    KeepOriginalTextAuto: "",
    CommentOriginalLink: "",
    UseLangLink: "checked"
};

// clear previous button
$('#wpLinktranslator').remove();

// secure server?
if ((mw.config.get('wgAction') == 'edit' || mw.config.get('wgAction') == 'submit') && mw.config.get('wgServer') == '//zh.wikipedia.org') {
    $('#wpDiff').after('\n<input id="wpLinktranslator" value="' + LTUI.TranslateLinks + '" title="' + LTUI.TLTitle + '" type="button"/>');
    $('#wpLinktranslator').click(LTClick);
}

// variables
var jobid = 0;
var ldsb = '__LEFT_DOUBLE_SQUARE_BRACKETS__';
var EXEConf;

function LTPascalCase(wordsStr){
	return wordsStr.match(/([A-Z]+(?=$|[A-Z][a-z])|[A-Z]?[a-z]+)/g);
}

// on click "Translate links" #wpLinktranslator
function LTClick(event) {
    event.preventDefault();
    $('#linktranslator').remove();
    if ($("#wikEdFrameWrapper").css("visibility") == "visible") {
        alert(LTUI.NowikEd);
        return;
    }
    $('<div id="linktranslator" class="plainlist" title="' + LTUI.LinkTranslator + '"><ul>' +
        '<li><label for="linktranslator-source-lang">' + LTUI.SourceLang + '</label> ' +
        '<input id="linktranslator-source-lang" value="' + LTConf.SourceLang + '" type="text" /></li>' +
        $.map(Object.keys(LTConf).slice(1), function(v, idx){
        	var id = 'linktranslator-' + LTPascalCase(v).join('-');
        	return '<li>' +
        	       '<label for="' + id + '">' + LTUI[v] + '</label> ' +
        	       '<input type="checkbox" id="' + id + '"' + LTConf[v] + '></label></li>';
        }).join('') + '</ul>' +
        '<input id="linktranslator-translate" value="' + LTUI.Translate + '" type="button" />' + '</div>'
    ).dialog({
        modal: false,
        close: function () {
            jobid++;
        },
        width: 500
    });
    $('#linktranslator-translate').click(TClick);
}

// on click "Translate" #linktranslator-translate
function TClick(event) {
    event.preventDefault(); 
    var thisjobid = jobid; // or in #wpLinktranslator's click event?

    EXEConf = Object.keys(LTConf).slice(1).reduce(function(acc, v){
    	acc[v] = $('#linktranslator-' + LTPascalCase(v).join('-')).prop('checked');
    	return acc;
    }, {});
    EXEConf.SourceLang = $('#linktranslator-source-lang').val();
    
    // if you don't use HTTPS, just die.
    var api = 'https://' + EXEConf.SourceLang + '.wikipedia.org/w/api.php';
    var wikitext = $('#wpTextbox1').val();
    var links = __lt_strarr_dedup($('#wpTextbox1').val().match(/(\[\[)(?!\:?.?.?\:)(?!(Image|File))(.+?)(\|.+?)?(\]\])/g));

    if (links === null) {
        $('#linktranslator').text(LTUI.NOLINKINPAGE);
        return;
    } else {
    	// assert links.length != 0 here, or we have a problem with the browsr.
        $('#linktranslator').dialog("option", "position", {
            my: "top",
            at: "top"
        });
        $('#linktranslator').html('<div id="linktranslator-progressbar"></div>');
        $('#linktranslator-progressbar').progressbar();
    }

    var respcount = 0;

    $(links).each(function eachlink(linkidx, linkelem) {
        var link = linkelem.slice(2, -2);
        var linktarget = link;
        // TODO: pipe tricks like [[/subpage/]]?
        var linkdisplay = EXEConf.KeepOriginalTextAuto ? link : '';
        var idx = link.indexOf('|');
        if (idx != -1) {
            linktarget = link.substring(0, idx);
            linkdisplay = link.substring(idx + 1);
        }
        $('#linktranslator').append('<div id="linktranslator-item-' + linkidx + '"></div>');
        $('#linktranslator-item-' + linkidx).text(linkelem + ' -> ')
            .append('<span class="linktranslator-item-newlink">...</span>');
        // TODO: cannot identify if missing or [[zh:]] (for main page, also blank text)
        $.ajax({
            data: {
                action: 'parse',
                format: 'json',
                page: linktarget,
                prop: 'langlinks',
                redirects: 1
            },
            dataType: "jsonp",
            type: 'POST',
            url: api,
            success: function (data) {
                console.log(data);
                if (thisjobid != jobid) {
                    return;
                }

                var iwmatches;
                var newtarget;
                var newlinks;

                if (data.parse) {
                    // request successful
                    iwmatches = $.grep(data.parse.langlinks, function(el){ return el.lang === 'zh' });
                } else if (data.error.info) {
                    // request completed with error
                    if (data.error.info == "The page you specified doesn't exist") {
                        $('#linktranslator-item-' + linkidx + ' .linktranslator-item-newlink').text(LTUI.DONTEXIST);
                    } else {
                        $('#linktranslator-item-' + linkidx + ' .linktranslator-item-newlink').text(LTUI.ERROR + '(' + data.error.info + ')');
                    }
                    return;
                } else {
                    // error without info field
                    $('#linktranslator-item-' + linkidx + ' .linktranslator-item-newlink').text(LTUI.PARSEFAILED);
                    return;
                }

                if (iwmatches.length === 1) {
                    newtarget = iwmatches[0]["*"];

                    if (linktarget === newtarget) {
                        $('#linktranslator-item-' + linkidx + ' .linktranslator-item-newlink').text(LTUI.PAGESAME);
                        return;
                    }

                    if (EXEConf.KeepOriginalTextBlue) {
                        newlinks = ldsb + newtarget + '|' + linkdisplay + ']]';
                    } else {
                        newlinks = ldsb + newtarget + ']]';
                    }
                } else if (iwmatches.length === 0) {
                    if (EXEConf.UseLangLink) {
                        if (EXEConf.KeepOriginalTextTsl) {
                            newlinks = '{{tsl|' + EXEConf.SourceLang + '|' + linktarget + '||' + (linkdisplay == linktarget ? '' : linkdisplay)  + '}}';
                        } else {
                            newlinks = '{{tsl|' + EXEConf.SourceLang + '|' + linktarget + '}}';
                        }
                    } else {
                        $('#linktranslator-item-' + linkidx + ' .linktranslator-item-newlink').text(LTUI.NOLINK);
                        return;
                    }
                } else {
                    $('#linktranslator-item-' + linkidx + ' .linktranslator-item-newlink').text(LTUI.MULTIPLELINK);
                    return;
                }


                // EXEConf.CommentOriginalLink
                var newcomment = EXEConf.CommentOriginalLink ? '<!-- ' + LTUI.OriginalLink + ldsb + link + ']] -->' : '';

                // mark on dialogue
                $('#linktranslator-item-' + linkidx + ' .linktranslator-item-newlink').text(newlinks.replace(new RegExp(ldsb, 'g'), '[['));
                // replace all. since input is sparse, we don't care about...
                wikitext = wikitext.split(links[linkidx]).join(newlinks + newcomment);

            },
            error: function (jqXHR, textStatus, errorThrown) {
                if (thisjobid != jobid) {
                    return;
                }
                $('#linktranslator-item-' + linkidx + ' .linktranslator-item-newlink').text(LTUI.ERROR + '(' + textStatus + ')');
            },
            complete: function () {
                if (thisjobid != jobid) {
                    return;
                }
                respcount++;
                $('#linktranslator-progressbar').progressbar('value', respcount * 100 / links.length);
                if (respcount >= links.length) {
                    $('#wpTextbox1').val(wikitext.replace(new RegExp(ldsb, 'g'), '[['));
                    $('#linktranslator').prepend('<div id="linktranlator-done"><strong>' + LTUI.Done + '</strong></div>');
                }
            }
        }); // end of $.ajax
    }); // end of $(links).each

    $('#wpSummary').val(LTUI.EditMessage + $('#wpSummary').val()/* + JSON.stringify(EXEConf)*/);
}
});
});