MediaWiki:Common.js: Unterschied zwischen den Versionen
Keine Bearbeitungszusammenfassung |
Keine Bearbeitungszusammenfassung Markierung: Zurückgesetzt |
||
| Zeile 1: | Zeile 1: | ||
/* Eigene Sprachleiste: UI-Sprache + PageTranslation-Ziel umschalten */ | /* Eigene Sprachleiste: UI-Sprache + PageTranslation-Ziel umschalten (mit Cache) */ | ||
mw.loader.using(['mediawiki.util', 'mediawiki.api'], function () { | mw.loader.using(['mediawiki.util', 'mediawiki.api'], function () { | ||
| Zeile 6: | Zeile 6: | ||
try { | try { | ||
var prefLang = localStorage.getItem('preferredLang'); | var prefLang = localStorage.getItem('preferredLang'); | ||
var currentLang = mw.config.get('wgUserLanguage'); | var currentLang = (mw.config.get('wgUserLanguage') || '').toLowerCase(); | ||
if ( | if ( | ||
prefLang && | prefLang && | ||
prefLang.toLowerCase() !== currentLang | prefLang.toLowerCase() !== currentLang && | ||
!/[?&](?:use|set)lang=/.test(location.search) | !/[?&](?:use|set)lang=/.test(location.search) | ||
) { | ) { | ||
// setlang = persistente ULS-Sprache (Cookie/Local) | |||
var url = new URL(window.location.href); | var url = new URL(window.location.href); | ||
url.searchParams.set(' | url.searchParams.set('setlang', prefLang); | ||
location.replace(url.toString()); | location.replace(url.toString()); | ||
return; // Rest | return; // Rest erst nach Redirect ausführen | ||
} | } | ||
} catch (e) {} | } catch (e) {} | ||
| Zeile 29: | Zeile 30: | ||
]; | ]; | ||
// Wenn bereits eine Leiste existiert, nichts tun | |||
if (document.getElementById('custom-langbar')) return; | if (document.getElementById('custom-langbar')) return; | ||
| Zeile 37: | Zeile 39: | ||
var baseTitle = pageName.replace(/\/[a-z]{2}(?:-[a-z]{2})?$/i, ''); | var baseTitle = pageName.replace(/\/[a-z]{2}(?:-[a-z]{2})?$/i, ''); | ||
// Leiste | // ====== Caching-Setup für die Leiste ====== | ||
var | var CACHE_TTL = 24 * 60 * 60 * 1000; // 24h | ||
var cacheKey = 'custom-langbar:' + baseTitle + ':' + LANGS.map(function (l) { return l.code; }).join(',') + ':v2'; | |||
LANGS. | function buildHtml() { | ||
// Direkt zu /lang springen (oder Special:MyLanguage ohne /lang, wenn du lieber adaptiv willst) | |||
return '<nav aria-label="Sprachen">' + LANGS.map(function (lang) { | |||
var href = mw.util.getUrl(baseTitle + '/' + lang.code); | |||
return '<a href="' + href + '" data-code="' + lang.code + '">' + lang.label + '</a>'; | |||
}).join(' ') + '</nav>'; | |||
} | |||
function renderBar(container, html) { | |||
container.innerHTML = html; | |||
a. | // aktive Sprache markieren (falls wir auf /xx sind) | ||
var m = mw.config.get('wgPageName').match(/\/([a-z-]+)$/i); | |||
var current = (m ? m[1] : userLang).toLowerCase(); | |||
container.querySelectorAll('a[data-code]').forEach(function (a) { | |||
if (a.getAttribute('data-code').toLowerCase() === current) a.classList.add('active-lang'); | |||
}); | }); | ||
} | |||
// ========================================== | |||
// Leiste einfügen (unterhalb Header) | |||
var bar = document.createElement('div'); | |||
bar.id = 'custom-langbar'; | |||
var header = document.querySelector('.minerva-header') || document.body; | var header = document.querySelector('.minerva-header') || document.body; | ||
header.parentNode.insertBefore(bar, header.nextSibling); | header.parentNode.insertBefore(bar, header.nextSibling); | ||
// 1) Aus Cache lesen | |||
try { | |||
var cached = JSON.parse(localStorage.getItem(cacheKey) || 'null'); | |||
if (cached && (Date.now() - cached.t) < CACHE_TTL && typeof cached.html === 'string') { | |||
renderBar(bar, cached.html); | |||
} else { | |||
// 2) Neu bauen und cachen | |||
var html = buildHtml(); | |||
renderBar(bar, html); | |||
try { localStorage.setItem(cacheKey, JSON.stringify({ t: Date.now(), html: html })); } catch (e) {} | |||
} | |||
} catch (e) { | |||
// Fallback ohne Cache | |||
renderBar(bar, buildHtml()); | |||
} | |||
// ====== Event-Delegation (funktioniert auch mit gecachtem HTML) ====== | |||
bar.addEventListener('click', function (e) { | |||
var a = e.target.closest('a[data-code]'); | |||
if (!a) return; | |||
e.preventDefault(); | |||
switchLanguageAndGo(a.getAttribute('data-code')); | |||
}); | |||
// ===================================================================== | |||
// ---- Logik: Sprache setzen + auf Übersetzung springen ---- | // ---- Logik: Sprache setzen + auf Übersetzung springen ---- | ||
function targetUrlFor(code) { | function targetUrlFor(code) { | ||
// Special:MyLanguage löst auf die passende /lang-Unterseite | // Special:MyLanguage löst auf die passende /lang-Unterseite | ||
var title = 'Special:MyLanguage/' + baseTitle; | var title = 'Special:MyLanguage/' + baseTitle; | ||
var url = mw.util.getUrl(title); | var url = mw.util.getUrl(title); | ||
var sep = url.indexOf('?') > -1 ? '&' : '?'; | var sep = url.indexOf('?') > -1 ? '&' : '?'; | ||
// setlang sorgt dafür, dass UI+ULS sofort umspringen | |||
return url + sep + 'setlang=' + encodeURIComponent(code); | return url + sep + 'setlang=' + encodeURIComponent(code); | ||
} | } | ||
| Zeile 74: | Zeile 107: | ||
code = code.toLowerCase(); | code = code.toLowerCase(); | ||
if (mw.config.get('wgUserName')) { | if (mw.config.get('wgUserName')) { | ||
// Eingeloggt: Preference per API setzen, dann weiterleiten | |||
new mw.Api().postWithToken('csrf', { | new mw.Api().postWithToken('csrf', { | ||
action: 'options', | action: 'options', | ||
| Zeile 85: | Zeile 118: | ||
} | } | ||
// Gäste: | // Gäste: preferredLang merken und per setlang weiter | ||
try { localStorage.setItem('preferredLang', code); } catch (e) {} | try { localStorage.setItem('preferredLang', code); } catch (e) {} | ||
location.href = targetUrlFor(code); | location.href = targetUrlFor(code); | ||
| Zeile 98: | Zeile 131: | ||
if (!mw.config.get('wgUserName')) { | if (!mw.config.get('wgUserName')) { | ||
var ns = mw.config.get('wgNamespaceNumber'); | var ns = mw.config.get('wgNamespaceNumber'); | ||
if (ns % 2 === 1) { // ungerade Namespace-Nummern = | if (ns % 2 === 1) { // ungerade Namespace-Nummern = Talk | ||
var subjectUrl = mw.util.getUrl(mw.config.get('wgPageName').replace(/^Talk:/, '')); | var subjectUrl = mw.util.getUrl(mw.config.get('wgPageName').replace(/^Talk:/, '')); | ||
window.location.href = subjectUrl; | window.location.href = subjectUrl; | ||
Version vom 8. August 2025, 11:56 Uhr
/* Eigene Sprachleiste: UI-Sprache + PageTranslation-Ziel umschalten (mit Cache) */
mw.loader.using(['mediawiki.util', 'mediawiki.api'], function () {
// ====== Automatische Anwendung der gespeicherten Sprache für Gäste ======
if (!mw.config.get('wgUserName')) {
try {
var prefLang = localStorage.getItem('preferredLang');
var currentLang = (mw.config.get('wgUserLanguage') || '').toLowerCase();
if (
prefLang &&
prefLang.toLowerCase() !== currentLang &&
!/[?&](?:use|set)lang=/.test(location.search)
) {
// setlang = persistente ULS-Sprache (Cookie/Local)
var url = new URL(window.location.href);
url.searchParams.set('setlang', prefLang);
location.replace(url.toString());
return; // Rest erst nach Redirect ausführen
}
} catch (e) {}
}
// ========================================================================
// ---- deine Sprachen ----
var LANGS = [
{ code: 'de', label: 'Deutsch' },
{ code: 'en', label: 'English' },
{ code: 'fr', label: 'Français' }
];
// Wenn bereits eine Leiste existiert, nichts tun
if (document.getElementById('custom-langbar')) return;
var userLang = (mw.config.get('wgUserLanguage') || mw.config.get('wgContentLanguage') || 'de').toLowerCase();
var pageName = mw.config.get('wgPageName');
// Basis-Seitenname ohne evtl. Sprach-Suffix (/en, /fr, /pt-br, …)
var baseTitle = pageName.replace(/\/[a-z]{2}(?:-[a-z]{2})?$/i, '');
// ====== Caching-Setup für die Leiste ======
var CACHE_TTL = 24 * 60 * 60 * 1000; // 24h
var cacheKey = 'custom-langbar:' + baseTitle + ':' + LANGS.map(function (l) { return l.code; }).join(',') + ':v2';
function buildHtml() {
// Direkt zu /lang springen (oder Special:MyLanguage ohne /lang, wenn du lieber adaptiv willst)
return '<nav aria-label="Sprachen">' + LANGS.map(function (lang) {
var href = mw.util.getUrl(baseTitle + '/' + lang.code);
return '<a href="' + href + '" data-code="' + lang.code + '">' + lang.label + '</a>';
}).join(' ') + '</nav>';
}
function renderBar(container, html) {
container.innerHTML = html;
// aktive Sprache markieren (falls wir auf /xx sind)
var m = mw.config.get('wgPageName').match(/\/([a-z-]+)$/i);
var current = (m ? m[1] : userLang).toLowerCase();
container.querySelectorAll('a[data-code]').forEach(function (a) {
if (a.getAttribute('data-code').toLowerCase() === current) a.classList.add('active-lang');
});
}
// ==========================================
// Leiste einfügen (unterhalb Header)
var bar = document.createElement('div');
bar.id = 'custom-langbar';
var header = document.querySelector('.minerva-header') || document.body;
header.parentNode.insertBefore(bar, header.nextSibling);
// 1) Aus Cache lesen
try {
var cached = JSON.parse(localStorage.getItem(cacheKey) || 'null');
if (cached && (Date.now() - cached.t) < CACHE_TTL && typeof cached.html === 'string') {
renderBar(bar, cached.html);
} else {
// 2) Neu bauen und cachen
var html = buildHtml();
renderBar(bar, html);
try { localStorage.setItem(cacheKey, JSON.stringify({ t: Date.now(), html: html })); } catch (e) {}
}
} catch (e) {
// Fallback ohne Cache
renderBar(bar, buildHtml());
}
// ====== Event-Delegation (funktioniert auch mit gecachtem HTML) ======
bar.addEventListener('click', function (e) {
var a = e.target.closest('a[data-code]');
if (!a) return;
e.preventDefault();
switchLanguageAndGo(a.getAttribute('data-code'));
});
// =====================================================================
// ---- Logik: Sprache setzen + auf Übersetzung springen ----
function targetUrlFor(code) {
// Special:MyLanguage löst auf die passende /lang-Unterseite
var title = 'Special:MyLanguage/' + baseTitle;
var url = mw.util.getUrl(title);
var sep = url.indexOf('?') > -1 ? '&' : '?';
// setlang sorgt dafür, dass UI+ULS sofort umspringen
return url + sep + 'setlang=' + encodeURIComponent(code);
}
function switchLanguageAndGo(code) {
code = code.toLowerCase();
if (mw.config.get('wgUserName')) {
// Eingeloggt: Preference per API setzen, dann weiterleiten
new mw.Api().postWithToken('csrf', {
action: 'options',
change: 'language=' + code
}).always(function () {
location.href = targetUrlFor(code);
});
return;
}
// Gäste: preferredLang merken und per setlang weiter
try { localStorage.setItem('preferredLang', code); } catch (e) {}
location.href = targetUrlFor(code);
}
// Anonyme erkennen und Flag auf <html> setzen
if (!mw.config.get('wgUserName')) {
document.documentElement.classList.add('bv-anon');
}
// Gäste nicht auf Diskussionsseiten lassen → auf Inhaltsseite umleiten
if (!mw.config.get('wgUserName')) {
var ns = mw.config.get('wgNamespaceNumber');
if (ns % 2 === 1) { // ungerade Namespace-Nummern = Talk
var subjectUrl = mw.util.getUrl(mw.config.get('wgPageName').replace(/^Talk:/, ''));
window.location.href = subjectUrl;
}
}
});