User:CFA/scripts/attributetranslation.js
Appearance
< User:CFA
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
This user script seems to have a documentation page at User:CFA/scripts/attributetranslation. |
(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 = `
<label for="langCode" style="font-weight:bold">Language code</label>
<p style="font-size: 50%;">The two-letter language code of the Wikipedia that this article was translated from.</p>
<input type="text" id="langCode" placeholder="e.g. zh, es, fr"><br><br>
<label for="articleName" style="font-weight:bold">Article name</label>
<p style="font-size: 50%;">The name of the page on the other Wikipedia that this article was translated from.</p>
<input type="text" id="articleName" placeholder="e.g. 维基百科"><br><br>
<label for="addTranslatedPageTemplate" style="font-weight:bold">
<input checked type="checkbox" id="addTranslatedPageTemplate"> Add {{Translated page}} to talk page
</label>
<p style="font-size: 50%;margin-bottom:1rem;">Add <a href="/wiki/Template:Translated page">{{Translated page}}</a> to the talk page <a href="/wiki/Help:Translation#License requirements">if</a> the translated content is significant.</p>
<label style="font-weight:bold">Warn users</label>
<p style="font-size: 50%;">Send a notice to the user(s) who added the non-attributed text.</p>
<div id="contributorsContainer">
<div id="contributorsList"></div>
</div><br>
<button id="submitTranslation">Submit</button>
<button id="closeGUI">Close</button>
<div id="logContainer" style="display: none; margin-top: 20px; border-top: 1px solid #a2a9b1; padding-top: 10px;">
<h3>Log</h3>
<ul id="logList" style="list-style-type: none; padding-left: 0;"></ul>
</div>
`;
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. ([[User:Clearfrienda/scripts/AttributeTranslation|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);
}
}
// Dummy edit
$.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',
// watchlistExpiry: '2 weeks',
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();
}
});
// Add {{Translated page}} template
if (addTemplate) {
var talkPageTitle = 'Talk:' + pageTitle;
$.ajax({
url: mw.util.wikiScript('api'),
type: 'POST',
data: {
format: 'json',
action: 'edit',
title: talkPageTitle,
summary: `Adding {{Translated page}} attribution ([[User:Clearfrienda/scripts/AttributeTranslation|AT]])`,
section: 'new',
watchlist: 'nochange',
// watchlistExpiry: '2 weeks',
sectiontitle: '',
text: `{{Translated page|${langCode}|${articleName}|small=no}}`,
token: mw.user.tokens.get('csrfToken')
},
success: function () {
console.log('Article talk page updated');
addLogEntry('Added template to talk page', true);
checkCompletion();
},
error: function (jqXHR, textStatus, errorThrown) {
console.error('Error updating article talk page:', textStatus, errorThrown);
addLogEntry('Failed to add template to talk page', false);
checkCompletion();
}
});
}
// Notify contributors
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 ([[User:Clearfrienda/scripts/AttributeTranslation|AT]])`,
section: 'new',
watchlist: 'nochange',
// watchlistExpiry: '2 weeks',
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();
})();