User:CFA/scripts/attributetranslation.js

//

(function () {

'use strict';

const ts = Date.now() + (29 * 24 * 60 * 60 * 1000);

const pageTitle = mw.config.get('wgPageName').replace(/_/g, ' ');

function createInputGUI(contributors) {

var gui = document.createElement('div');

gui.style.position = 'fixed';

gui.style.top = '50%';

gui.style.left = '50%';

gui.style.transform = 'translate(-50%, -50%)';

gui.style.backgroundColor = '#f8f9fa';

gui.style.border = '1px solid #a2a9b1';

gui.style.padding = '20px';

gui.style.zIndex = 10000;

gui.style.overflowY = 'auto';

gui.style.maxHeight = '80vh';

gui.innerHTML = `

The two-letter language code of the Wikipedia that this article was translated from.



The name of the page on the other Wikipedia that this article was translated from.



Add {{Translated page}} to talk page

Add {{Translated page}} to the talk page if the translated content is significant.

Send a notice to the user(s) who added the non-attributed text.


`;

document.body.appendChild(gui);

var contributorsList = document.getElementById('contributorsList');

if (!contributorsList) {

console.error('Contributors list container not found.');

return;

}

contributors.forEach(function (contributor) {

var checkbox = document.createElement('input');

checkbox.type = 'checkbox';

checkbox.style = "transform: scale(0.75);margin-right:3px;";

checkbox.name = 'contributors';

checkbox.value = contributor.username;

var label = document.createElement('label');

label.style = "font-size:75%";

label.appendChild(checkbox);

label.appendChild(document.createTextNode(`${contributor.username} — ${contributor.edits} edit${contributor.edits === 1 ? : 's'}${contributor.isCreator ? ' (Page Creator)' : }`));

label.appendChild(document.createElement('br'));

contributorsList.appendChild(label);

});

document.getElementById('submitTranslation').addEventListener('click', function () {

var langCode = document.getElementById('langCode').value.trim();

var articleName = document.getElementById('articleName').value.trim();

var selectedContributors = Array.from(document.querySelectorAll('input[name=contributors]:checked')).map(function (checkbox) {

return checkbox.value;

});

var addTemplate = document.getElementById('addTranslatedPageTemplate').checked;

if (langCode && articleName) {

processTranslation(langCode, articleName, selectedContributors, addTemplate);

document.getElementById('logContainer').style.display = 'block';

} else {

alert('Please fill in both fields.');

}

});

document.getElementById('closeGUI').addEventListener('click', function () {

document.body.removeChild(gui);

});

}

function processTranslation(langCode, articleName, selectedContributors, addTemplate) {

var editSummary = `This article contains content translated from the Wikipedia article at ${langCode}:${articleName}; see its history for attribution. (AT)`;

var tasksCompleted = 0;

var totalTasks = 1 + (addTemplate ? 1 : 0) + selectedContributors.length;

var logList = document.getElementById('logList');

function addLogEntry(message, success) {

var listItem = document.createElement('li');

listItem.style.display = 'flex';

listItem.style.alignItems = 'center';

var checkmark = document.createElement('span');

checkmark.style.display = 'inline-block';

checkmark.style.width = '16px';

checkmark.style.height = '16px';

checkmark.style.marginRight = '8px';

checkmark.style.backgroundColor = success ? 'green' : 'red';

checkmark.style.borderRadius = '50%';

listItem.appendChild(checkmark);

listItem.appendChild(document.createTextNode(message));

logList.appendChild(listItem);

}

function checkCompletion() {

tasksCompleted++;

if (tasksCompleted === totalTasks) {

setTimeout(() => {

location.reload();

}, 1000);

}

}

$.ajax({

url: mw.util.wikiScript('api'),

type: 'GET',

data: {

format: 'json',

action: 'query',

prop: 'revisions',

rvprop: 'content',

titles: pageTitle

},

success: function (data) {

var pages = data.query.pages;

var pageContent = '';

for (var pageId in pages) {

if (pages.hasOwnProperty(pageId)) {

pageContent = pages[pageId].revisions[0]['*'];

}

}

pageContent += '\n​';

$.ajax({

url: mw.util.wikiScript('api'),

type: 'POST',

data: {

format: 'json',

action: 'edit',

title: pageTitle,

text: pageContent,

summary: editSummary,

minor: true,

watchlist: 'nochange',

token: mw.user.tokens.get('csrfToken')

},

success: function () {

console.log('Dummy edit successful');

addLogEntry('Added dummy edit to article', true);

checkCompletion();

},

error: function (jqXHR, textStatus, errorThrown) {

console.error('Error performing dummy edit:', textStatus, errorThrown);

addLogEntry('Failed to add dummy edit to article', false);

checkCompletion();

}

});

},

error: function (jqXHR, textStatus, errorThrown) {

console.error('Error retrieving page content:', textStatus, errorThrown);

addLogEntry('Failed to retrieve page content', false);

checkCompletion();

}

});

if (addTemplate) {

var talkPageTitle = 'Talk:' + pageTitle;

$.ajax({

url: mw.util.wikiScript('api'),

type: 'GET',

data: {

format: 'json',

action: 'query',

prop: 'revisions',

rvprop: 'content',

titles: talkPageTitle

},

success: function (data) {

var pages = data.query.pages;

var talkPageContent = '';

var talkPageExists = false;

for (var pageId in pages) {

if (pages.hasOwnProperty(pageId)) {

if (pages[pageId].revisions) {

talkPageExists = true;

talkPageContent = pages[pageId].revisions[0]['*'];

}

}

}

if (talkPageExists) {

var existingTemplateMatch = talkPageContent.match(/{{\s*(?:translationsource|translated article|translated|tradotto da|traducido ref|translated page|překlad|translated from)\s*(\|.*)?}}/i);

if (existingTemplateMatch) {

console.log('Template already present');

addLogEntry('{{Translated page}} already exists on talk page', true);

checkCompletion();

return;

}

if (talkPageContent.includes('{{WikiProject banner shell')) {

var bannerShellEndIndex = talkPageContent.lastIndexOf('}}');

if (bannerShellEndIndex !== -1) {

talkPageContent = talkPageContent.slice(0, bannerShellEndIndex + 2) + '\n{{translated page|' + langCode + '|' + articleName + '|small=no}}' + talkPageContent.slice(bannerShellEndIndex + 2);

console.log('Added {{translated page}} to talk page');

}

} else {

talkPageContent += '\n{{translated page|' + langCode + '|' + articleName + '|small=no}}';

console.log('Added {{translated page}} to talk page');

}

$.ajax({

url: mw.util.wikiScript('api'),

type: 'POST',

data: {

format: 'json',

action: 'edit',

title: talkPageTitle,

summary: 'Adding {{translated page}} attribution (AT)',

text: talkPageContent,

token: mw.user.tokens.get('csrfToken')

},

success: function () {

console.log('Talk page updated');

addLogEntry('Added {{translated page}} to talk page', true);

checkCompletion();

},

error: function (jqXHR, textStatus, errorThrown) {

console.error('Error updating talk page:', textStatus, errorThrown);

addLogEntry('Failed to add template to talk page', false);

checkCompletion();

}

});

} else {

$.ajax({

url: mw.util.wikiScript('api'),

type: 'POST',

data: {

format: 'json',

action: 'edit',

title: talkPageTitle,

summary: 'Adding {{Translated page}} attribution (AT)',

text: '{{translated page|' + langCode + '|' + articleName + '|small=no}}',

token: mw.user.tokens.get('csrfToken')

},

success: function () {

console.log('Talk page created and template added');

addLogEntry('Added {{translated page}} to talk page', true);

checkCompletion();

},

error: function (jqXHR, textStatus, errorThrown) {

console.error('Error creating talk page:', textStatus, errorThrown);

addLogEntry('Failed to create talk page', false);

checkCompletion();

}

});

}

},

error: function (jqXHR, textStatus, errorThrown) {

console.error('Error retrieving talk page:', textStatus, errorThrown);

addLogEntry('Failed to retrieve talk page', false);

checkCompletion();

}

});

}

selectedContributors.forEach(function (contributor) {

notifyContributor(contributor, langCode, articleName);

});

function notifyContributor(contributor, langCode, articleName) {

var subst = "subst:";

var sig = "~~" + "~~";

var notificationMessage = `{{${subst}uw-translation|1=${langCode}:${articleName}|to=${pageTitle}}} ${sig}`;

$.ajax({

url: mw.util.wikiScript('api'),

type: 'POST',

data: {

format: 'json',

action: 'edit',

title: 'User talk:' + contributor,

summary: 'Adding non-attributed translation notice (AT)',

section: 'new',

watchlist: 'nochange',

sectiontitle: 'Non-attributed translations',

text: notificationMessage,

token: mw.user.tokens.get('csrfToken')

},

success: function () {

console.log('Notification sent to user talk page');

addLogEntry(`Warned user (${contributor})`, true);

checkCompletion();

},

error: function (jqXHR, textStatus, errorThrown) {

console.error('Error sending notification:', textStatus, errorThrown);

addLogEntry(`Failed to warn user (${contributor})`, false);

if (confirm("Could not notify contributor. Retry?")) {

notifyContributor(contributor, langCode, articleName);

} else {

checkCompletion();

}

}

});

}

}

function getPageContributors(pageTitle, callback) {

$.ajax({

url: mw.util.wikiScript('api'),

type: 'GET',

data: {

format: 'json',

action: 'query',

prop: 'revisions',

rvprop: 'user',

titles: pageTitle,

rvlimit: 'max',

rvdir: 'newer'

},

success: function (data) {

var pages = data.query.pages;

var contributors = [];

for (var pageId in pages) {

if (pages.hasOwnProperty(pageId)) {

var revisions = pages[pageId].revisions;

var creator = true;

revisions.forEach(function (revision) {

if (revision.user && revision.user !== '') {

var contributorIndex = contributors.findIndex(function (item) {

return item.username === revision.user;

});

if (contributorIndex === -1) {

contributors.push({ username: revision.user, edits: 1, isCreator: creator });

} else {

contributors[contributorIndex].edits++;

}

creator = false;

}

});

}

}

callback(contributors);

},

error: function (jqXHR, textStatus, errorThrown) {

console.error('Error retrieving page contributors:', textStatus, errorThrown);

}

});

}

function addButtonToToolbar() {

var allowedNamespaces = [0, 118];

var currentNamespace = mw.config.get('wgNamespaceNumber');

if (allowedNamespaces.includes(currentNamespace)) {

mw.util.addPortletLink(

'p-cactions',

'#',

'Translation attribution',

'ca-translation-attribution',

'AttributeTranslation',

null,

null

);

document.getElementById('ca-translation-attribution').addEventListener('click', function () {

getPageContributors(pageTitle, function (contributors) {

createInputGUI(contributors);

});

});

}

}

addButtonToToolbar();

})();

//