Keine Bearbeitungszusammenfassung
Markierungen: Manuelle Zurücksetzung Zurückgesetzt
Keine Bearbeitungszusammenfassung
Markierung: Zurückgesetzt
Zeile 1: Zeile 1:
/* Eigene Sprachleiste: manuelles Umschalten + stabile Navigation über Special:MyLanguage */
/* Eigene Sprachleiste: manuelles Umschalten mit setlang + Anpassung aller MyLanguage-Links */
mw.loader.using(['mediawiki.util', 'mediawiki.api'], function () {
mw.loader.using(['mediawiki.util', 'mediawiki.api'], function () {


   // --- Nur im Lesemodus + im Haupt-Namensraum (0) anzeigen ---
   // --- Grundkonfiguration ---
  var action = mw.config.get('wgAction');
  var ns = mw.config.get('wgNamespaceNumber');
  if (action !== 'view' || ns !== 0) return;
 
  // --- Sprachen definieren ---
   var LANGS = [
   var LANGS = [
     { code: 'de', label: 'Deutsch' },
     { code: 'de', label: 'Deutsch' },
Zeile 16: Zeile 11:
   var FALLBACK = 'en';
   var FALLBACK = 'en';


   // Doppelte Einbindung vermeiden
   // --- Doppelte Einbindung verhindern ---
   if (document.getElementById('custom-langbar')) return;
   if (document.getElementById('custom-langbar')) return;


   var pageName = mw.config.get('wgPageName'); // mit _ statt Leerzeichen
   var pageName = mw.config.get('wgPageName');
   var baseTitle = pageName.replace(/\/[a-z]{2}(?:-[a-z]{2})?$/i, ''); // ggf. /de,/en,… abschneiden
   var baseTitle = pageName.replace(/\/[a-z]{2}(?:-[a-z]{2})?$/i, '');


   function normalize(code) {
   function normalize(code) {
Zeile 28: Zeile 23:
   }
   }


  function getCurrentLang() {
   // Ziel-URL: gleiche Seite mit setlang erzwingen
    var u = new URL(window.location.href);
    var fromUrl = u.searchParams.get('uselang');
    return normalize(fromUrl || null);
  }
 
   // Ziel-URL: gleiche Seite in gewünschter Sprache über Special:MyLanguage + uselang
   function targetUrl(code) {
   function targetUrl(code) {
     code = normalize(code);
     code = normalize(code);
     var title = 'Special:MyLanguage/' + baseTitle.replace(/_/g, ' ');
     var title = 'Special:MyLanguage/' + baseTitle.replace(/_/g, ' ');
     var url = mw.util.getUrl(title);
     var url = mw.util.getUrl(title);
     return url + (url.includes('?') ? '&' : '?') + 'uselang=' + code;
     return url + (url.includes('?') ? '&' : '?') + 'setlang=' + code;
   }
   }


   // --- Falls uselang ungültig (z. B. ?uselang=frok) → einmalig auf gültig korrigieren ---
   // --- Sprachleiste bauen ---
   (function fixInvalidUselangOnce() {
   var current = normalize(mw.config.get('wgUserLanguage') || mw.config.get('wgContentLanguage') || FALLBACK);
    var u = new URL(window.location.href);
    var raw = u.searchParams.get('uselang');
    if (raw && normalize(raw) !== raw.toLowerCase().split('-')[0]) {
      u.searchParams.set('uselang', normalize(raw));
      window.history.replaceState(null, '', u.toString()); // kein Reload, nur URL bereinigen
    }
  })();
 
  // --- Bar bauen ---
   var bar = document.createElement('div');
   var bar = document.createElement('div');
   bar.id = 'custom-langbar';
   bar.id = 'custom-langbar';
  var current = getCurrentLang() ||
    normalize(mw.config.get('wgUserLanguage') || mw.config.get('wgContentLanguage') || FALLBACK);


   LANGS.forEach(function (lang) {
   LANGS.forEach(function (lang) {
Zeile 71: Zeile 48:
   });
   });


   // Sicher ins DOM hängen (Minerva/Vector kompatibel)
   // In DOM einfügen
   var mount =
   var mount =
     document.querySelector('.minerva-header') ||
     document.querySelector('.minerva-header') ||
Zeile 84: Zeile 61:
   }
   }


   // Sprachwechsel: eingeloggte speichern; Gäste nur per URL-Parameter
   // --- Sprache umschalten ---
   function switchLanguage(code) {
   function switchLanguage(code) {
     code = normalize(code);
     code = normalize(code);


     if (mw.config.get('wgUserName')) {
     if (mw.config.get('wgUserName')) {
      // Eingeloggt: User-Option setzen
       new mw.Api().postWithToken('csrf', {
       new mw.Api().postWithToken('csrf', {
         action: 'options',
         action: 'options',
Zeile 96: Zeile 74:
       });
       });
     } else {
     } else {
      // Gäste: nur URL-Wechsel
       location.href = targetUrl(code);
       location.href = targetUrl(code);
     }
     }
   }
   }


   // ---------- Link-Rewriting im Artikeltext ----------
   // --- Alle MyLanguage-Links im Dokument anpassen ---
   // Alle internen Content-Links auf Special:MyLanguage/<Ziel> + aktuellen uselang umbiegen,
   function adjustMyLanguageLinks(langCode) {
  // damit nicht auf falsche /xx-Unterseiten gesprungen wird.
    langCode = normalize(langCode);
  (function rewriteContentLinks() {
    document.querySelectorAll('a[href*="Special:MyLanguage/"]').forEach(function (link) {
    var root = document.querySelector('.mw-parser-output');
      var url = new URL(link.href, window.location.origin);
     if (!root) return;
      url.searchParams.set('setlang', langCode);
      link.href = url.toString();
     });
  }


    var curLang = getCurrentLang() || current;
  // Sofort auf aktuelle Sprache anwenden
  adjustMyLanguageLinks(current);


    // Namespaces/Pattern, die wir NICHT anfassen
  // Falls der Nutzer über die Sprachleiste wechselt, Links neu anpassen
    var skipPrefixes = [
  LANGS.forEach(function (lang) {
      'Special:', 'Spezial:', 'File:', 'Datei:', 'Image:', 'Media:', 'MediaWiki:',
     document.querySelectorAll('#custom-langbar a[data-code="' + lang.code + '"]').forEach(function (el) {
      'Template:', 'Vorlage:', 'Category:', 'Kategorie:', 'Help:', 'Hilfe:',
       el.addEventListener('click', function () {
      'User:', 'Benutzer:', 'Talk:', 'Diskussion:'
         adjustMyLanguageLinks(lang.code);
    ];
       });
    function shouldSkipTitle(title) {
      if (!title) return true;
      var t = title.replace(/_/g, ' ');
      return skipPrefixes.some(function (p) { return t.startsWith(p); });
    }
 
     function getTitleFromHref(href) {
      try {
        var url = new URL(href, window.location.origin);
        // Extern?
        if (url.origin !== window.location.origin) return null;
        // Anchors
        if (url.hash && (url.pathname === window.location.pathname) && !url.searchParams.get('title')) return null;
 
        // /wiki/Title
        var m = url.pathname.match(/\/wiki\/(.+)$/);
        if (m && m[1]) {
          return decodeURIComponent(m[1]);
        }
        // /index.php?title=Title
        var t = url.searchParams.get('title');
        if (t) return t;
 
        return null;
      } catch (e) {
        return null;
      }
    }
 
    function stripLangSuffix(title) {
      // Sprachsuffix am Ende entfernen (…/de, …/en, …/fr)
      return title.replace(/\/([a-z]{2})(?:-[a-z]{2})?$/i, '');
    }
 
    root.querySelectorAll('a[href]').forEach(function (a) {
       var href = a.getAttribute('href');
      if (!href || href.startsWith('#')) return;
 
      var title = getTitleFromHref(href);
      if (!title || shouldSkipTitle(title)) return;
 
      // Edit/History/Action-Links nicht anfassen
      if (/\b(action|oldid|diff)=/.test(href)) return;
 
      // Wenn Link bereits Special:MyLanguage ist, nur uselang sicherstellen
      if (/Special:MyLanguage\//i.test(title)) {
        var url = new URL(a.href, window.location.origin);
        if (!url.searchParams.get('uselang')) {
          url.searchParams.set('uselang', curLang);
          a.href = url.toString();
        }
         return;
      }
 
      // Sprachsuffix entfernen und zu Special:MyLanguage umschreiben
      var base = stripLangSuffix(title);
      var newUrl = mw.util.getUrl('Special:MyLanguage/' + base.replace(/_/g, ' '));
      newUrl += (newUrl.includes('?') ? '&' : '?') + 'uselang=' + curLang;
 
      // Fragment (#anchor) beibehalten
      try {
        var old = new URL(a.href, window.location.origin);
        if (old.hash) newUrl += old.hash;
       } catch (e) {}
 
      a.href = newUrl;
     });
     });
   })();
   });


   // Anonyme markieren (falls du CSS darauf hast)
   // --- Anonyme markieren (falls CSS nötig) ---
   if (!mw.config.get('wgUserName')) {
   if (!mw.config.get('wgUserName')) {
     document.documentElement.classList.add('bv-anon');
     document.documentElement.classList.add('bv-anon');
   }
   }


   // Gäste nicht auf Diskussionsseiten lassen → zurück zur Inhaltseite
   // --- Gäste nicht auf Diskussionsseiten lassen ---
   if (!mw.config.get('wgUserName')) {
   if (!mw.config.get('wgUserName')) {
     var nsNum = mw.config.get('wgNamespaceNumber');
     var nsNum = mw.config.get('wgNamespaceNumber');

Version vom 8. August 2025, 14:32 Uhr

/* Eigene Sprachleiste: manuelles Umschalten mit setlang + Anpassung aller MyLanguage-Links */
mw.loader.using(['mediawiki.util', 'mediawiki.api'], function () {

  // --- Grundkonfiguration ---
  var LANGS = [
    { code: 'de', label: 'Deutsch' },
    { code: 'en', label: 'English' },
    { code: 'fr', label: 'Français' }
  ];
  var ALLOWED = ['de', 'en', 'fr'];
  var FALLBACK = 'en';

  // --- Doppelte Einbindung verhindern ---
  if (document.getElementById('custom-langbar')) return;

  var pageName = mw.config.get('wgPageName');
  var baseTitle = pageName.replace(/\/[a-z]{2}(?:-[a-z]{2})?$/i, '');

  function normalize(code) {
    if (!code) return FALLBACK;
    code = String(code).toLowerCase().split('-')[0];
    return ALLOWED.indexOf(code) > -1 ? code : FALLBACK;
  }

  // Ziel-URL: gleiche Seite mit setlang erzwingen
  function targetUrl(code) {
    code = normalize(code);
    var title = 'Special:MyLanguage/' + baseTitle.replace(/_/g, ' ');
    var url = mw.util.getUrl(title);
    return url + (url.includes('?') ? '&' : '?') + 'setlang=' + code;
  }

  // --- Sprachleiste bauen ---
  var current = normalize(mw.config.get('wgUserLanguage') || mw.config.get('wgContentLanguage') || FALLBACK);
  var bar = document.createElement('div');
  bar.id = 'custom-langbar';

  LANGS.forEach(function (lang) {
    var a = document.createElement('a');
    a.href = '#';
    a.textContent = lang.label;
    if (current === lang.code) a.className = 'active-lang';
    a.addEventListener('click', function (e) {
      e.preventDefault();
      switchLanguage(lang.code);
    });
    bar.appendChild(a);
  });

  // In DOM einfügen
  var mount =
    document.querySelector('.minerva-header') ||
    document.querySelector('.vector-header') ||
    document.getElementById('content') ||
    document.body;

  if (mount && mount.parentNode) {
    mount.parentNode.insertBefore(bar, mount.nextSibling);
  } else {
    document.body.insertBefore(bar, document.body.firstChild);
  }

  // --- Sprache umschalten ---
  function switchLanguage(code) {
    code = normalize(code);

    if (mw.config.get('wgUserName')) {
      // Eingeloggt: User-Option setzen
      new mw.Api().postWithToken('csrf', {
        action: 'options',
        change: 'language=' + code
      }).always(function () {
        location.href = targetUrl(code);
      });
    } else {
      // Gäste: nur URL-Wechsel
      location.href = targetUrl(code);
    }
  }

  // --- Alle MyLanguage-Links im Dokument anpassen ---
  function adjustMyLanguageLinks(langCode) {
    langCode = normalize(langCode);
    document.querySelectorAll('a[href*="Special:MyLanguage/"]').forEach(function (link) {
      var url = new URL(link.href, window.location.origin);
      url.searchParams.set('setlang', langCode);
      link.href = url.toString();
    });
  }

  // Sofort auf aktuelle Sprache anwenden
  adjustMyLanguageLinks(current);

  // Falls der Nutzer über die Sprachleiste wechselt, Links neu anpassen
  LANGS.forEach(function (lang) {
    document.querySelectorAll('#custom-langbar a[data-code="' + lang.code + '"]').forEach(function (el) {
      el.addEventListener('click', function () {
        adjustMyLanguageLinks(lang.code);
      });
    });
  });

  // --- Anonyme markieren (falls CSS nötig) ---
  if (!mw.config.get('wgUserName')) {
    document.documentElement.classList.add('bv-anon');
  }

  // --- Gäste nicht auf Diskussionsseiten lassen ---
  if (!mw.config.get('wgUserName')) {
    var nsNum = mw.config.get('wgNamespaceNumber');
    if (nsNum % 2 === 1) {
      var subject = mw.util.getUrl(mw.config.get('wgPageName').replace(/^Talk:/, ''));
      window.location.href = subject;
    }
  }
});