User:Ainali/bylines.js
Appearance
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
// Fetch image author and license info for up to 50 images in one API call
(function() {
'use strict';
// Define translations
const translations = {
en: {
unknownAuthor: 'Unknown author',
unknownLicense: 'Unknown license',
imageBy: 'Image by: '
},
de: {
unknownAuthor: 'Unbekannter Autor',
unknownLicense: 'Unbekannte Lizenz',
imageBy: 'Bild von: '
},
sv: {
unknownAuthor: 'Okänd författare',
unknownLicense: 'Okänd licens',
imageBy: 'Bild av: '
}
// Add more languages here as needed
};
// Function to get the translation based on the user's language
function translate(key) {
const userLang = mw.config.get('wgUserLanguage') || 'en'; // Default to English
console.log('User language:', userLang); // Debugging: Log the user language
// Check if translations exist for the user language, else fallback to 'en'
if (translations.hasOwnProperty(userLang) && translations[userLang].hasOwnProperty(key)) {
return translations[userLang][key];
} else {
// Fallback to English if translation not found
return translations['en'][key];
}
}
// Function to fetch image metadata for multiple images (up to 50) using the MediaWiki API
async function fetchImageMetadataBatch(imageTitles) {
const titlesParam = imageTitles.map(title => encodeURIComponent(title)).join('|');
const url = `/w/api.php?action=query&titles=${titlesParam}&prop=imageinfo&iiprop=extmetadata&format=json&origin=*`;
const response = await fetch(url);
const data = await response.json();
const pages = data.query.pages;
// Extract the metadata for each image
const metadata = {};
for (const page of Object.values(pages)) {
if (page.imageinfo && page.imageinfo[0].extmetadata) {
const extmetadata = page.imageinfo[0].extmetadata;
const author = extmetadata.Artist ? extmetadata.Artist.value : translate('unknownAuthor');
const license = extmetadata.LicenseShortName ? extmetadata.LicenseShortName.value : translate('unknownLicense');
const licenseUrl = extmetadata.LicenseUrl ? extmetadata.LicenseUrl.value : "#";
metadata[page.title] = { author, license, licenseUrl };
} else {
metadata[page.title] = {
author: translate('unknownAuthor'),
license: translate('unknownLicense'),
licenseUrl: "#"
};
}
}
return metadata;
}
// Function to insert the byline next to the image
function insertByline(image, author, license, licenseUrl) {
const byline = document.createElement('div');
byline.className = 'image-byline';
// Use <strong> for bold styling around "Image by" translated string
byline.innerHTML = `<strong>${translate('imageBy')}</strong>${author} | <a href="${licenseUrl}" target="_blank">${license}</a>`;
image.parentNode.insertBefore(byline, image.nextSibling);
}
// Function to batch process images in chunks of 50
async function processImagesInBatches(imageTitles) {
const BATCH_SIZE = 50;
// Process images in batches
for (let i = 0; i < imageTitles.length; i += BATCH_SIZE) {
const batch = imageTitles.slice(i, i + BATCH_SIZE); // Get batch of up to 50 images
const metadata = await fetchImageMetadataBatch(batch); // Fetch metadata for the batch
for (const imageTitle of batch) {
const imageName = imageTitle.split(':')[1].trim(); // Extract the actual image name
const encodedImageName = mw.util.wikiUrlencode(imageName); // Encode the image name safely
const imageElement = document.querySelector(`img[src*="${encodedImageName}"]`); // Find the image element on the page
if (imageElement) {
const { author, license, licenseUrl } = metadata[imageTitle];
insertByline(imageElement, author, license, licenseUrl); // Insert the byline
}
}
}
}
// Function to fetch all images on the page from the API
async function fetchKnownImages(pageTitle) {
const url = `/w/api.php?action=query&format=json&prop=images&titles=${encodeURIComponent(pageTitle)}&imlimit=max&formatversion=2&origin=*`;
const response = await fetch(url);
const data = await response.json();
const pages = data.query.pages;
const page = Object.values(pages)[0];
return page.images ? page.images.map(img => img.title) : [];
}
// Function to process images known to the API
async function processImages() {
const pageTitle = mw.config.get('wgPageName'); // Get the current page title
const knownImageTitles = await fetchKnownImages(pageTitle); // Fetch known images
if (knownImageTitles.length > 0) {
// Process images in batches of 50
await processImagesInBatches(knownImageTitles);
}
}
// Function to add click event to the page title immediately
const pageTitleElement = document.getElementById('firstHeading'); // Get the page title element
if (pageTitleElement) {
pageTitleElement.style.cursor = 'pointer'; // Change cursor to pointer to indicate it's clickable
pageTitleElement.addEventListener('click', processImages); // Add click event to trigger processing images
}
})();