ميدياويكي:Gadget-LinkTranslator.js
هذه الصفحة هي جزء من الإضافة «LinkTranslator»، يستعملها 5٬481 مستخدم. |
ملاحظة: بعد الحفظ، قد يلزمك إفراغ الكاش لرؤية التغييرات.
//[[: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': 'ar',
'fromLang': 'en',
'translatorBarFormat': '$1ترجم$2 الوصلات $4 ⇒ $3',
'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(mw.config.get('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) + mw.config.get('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 style="unicode-bidi: plaintext;"><a href="' + x[0] + '">' + x[0] + '</a></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 === mw.config.get('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;margin-inline-end: 1em;list-style-type: none;display: inline-block; direction: rtl; margin-top: 0.5em; color: grey; letter-spacing: 0.5px;" 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 + '<span id="translatorStatus"></span><progress id="translatorProgress" style="display: none;font-size:5px;margin-inline-start:1em">يجري...</progress></li>';
html = html.replace('$1', '(<a title="البحث أو الترجمة في غوغل" id="translator-equ" href="#"">…</a><span id="translator-equ-links"></span>) <a id="translator-button" href="#"> ');
html = html.replace('$2', '</a><span> (<a id="translator-plus" title="المقالات الناقصة في العربية" href="#">-</a>)</span>');
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">');
if (mw.config.get('skin') == 'minerva') {
$('#bodyContent').prepend(html);
} else {
$('#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-family: monospace;} .translatorAddedcontent {font-size: small; padding-left: 5px; unicode-bidi: plaintext;font-family: serif; color: red;} #translatorStatus {margin-right:1em}");