MediaWiki:Gadget-I18nSwitcher.js: Difference between revisions
From Bodhicitta
(VSCode edit) |
(VSCode edit) |
||
| Line 152: | Line 152: | ||
if (currentLang === 'bo') { | if (currentLang === 'bo') { | ||
el.classList.add('text-130', ' | el.classList.add('text-130', 'line14'); | ||
} else { | } else { | ||
el.classList.remove('text-130', ' | el.classList.remove('text-130', 'line14'); | ||
} | } | ||
} | } | ||
Revision as of 14:18, 7 May 2026
// Universal language switcher for logged-in and anonymous users
(function() {
'use strict';
var currentLang = 'en';
var storageKey = 'bca-language-pref';
var isLoggedIn = false;
// Check if user is logged in
function checkLoginStatus() {
if (window.mw && mw.user) {
isLoggedIn = !mw.user.isAnon();
} else {
// Fallback: check for login-specific elements
isLoggedIn = document.getElementById('pt-userpage') !== null;
}
return isLoggedIn;
}
// Get stored language preference
function getStoredLang() {
try {
// For logged-in users, try MediaWiki user options first
if (isLoggedIn && window.mw && mw.user && mw.user.options) {
var userPref = mw.user.options.get('bca-language');
if (userPref) {
return userPref;
}
}
// For all users, try localStorage
if (window.localStorage) {
var stored = localStorage.getItem(storageKey);
if (stored) {
return stored;
}
}
// Fallback to cookie
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
if (cookie.indexOf(storageKey + '=') === 0) {
return cookie.substring(storageKey.length + 1);
}
}
} catch (e) {
console.log('Error getting stored language:', e);
}
return 'en';
}
// Store language preference
function storeLang(lang) {
try {
// For logged-in users, save to MediaWiki preferences
if (isLoggedIn && window.mw && mw.user && mw.user.options && mw.Api) {
mw.user.options.set('bca-language', lang);
new mw.Api().saveOption('bca-language', lang).catch(function(error) {
console.log('Failed to save to user preferences:', error);
});
}
// For all users, save to localStorage
if (window.localStorage) {
localStorage.setItem(storageKey, lang);
}
// Fallback to cookie for all users
var expires = new Date();
expires.setTime(expires.getTime() + (365 * 24 * 60 * 60 * 1000)); // 1 year
document.cookie = storageKey + '=' + lang + '; expires=' + expires.toUTCString() + '; path=/';
} catch (e) {
console.log('Error storing language:', e);
}
}
function createLanguageToggle() {
var toggle = document.createElement('div');
toggle.className = 'lang-toggle nowrap';
// Add user type indicator for debugging (remove in production)
var userType = isLoggedIn ? ' (logged in)' : ' (anonymous)';
toggle.innerHTML = '<button type="button" data-lang="en" class="lang-btn">english</button><i class="fa-sharp-duotone fa-solid fa-caret-left text-right" style="color: #86cf96;"></i><i class="fa-sharp-duotone fa-solid fa-caret-right text-left" style="color: #86cf96;"></i><button type="button" data-lang="bo" class="lang-btn text-120">བོད་སྐད་</button>';
// Try different locations for the toggle
var targetElement = document.querySelector('.navbar-collapse > .navbar-nav:first-of-type');
if (targetElement) {
targetElement.appendChild(toggle);
}
// Add click handlers
toggle.onclick = function(e) {
var target = e.target || e.srcElement;
if (target.className.indexOf('lang-btn') !== -1) {
var lang = target.getAttribute('data-lang');
if (lang) {
switchLanguage(lang);
}
}
};
// Initialize with stored preference
currentLang = getStoredLang();
updateActiveButton();
switchLanguage(currentLang);
}
function updateActiveButton() {
var buttons = document.querySelectorAll('.lang-btn') ||
document.getElementsByClassName('lang-btn');
for (var i = 0; i < buttons.length; i++) {
var btn = buttons[i];
if (btn.getAttribute('data-lang') === currentLang) {
btn.className = btn.className.replace(' active', '') + ' active';
} else {
btn.className = btn.className.replace(' active', '');
}
}
}
function switchLanguage(lang) {
currentLang = lang;
storeLang(lang);
updateActiveButton();
// Switch all i18n elements
var elements = document.querySelectorAll('.i18n-text') ||
document.getElementsByClassName('i18n-text');
for (var i = 0; i < elements.length; i++) {
var el = elements[i];
var targetSpan = el.querySelector('.i18n-lang-' + lang);
var defaultLang = el.getAttribute('data-default') || 'en';
var fallbackSpan = el.querySelector('.i18n-lang-' + defaultLang);
// Hide all lang spans, then show the right one
var langSpans = el.querySelectorAll('[class^="i18n-lang-"]');
for (var j = 0; j < langSpans.length; j++) {
langSpans[j].style.display = 'none';
}
if (targetSpan) {
// Use block display for div elements, inline for span
targetSpan.style.display = targetSpan.tagName === 'DIV' ? 'block' : 'inline';
} else if (fallbackSpan) {
fallbackSpan.style.display = fallbackSpan.tagName === 'DIV' ? 'block' : 'inline';
}
if (currentLang === 'bo') {
el.classList.add('text-130', 'line14');
} else {
el.classList.remove('text-130', 'line14');
}
}
}
// Initialize when DOM is ready
function init() {
checkLoginStatus();
// Re-run switchLanguage on any new .i18n-text nodes injected by SMW deferred queries
function watchForI18nContent() {
if (!window.MutationObserver) return;
var observer = new MutationObserver(function(mutations) {
var found = false;
for (var m = 0; m < mutations.length; m++) {
var nodes = mutations[m].addedNodes;
for (var n = 0; n < nodes.length; n++) {
var node = nodes[n];
if (node.nodeType !== 1) continue;
if (node.classList && node.classList.contains('i18n-text') ||
node.querySelector && node.querySelector('.i18n-text')) {
found = true;
break;
}
}
if (found) break;
}
if (found) {
if (!document.querySelector('.lang-toggle')) {
createLanguageToggle();
} else {
switchLanguage(currentLang);
}
}
});
observer.observe(document.body, { childList: true, subtree: true });
}
function setup() {
if (document.querySelector('.i18n-text')) {
createLanguageToggle();
}
// Always watch: SMW deferred queries may inject .i18n-text after init
watchForI18nContent();
}
// Prefer mw.hook so we re-run after cached/ajax content loads
if (window.mw && mw.hook) {
mw.hook('wikipage.content').add(function() {
// Remove any previously inserted toggle to avoid duplicates on re-fire
var existing = document.querySelector('.lang-toggle');
if (existing) {
existing.parentNode.removeChild(existing);
}
setup();
});
} else if (document.readyState === 'complete' || document.readyState === 'interactive') {
setup();
} else {
document.addEventListener('DOMContentLoaded', setup);
}
}
init();
})();