Jump to content

User:Vanished user 1929210/link-ts.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.
/*
 * @name Link Translator
 * 
 * Originally designed by [[User:Liangent]]
 * Changed by [[User:Kovl]] v2015-2-6-7-52
 * Changed again by [[user:Panintelize]] 2016-02-06
 * Source code is at [[User:Liangent/Gadgets/Toolkit/linktranslator.uncompressed.js]]
 *
 * VANDALIZED BY [[User:逆襲的天邪鬼]] v2016-11-31
 *
 * See also: [[zh:User:逆襲的天邪鬼/link-ts.js]]
 */

// <pre>
/**
 * TODO:
 *
 * 1. 把中文的{{le}}、{{lang-xx}}、{{tsl}}变成对应的英文版本条目;
 * 2. 使用{{Interlanguage link multi}}因为英文的{{link-zh}}并不起作用;
 */

mw.loader.using(['jquery.ui']).then(function () {
    'use strict';

    var LTUI = {
        Translate:              'Translate',
        TranslateLinks:         'Translate links',
        LinkTranslator:         'Link Translator',
        TLTitle:                'Translate links from Wikipedia in another language automatically',
        SourceLanguageCode:     'Language code of the target Wikipedia: ',
        OriginalLink:           'Original Link: ',
        NOLINKINPAGE:           'There is no links in this page',
        Done:                   'Done',
        NoWikiEd:               'Please disable WikEd before using linktranslator.js due to incompatibility',
        EditMessage:            '[[User:逆襲的天邪鬼/link-ts.js|Translate links]] from another Wikipedia',

        // OPTION
        SelectedTextOnly:       'Only process highlighted texts',
        IfFound:                'If corresponding articles are found --',
        KeepOriginalText:       'Keep original lagels ({{link-zh||原文|Label}})',
        KeepOriginalText2:      'Keep original labels ([[English|原文]])',
        CommentOriginalLink:    'Comment original links',
        IfNotFound:             'Otherwise --',
        UseLangLink:            'Convert it to {{link-xx}}',
        MarkWrongPage:          'Mark pages which are not found in Wikipedia',

        // STATUS
        PARSEFAILED:            'Parse Failed',
        ERROR:                  'Error',
        NOLINK:                 'No Links',
        MULTIPLELINK:           'Multiple Links',
        PAGESAME:               'Same page',
        PAGEDIFF:               'Different pages',
        DONTEXIST:              'Page Not Found'
    };

    var LTConf = {
        SourceLanguageCode:     'zh',
        KeepOriginalText:       'checked',      // 'checked' or ''
        KeepOriginalText2:      'checked',
        CommentOriginalLink:    '',
        UseLangLink:            'checked',
        SelectedTextOnly:       'checked',
        MarkWrongPage:          'checked',
    };


    // variables
    var currentJobid = 0;
    var LDSB = '__LEFT_DOUBLE_SQUARE_BRACKETS__';
    var EXEConf;

    /**
     * 调用维基百科API来转换条目标题
     */
    var callApi = function (options) {
        var links = options.links || [];
        var callback = options.callback || (function () {});
        var failure = options.failure || (function () {});
        var lang = options.lang || 'en';
        var tolang = options.tolang || mw.config.get('wgContentLanguage');
        var jobid = options.jobid || currentJobid;

        // 标题去重,同时将这些标题分组,因为API只允许一次性最多提交50个标题
        var map = {};
        var i;
        for (i=0; i<links.length; i++) {
            map[links[i]] = true;
        }

        var queue = [];
        var queue2 = [];
        var m = 0, n = 0;
        for (var j in map) {
            queue.push(j);
            m++;
            if (m === 50) {
                m = 0;
                queue2.push(queue);
                queue = [];
                n++;
            }
        }
        if (queue.length > 0) {
            queue2.push(queue);
            n++;
        }

        // 开始处理
        var stop = false;
        var langlinks = {};

        var done = function (data) {
            if (data.query) {
                // 獲取原來的標題
                var orinTitle = {};
                var convert = function (arr) {
                    if (arr) {
                        for (var i=0; i<arr.length; i++) {
                            if (orinTitle[arr[i].from]) {
                                orinTitle[arr[i].to] = orinTitle[arr[i].from];
                            } else {
                                orinTitle[arr[i].to] = arr[i].from;
                            }
                        }
                    }
                };
                convert(data.query.normalized);
                convert(data.query.converted);
                convert(data.query.redirects);

                // 標明翻譯情況
                var pages = data.query.pages;
                for (var pageid in pages) {
                    var page = pages[pageid];
                    var title = page.title;
                    if (orinTitle[title]) {
                        title = orinTitle[title];
                    }

                    if (page.missing !== undefined) {
                        // 页面不存在
                        langlinks[title] = undefined;
                    } else if (page.langlinks) {
                        langlinks[title] = page.langlinks[0]['*'];
                    } else {
                        // 没有对应条目
                        langlinks[title] = null;
                    }
                }
            }

            n--;
            if (n === 0 && !stop) {
                callback(langlinks);
            }
        };

        var error = function (jqXHR, textStatus, errorThrown) {
            stop = true;
            if (jobid === currentJobid) {
                failure(langlinks);
            }
        };

        var process = function (links) {
            if (jobid !== currentJobid) {
                stop = true;
                return;
            }

            $.ajax({
                data: {
                    action: 'query',
                    prop: 'langlinks',
                    lllang: tolang,
                    format: 'json',
                    redirects: true,
                    converttitles: true,
                    lllimit: 50,
                    titles: links.join('|'),
                },
                dataType: 'jsonp',
                type: 'POST',
                url: 'https://' + lang + '.wikipedia.org/w/api.php',
                success: done,
                error: error,
            });
        };

        for (i=0; i<queue2.length && !stop; i++) {
            process(queue2[i]);
        }
    };

    /**
     * 根据要求,将跨语言链接变成普通链接或{{link-xx}}(英文维基没有{{tsl}})。Category会被特殊处理。
     */
    var makeLink = function (options) {
        var link = options.link || { target: '', display: '' };
        var lang = options.lang || '';
        var newTarget = options.newTarget;
        var output = '';

        if (!link) {
            return '';
        }

        var makeNormalLink = function (target, display) {
            if (target === display || display === '') {
                return LDSB + target + ']]';
            } else {
                return LDSB + target + '|' + display + ']]';
            }
        };

        // 禁止把页面分类变成跨语言链接,或者在其后面附加文字(除非是[[Category:XXX|*]]那种)
        if (link.target.toLowerCase().indexOf('category:') === 0) {
            options.useLangLink = false;
            options.keepOriginalText2 = (link.display !== '' && link.display !== link.target);
        }

        if (newTarget === null) {
            // 没有对应英文条目
            if (options.useLangLink) {
                if (options.keepOriginalText) {
                    return '{{link-' + lang + '||' + link.target + '|' + link.display + '}}';
                } else {
                    return '{{link-' + lang + '||' + link.target + '}}';
                }
            } else {
                if (options.markWrongPage) {
                    return '<!-- ' + LTUI.NOLINK + ' -->' + makeNormalLink(link.target, link.display);
                } else {
                    return makeNormalLink(link.target, link.display);
                }
            }
        } else if (newTarget === undefined) {
            // 页面不存在
            if (options.markWrongPage) {
                return '<!-- ' + LTUI.DONTEXIST + ' -->' + makeNormalLink(link.target, link.display);
            } else {
                return makeNormalLink(link.target, link.display);
            }
        } else {
            if (options.keepOriginalText2) {
                output = makeNormalLink(newTarget, link.display || link.target);
            } else {
                output = makeNormalLink(newTarget, '');
            }
        }

        if (options.commentOriginalLink) {
            output = '<!-- ' + makeNormalLink(link.target, link.display) + ' -->' + output;
        }

        return output;
    };

    /**
     * 开始进行处理
     */
    var processLinks = function (event) {
        event.preventDefault();
        var jobid = currentJobid;

        EXEConf = {
            KeepOriginalText:       $('#linktranslator-keep-original').prop('checked'),
            KeepOriginalText2:      $('#linktranslator-keep-original2').prop('checked'),
            CommentOriginalLink:    $('#linktranslator-comment-link').prop('checked'),
            UseLangLink:            $('#linktranslator-lang-link').prop('checked'),
            SelectedTextOnly:       $('#linktranslator-selected-text').prop('checked'),
            MarkWrongPage:          $('#linktranslator-markwrongpage').prop('checked'),
        };

        LTConf.SourceLanguageCode = $('#linktranslator-source-lang').val();

        var textBox = document.getElementById('wpTextbox1');
        var wikitext = textBox.value;
        if (EXEConf.SelectedTextOnly && textBox.selectionEnd - textBox.selectionStart > 0) {
            wikitext = wikitext.substring(textBox.selectionStart, textBox.selectionEnd);
        }

        var links = wikitext.match(/(\[\[)(?!\:?.?.?\:)(?!Image:)(?!File:)(.+?)(\|.+?)?(\]\])/g);

        if (links === null) {
            $('#linktranslator').text(LTUI.NOLINKINPAGE);
            return;
        } else {
            $('#linktranslator').dialog( 'option', 'position', { my: 'top', at: 'top'} );
            $('#linktranslator').html('<div id="linktranslator-progressbar"></div>');
            $('#linktranslator-progressbar').progressbar();
        }

        // 整合各links
        var realLinks = [];
        var links2 = [];
        for (var i=0; i<links.length; i++) {
            var link = links[i].slice(2, -2);

            var linktarget = link;
            var linkdisplay = link;

            var idx = link.indexOf('|');
            if (idx != -1) {
                linktarget = link.substring(0, idx);
                linkdisplay = link.substring(idx + 1);
            }
            $('#linktranslator').append('<div id="linktranslator-item-' + i + '"></div>');
            $('#linktranslator-item-' + i).text(links[i] + ' -> ')
                .append('<span class="linktranslator-item-newlink">...</span>');

            realLinks.push(linktarget);
            links2.push({ target: linktarget, display: linkdisplay });
        }

        var apiCallback = function (langlinks) {
            var code = wikitext + '';

            for (var i=0; i<links2.length; i++) {
                var link = links2[i];

                // 处理文内链接
                var linkCode = makeLink({
                    link: link,
                    newTarget: langlinks[link.target],
                    lang: LTConf.SourceLanguageCode,
                    useLangLink: EXEConf.UseLangLink,
                    keepOriginalText: EXEConf.KeepOriginalText,
                    keepOriginalText2: EXEConf.KeepOriginalText2,
                    commentOriginalLink: EXEConf.CommentOriginalLink,
                    markWrongPage: EXEConf.MarkWrongPage,
                });

                //mark on dialogue
                $('#linktranslator-item-' + i + ' .linktranslator-item-newlink').text(linkCode.replace(new RegExp(LDSB, 'g'), '[['));

                if (langlinks[link.target] === null) {
                    // 没有对应英文条目
                    if (!EXEConf.UseLangLink) {
                        $('#linktranslator-item-' + i + ' .linktranslator-item-newlink').text(LTUI.NOLINK);
                    }
                } else if (langlinks[link.target] === undefined) {
                    // 页面不存在
                    $('#linktranslator-item-' + i + ' .linktranslator-item-newlink').text(LTUI.DONTEXIST);
                } else if (langlinks[link.target] === link) {
                    $('#linktranslator-item-' + i + ' .linktranslator-item-newlink').text(LTUI.PAGESAME);
                }

                // only replacing the first is ok, we will run this many times
                code = code.replace(links[i], linkCode);
            }

            return code.replace(new RegExp(LDSB, 'g'), '[[');
        };

        // 开始处理
        // 过去是一个条目调用一次API,现在是一次性处理全部,所以滚动条已经没有意义。
        // var respcount = 0;
        callApi({
            links: realLinks,
            lang: LTConf.SourceLanguageCode,
            jobid: jobid,
            callback: function (langlinks) {
                var newtext = apiCallback(langlinks);

                //$('#linktranslator-progressbar').progressbar('value', respcount * 100 / links.length);
                $('#linktranslator-progressbar').progressbar('value', 100);
                $('#linktranslator').prepend('<div id="linktranlator-done"><strong>' + LTUI.Done + '</strong></div>');

                if (EXEConf.SelectedTextOnly && textBox.selectionEnd - textBox.selectionStart > 0) {
                    textBox.setRangeText(newtext);
                } else {
                    textBox.value = newtext;
                }
                $('#wpSummary').val(LTUI.EditMessage + $('#wpSummary').val());
            },
            failure: function (langlinks) {
                $('#linktranslator').prepend('<div id="linktranlator-done" style="color:red;"><strong>' + LTUI.ERROR + '</strong></div>');
            },
        });
    };

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

    // secure server?
    var wgAction = mw.config.get('wgAction');
    if (wgAction == 'edit' || wgAction == 'submit') {
        $('#wpDiff').after('\n<input id="wpLinktranslator" value="' + LTUI.TranslateLinks + '" title="' + LTUI.TLTitle + '" type="button"/>');
        $('#wpLinktranslator').click(function (event) {
            event.preventDefault();
            $('#linktranslator').remove();
            if ($('#wikEdFrameWrapper').css('visibility') === 'visible'){
                alert(LTUI.NoWikiEd);
                return;
            }

            var textBox = document.getElementById('wpTextbox1');
            if (textBox.selectionEnd - textBox.selectionStart > 0) {
                LTConf.SelectedTextOnly = 'checked';
            } else {
                LTConf.SelectedTextOnly = '';
            }

            $('<div id="linktranslator" title="' + LTUI.LinkTranslator + '">' +
                '<label for="linktranslator-source-lang">' + LTUI.SourceLanguageCode + '</label> ' +
                '<input id="linktranslator-source-lang" value="' + LTConf.SourceLanguageCode + '" type="text" /><br><br>' +
                '<input type="checkbox" id="linktranslator-selected-text" ' + LTConf.SelectedTextOnly + '/> ' +
                '<label for="linktranslator-selected-text">' + LTUI.SelectedTextOnly + '</label><br>' +
                '<br>' + LTUI.IfFound + '<br><br>' +
                '<input type="checkbox" id="linktranslator-comment-link" ' + LTConf.CommentOriginalLink + '/> ' +
                '<label for="linktranslator-comment-link">' + LTUI.CommentOriginalLink + '</label><br>' +
                '<input type="checkbox" id="linktranslator-keep-original2" ' + LTConf.KeepOriginalText2 + '/> ' +
                '<label for="linktranslator-keep-original2">' + LTUI.KeepOriginalText2 + '</label><br>' +
                '<br>' + LTUI.IfNotFound + '<br><br>' +
                '<input type="checkbox" id="linktranslator-lang-link" ' + LTConf.UseLangLink + '/> ' +
                '<label for="linktranslator-lang-link">' + LTUI.UseLangLink + '</label><br>' +
                '<input type="checkbox" id="linktranslator-keep-original" ' + LTConf.KeepOriginalText + '/> ' +
                '<label for="linktranslator-keep-original">' + LTUI.KeepOriginalText + '</label><br>' +
                '<input type="checkbox" id="linktranslator-markwrongpage" ' + LTConf.MarkWrongPage + '/> ' +
                '<label for="linktranslator-markwrongpage">' + LTUI.MarkWrongPage + '</label><br>' +
                '<br><input class="mw-ui-button mw-ui-constructive" id="linktranslator-translate" value="' + LTUI.Translate + '" type="button" /></div>'
            ).dialog({
                modal: false,
                close: function() {
                    currentJobid++;
                },
                width: 500
            });
            $('#linktranslator-translate').click(processLinks);
        });
    }
});
// </pre>