MediaWiki:Vector.js: Difference between revisions
Jump to navigation
Jump to search
Link the header username to the user talk page; open the account menu only from its arrow |
Preserve sidebar colour spans and icons when translating navigation labels |
||
| (13 intermediate revisions by the same user not shown) | |||
| Line 231: | Line 231: | ||
accountName.className = 'gd-account-talk-link'; | accountName.className = 'gd-account-talk-link'; | ||
var userName = mw.config.get('wgUserName'); | var userName = mw.config.get('wgUserName'); | ||
accountName.href = mw.util.getUrl(userName ? 'User | accountName.href = mw.util.getUrl(userName ? 'User:' + userName : 'Special:UserLogin'); | ||
accountName.innerHTML = iconMarkup('user'); | accountName.innerHTML = iconMarkup('user'); | ||
var nameText = document.createElement('span'); | var nameText = document.createElement('span'); | ||
nameText.textContent = userName || 'Account'; | nameText.textContent = userName || 'Account'; | ||
accountName.appendChild(nameText); | accountName.appendChild(nameText); | ||
accountName.title = userName ? 'Your | accountName.title = userName ? 'Your user page' : 'Log in'; | ||
accountGroup.appendChild(accountName); | accountGroup.appendChild(accountName); | ||
account.appendChild(accountLabel); | account.appendChild(accountLabel); | ||
var duplicateUserPage = links.querySelector('#pt-userpage'); | |||
if (duplicateUserPage) duplicateUserPage.remove(); | |||
links.classList.add('gd-account-links'); | links.classList.add('gd-account-links'); | ||
account.appendChild(links); | account.appendChild(links); | ||
accountGroup.appendChild(account); | accountGroup.appendChild(account); | ||
controls.appendChild(accountGroup); | controls.appendChild(accountGroup); | ||
var barLogo = document.createElement('a'); | |||
barLogo.className = 'gd-header-bar-logo'; | |||
barLogo.href = mw.util.getUrl(mw.config.get('wgMainPageTitle') || 'Main Page'); | |||
barLogo.title = mw.config.get('wgSiteName') || 'Geometry Dash Expanded Wiki'; | |||
barLogo.setAttribute('aria-label', barLogo.title + ' main page'); | |||
var logoImage = document.createElement('img'); | |||
logoImage.src = 'https://geometrydashwiki.com/images/d/d4/Logo.jpg'; | |||
logoImage.alt = ''; logoImage.width = 32; logoImage.height = 32; | |||
barLogo.appendChild(logoImage); | |||
personal.appendChild(barLogo); | |||
personal.appendChild(controls); | personal.appendChild(controls); | ||
personal.classList.add('gd-header-ready'); | personal.classList.add('gd-header-ready'); | ||
| Line 255: | Line 267: | ||
}); | }); | ||
}()); | }()); | ||
/* Expanded multilingual navigation: shared accounts, files and Recent Changes. */ | |||
(function () { | |||
'use strict'; | |||
mw.loader.using(['mediawiki.api', 'mediawiki.util']).then(function () { | |||
$(function () { | |||
var controls = document.querySelector('.gd-header-controls'); | |||
if (!controls || document.getElementById('gd-language-menu')) return; | |||
var page = (mw.config.get('wgPageName') || 'Main_Page').replace(/_/g, ' '); | |||
var match = /^(Spa|Rus|Pol)\/(.+)$/.exec(page); | |||
var pathCode = /^\/(eng|spa|rus|pol)(?:\/|$)/.exec(location.pathname); | |||
var articleCode = match ? match[1].toLowerCase() : 'eng'; | |||
var cookie = /(?:^|;\s*)gdwiki-language=(eng|spa|rus|pol)(?:;|$)/.exec(document.cookie); | |||
var code = cookie ? cookie[1] : (mw.config.get('wgExpandedActiveLanguage') || (pathCode ? pathCode[1] : articleCode)); | |||
var base = match ? match[2] : page; | |||
var spanish = code === 'spa'; | |||
var isArticle = mw.config.get('wgNamespaceNumber') === 0; | |||
document.documentElement.setAttribute('data-gd-language', code); | |||
var definitions = [ | |||
{code:'eng', name:'English', lang:'en', flag:'/images/4/49/Flag_gb.svg'}, | |||
{code:'spa', name:'Español', lang:'es', flag:'/images/2/2d/Flag_es.svg'} | |||
]; | |||
var menu = document.createElement('details'); | |||
menu.id = 'gd-language-menu'; menu.className = 'gd-header-menu gd-language-menu'; | |||
var summary = document.createElement('summary'); | |||
summary.setAttribute('aria-label', spanish ? 'Cambiar idioma' : 'Change language'); | |||
summary.title = summary.getAttribute('aria-label'); | |||
var current = definitions[spanish ? 1 : 0]; | |||
var image = document.createElement('img'); image.src=current.flag; image.alt=''; image.width=24; image.height=16; | |||
summary.appendChild(image); | |||
var label=document.createElement('span'); label.textContent=current.name; summary.appendChild(label); | |||
menu.appendChild(summary); | |||
var panel=document.createElement('div'); panel.className='gd-header-dropdown gd-language-options'; | |||
panel.setAttribute('aria-label', spanish ? 'Idiomas' : 'Languages'); | |||
menu.appendChild(panel); | |||
var personal = document.getElementById('p-personal'); | |||
personal.appendChild(menu); | |||
var api=new mw.Api(); | |||
function route(title, lang) { | |||
if (!mw.config.get('wgExpandedLanguageRoutes')) return mw.util.getUrl(title); | |||
var m=/^(Spa|Rus|Pol)\/(.+)$/.exec(title); | |||
var language=m ? m[1].toLowerCase() : 'eng'; | |||
var name=m ? m[2] : title; | |||
if (name.indexOf(':')!==-1 && !m) return mw.util.getUrl(title); | |||
return '/'+language+'/'+encodeURIComponent(name.replace(/ /g,'_')).replace(/%2F/g,'/'); | |||
} | |||
function build(mapping) { | |||
var entry=mapping[base] || {}; | |||
Object.keys(mapping).some(function (key) { | |||
if (mapping[key][articleCode]===page) {base=key;entry=mapping[key];return true;} | |||
return false; | |||
}); | |||
var titles=definitions.map(function (d) { | |||
return isArticle ? (entry[d.code] || (d.code==='eng' ? base : 'Spa/'+base)) : page; | |||
}); | |||
api.get({action:'query',titles:titles.join('|'),prop:'info',formatversion:2}).then(function (data) { | |||
var existing={}; | |||
(data.query.pages || []).forEach(function (p) {existing[p.title]=!p.missing && !p.invalid;}); | |||
definitions.forEach(function (d,i) { | |||
var available=existing[titles[i]], target=available || !isArticle ? titles[i] : titles[0]; | |||
var link=document.createElement('a');link.lang=d.lang;link.hreflang=d.lang; | |||
var flag=document.createElement('img');flag.src=d.flag;flag.alt='';flag.width=24;flag.height=16;link.appendChild(flag); | |||
var text=document.createElement('span');text.textContent=d.name;link.appendChild(text); | |||
if(d.code===code)link.setAttribute('aria-current','page'); | |||
link.href=route(target,d.lang); | |||
link.addEventListener('click',function () { | |||
document.cookie='gdwiki-language='+d.code+'; Path=/; Max-Age=31536000; SameSite=Lax; Secure'; | |||
try { | |||
localStorage.setItem('gdwiki-language',d.code); | |||
if(isArticle && !available)sessionStorage.setItem('gdwiki-fallback',JSON.stringify({language:d.code,page:base})); | |||
} catch(error) {} | |||
}); | |||
panel.appendChild(link); | |||
}); | |||
if(isArticle && !existing[titles[1]]) { | |||
var create=document.createElement('a');create.className='gd-language-create'; | |||
create.textContent=spanish ? 'Crear traducción al español' : 'Create Spanish translation'; | |||
if(mw.config.get('wgExpandedLanguageEditorSafe')) { | |||
var editParams={action:'edit',preload:titles[0],summary:'Start Español translation from [['+titles[0]+']]'}; | |||
create.href=route(titles[1],'es')+'?'+new URLSearchParams(editParams).toString(); | |||
} else {create.setAttribute('aria-disabled','true');create.title='Translation setup awaiting server update';} | |||
panel.appendChild(create); | |||
} | |||
var home=document.createElement('a');home.className='gd-language-home';home.textContent=spanish ? 'Inicio' : 'Home';home.href=route('Main Page','en');panel.appendChild(home); | |||
var guide=document.createElement('a');guide.textContent=spanish ? 'Guía de traducción' : 'Translation guide';guide.href=mw.util.getUrl('Help:Translations');panel.appendChild(guide); | |||
}, function () {panel.textContent=spanish ? 'No se pudieron cargar los idiomas. Recarga la página.' : 'Languages could not load. Reload the page.';}); | |||
} | |||
api.get({action:'query',titles:'MediaWiki:Expanded-language-pages.json',prop:'revisions',rvprop:'content',rvslots:'main',formatversion:2}).then(function (data) { | |||
try {build(JSON.parse(data.query.pages[0].revisions[0].slots.main.content));} catch (error) {build({});} | |||
},function () {build({});}); | |||
document.addEventListener('click',function (event) {if (!menu.contains(event.target)) menu.open=false;}); | |||
document.addEventListener('keydown',function (event) {if (event.key==='Escape') menu.open=false;}); | |||
if (spanish) { | |||
var interfaceLabels={"Navigation": "Navegación", "Main page": "Página principal", "Recent changes": "Cambios recientes", "New files": "Archivos nuevos", "Random page": "Página aleatoria", "New here? Get started": "¿Eres nuevo? Empieza aquí", ">> Site policy": ">> Normas del sitio", ">> Staff": ">> Administración", "Help using MediaWiki": "Ayuda sobre MediaWiki", "GD Base Content": "Contenido base de GD", "Games": "Juegos", "Main levels": "Niveles principales", "Gameplay": "Jugabilidad", "Rewards": "Recompensas", "Rooms (vaults etc.)": "Salas (bóvedas, etc.)", "Level editing": "Editor de niveles", "Account features": "Funciones de la cuenta", "Updates": "Actualizaciones", "GD Community Content": "Contenido de la comunidad de GD", "Demon List levels": "Niveles de la Demon List", "Gauntlet levels": "Niveles de gauntlets", "Map Pack levels": "Niveles de paquetes de mapas", "Classic levels": "Niveles clásicos", "Platformer levels": "Niveles de plataformas", "Players": "Jugadores", "Community activities": "Actividades de la comunidad", "Wiki Resources": "Recursos de la wiki", "Propose new articles": "Proponer artículos nuevos", "Submit edits for review": "Enviar cambios para revisión", "Admin Dashboard": "Panel de administración", "Images": "Imágenes", "Videos": "Vídeos", "Audio": "Audio", "PDFs": "PDF", "Templates": "Plantillas", "Sandbox": "Zona de pruebas", "Discuss the wiki": "Debatir sobre la wiki", "Guestbook": "Libro de visitas", "Tools": "Herramientas", "What links here": "Lo que enlaza aquí", "Related changes": "Cambios relacionados", "Upload file": "Subir archivo", "Printable version": "Versión para imprimir", "Permanent link": "Enlace permanente", "Page information": "Información de la página", "Account": "Cuenta", "Preferences": "Preferencias", "Your user page": "Tu página de usuario", "Log in": "Iniciar sesión", "Account menu": "Menú de cuenta", "Appearance": "Apariencia"}; | |||
document.querySelectorAll('#mw-panel h3, #mw-panel h3 span, #mw-panel a, .gd-account-links a, .gd-account-talk-link span').forEach(function (element) { | |||
var key=element.textContent.trim(); | |||
if (interfaceLabels[key]) { | |||
// Translate text nodes without removing colour spans, links or icons. | |||
var walker=document.createTreeWalker(element,NodeFilter.SHOW_TEXT), node; | |||
while ((node=walker.nextNode())) { | |||
var original=node.nodeValue.trim(); | |||
if (interfaceLabels[original]) node.nodeValue=node.nodeValue.replace(original,interfaceLabels[original]); | |||
} | |||
} | |||
}); | |||
document.querySelectorAll('#p-personal [title], #p-personal [aria-label]').forEach(function (element) { | |||
['title','aria-label'].forEach(function (attr) {var key=element.getAttribute(attr);if(interfaceLabels[key])element.setAttribute(attr,interfaceLabels[key]);}); | |||
}); | |||
var appearance=controls.querySelector('.gd-header-menu summary'); | |||
if (appearance) {appearance.textContent='Apariencia';appearance.title='Apariencia';appearance.setAttribute('aria-label','Apariencia');} | |||
var account=controls.querySelector('.gd-account-menu summary'); | |||
if (account) {account.title='Menú de cuenta';account.setAttribute('aria-label','Menú de cuenta');} | |||
var titles={'Blue':'Azul','Purple':'Morado','Green':'Verde','Red':'Rojo','Dark':'Oscuro','Blackout':'Negro','Vault':'La bóveda','Vault of Secrets':'La bóveda de los secretos','Chamber of Time':'La cámara del tiempo'}; | |||
controls.querySelectorAll('.gd-theme-option').forEach(function (button) {if(titles[button.textContent])button.textContent=titles[button.textContent];}); | |||
} | |||
// Optional translated assets use the same existing theme filters. | |||
var logos=mw.config.get('wgExpandedLanguageLogos') || {}; | |||
logos.spa=Object.assign({"header": "https://geometrydashwiki.com/images/4/4a/Logo-spa.jpg", "banner": "https://geometrydashwiki.com/images/a/a7/Site-logo-spa.png"},logos.spa || {}); | |||
if (logos[code]) { | |||
if (logos[code].header) { | |||
var header=document.querySelector('.gd-header-bar-logo img');if(header)header.src=logos[code].header; | |||
} | |||
if (logos[code].banner) document.documentElement.style.setProperty('--wiki-logo-image','url("'+logos[code].banner.replace(/["\\]/g,'')+'")'); | |||
} | |||
}); | |||
}); | |||
}()); | |||
/* Keep language parameters and script endpoints out of visible navigation URLs. */ | |||
(function () { | |||
'use strict'; | |||
function clean(raw) { | |||
var url; | |||
try {url=new URL(raw,location.href);} catch(error) {return raw;} | |||
if (url.origin!==location.origin) return raw; | |||
url.searchParams.delete('uselang'); | |||
if (/\/index\.php$/.test(url.pathname) && !url.searchParams.has('title') && url.searchParams.has('search')) {url.pathname='/wiki/Special:Search';} | |||
if (/\/index\.php$/.test(url.pathname) && url.searchParams.has('title')) { | |||
var title=url.searchParams.get('title');url.searchParams.delete('title'); | |||
var match=/^(Spa|Rus|Pol)\/(.+)$/.exec(title.replace(/_/g,' ')); | |||
var ns=title.indexOf(':')!==-1; | |||
var prefix=match ? '/'+match[1].toLowerCase()+'/' : (ns ? '/wiki/' : '/eng/'); | |||
var name=match ? match[2] : title; | |||
url.pathname=prefix+encodeURIComponent(name.replace(/ /g,'_')).replace(/%2F/g,'/').replace(/%3A/g,':'); | |||
} | |||
return url.pathname+url.search+url.hash; | |||
} | |||
// The current request has already chosen its interface language. | |||
var address=new URL(location.href); | |||
var cleanAddress=clean(location.href); | |||
if (cleanAddress!==address.pathname+address.search+address.hash) history.replaceState(null,'',cleanAddress); | |||
function links() { | |||
document.querySelectorAll('a[href]').forEach(function (link) { | |||
var href=link.getAttribute('href'); | |||
if (href && !/^(?:#|javascript:|mailto:)/.test(href)) { | |||
var replacement=clean(href);if(replacement!==href)link.setAttribute('href',replacement); | |||
} | |||
}); | |||
} | |||
$(function () { | |||
links(); | |||
var pending=false; | |||
new MutationObserver(function () { | |||
if(pending)return;pending=true; | |||
requestAnimationFrame(function () {pending=false;links();}); | |||
}).observe(document.body,{childList:true,subtree:true}); | |||
}); | |||
mw.hook('wikipage.content').add(links); | |||
// Also handles asynchronously built language and account menus. | |||
document.addEventListener('click',function(event) { | |||
var link=event.target.closest && event.target.closest('a[href]'); | |||
if(link)link.setAttribute('href',clean(link.getAttribute('href'))); | |||
},true); | |||
}()); | |||
/* Article-language tabs and links follow the persistent site language. */ | |||
(function () { | |||
'use strict'; | |||
mw.loader.using(['mediawiki.api','mediawiki.util']).then(function () { | |||
$(function () { | |||
var cookie=/(?:^|;\s*)gdwiki-language=(eng|spa|rus|pol)(?:;|$)/.exec(document.cookie); | |||
var mode=cookie ? cookie[1] : (mw.config.get('wgExpandedActiveLanguage') || mw.config.get('wgExpandedLanguage') || 'eng'); | |||
var names={eng:'English',spa:'Español',rus:'Русский',pol:'Polski'}; | |||
var notices={eng:'This article is not available in English. Showing the original article.',spa:'Este artículo todavía no está disponible en español. Se muestra la versión en inglés.',rus:'Эта статья пока недоступна на русском языке. Показана английская версия.',pol:'Ten artykuł nie jest jeszcze dostępny po polsku. Wyświetlono wersję angielską.'}; | |||
try { | |||
var pending=JSON.parse(sessionStorage.getItem('gdwiki-fallback') || 'null'); | |||
sessionStorage.removeItem('gdwiki-fallback'); | |||
if(!pending && mw.config.get('wgExpandedLanguageFallback'))pending={language:mw.config.get('wgExpandedLanguageFallback')}; | |||
if(pending && notices[pending.language])mw.notify(notices[pending.language],{tag:'gd-language-fallback',autoHideSeconds:10}); | |||
} catch(error) {} | |||
function rememberFallback(language) { | |||
try {sessionStorage.setItem('gdwiki-fallback',JSON.stringify({language:language}));} catch(error) {} | |||
} | |||
function normal(title) {title=title.replace(/_/g,' ').trim();return title.charAt(0).toUpperCase()+title.slice(1);} | |||
function bare(title) {return title.replace(/^(?:Spa|Rus|Pol)\//,'');} | |||
function route(title) { | |||
var m=/^(Spa|Rus|Pol)\/(.+)$/.exec(title); | |||
return '/'+(m ? m[1].toLowerCase() : 'eng')+'/'+encodeURIComponent((m ? m[2] : title).replace(/ /g,'_')).replace(/%2F/g,'/'); | |||
} | |||
var api=new mw.Api(); | |||
api.get({action:'query',titles:'MediaWiki:Expanded-language-pages.json',prop:'revisions',rvprop:'content',rvslots:'main',formatversion:2}).then(function (data) { | |||
var map; | |||
try {map=JSON.parse(data.query.pages[0].revisions[0].slots.main.content);} catch(error) {map={};} | |||
var aliases={}; | |||
Object.keys(map).forEach(function (root) { | |||
if(!map[root] || typeof map[root]!=='object')return; | |||
[root].concat(Object.keys(map[root]).map(function (key) {return map[root][key];})).forEach(function (title) { | |||
if(typeof title!=='string')return; | |||
[normal(title),normal(bare(title))].forEach(function (alias) { | |||
if(!aliases[alias])aliases[alias]=[]; | |||
if(aliases[alias].indexOf(root)===-1)aliases[alias].push(root); | |||
}); | |||
}); | |||
}); | |||
function group(title) { | |||
var roots=aliases[normal(title)] || []; | |||
if(roots.length===1)return map[roots[0]]; | |||
if(roots.length>1)return null; // Never guess between unrelated concepts. | |||
var english=bare(normal(title));return {eng:english,spa:'Spa/'+english,rus:'Rus/'+english,pol:'Pol/'+english}; | |||
} | |||
var links=[],checks={},current=(mw.config.get('wgPageName') || '').replace(/_/g,' '); | |||
document.querySelectorAll('#mw-content-text a[href], #mw-panel a[href], .gd-header-bar-logo, .gd-language-home').forEach(function (link) { | |||
var url;try {url=new URL(link.href);}catch(error){return;} | |||
if(url.origin!==location.origin)return; | |||
if(link.getAttribute('href').charAt(0)==='#')return; | |||
var path=/^\/(?:eng|spa|rus|pol|wiki)\/(.+)$/.exec(url.pathname); | |||
if(!path && url.pathname!=='/')return; | |||
var title=path ? decodeURIComponent(path[1]).replace(/_/g,' ') : (mw.config.get('wgMainPageTitle') || 'Main Page'); | |||
if(/^\/(spa|rus|pol)\//.test(url.pathname))title=url.pathname.split('/')[1].charAt(0).toUpperCase()+url.pathname.split('/')[1].slice(1)+'/'+title; | |||
if(title.indexOf(':')!==-1)return; | |||
var action=url.searchParams.get('action'); | |||
var redlink=url.searchParams.get('redlink')==='1'; | |||
if((action && action!=='view' && !redlink) || url.searchParams.has('veaction') || url.searchParams.has('oldid') || url.searchParams.has('diff'))return; | |||
if(normal(title)===normal(current) && url.hash)return; | |||
var versions=group(title);if(!versions)return; | |||
Object.keys(versions).forEach(function (lang) {checks[versions[lang]]=true;}); | |||
links.push({element:link,url:url,title:title,versions:versions}); | |||
}); | |||
var currentVersions=group(current); | |||
if(currentVersions)Object.keys(currentVersions).forEach(function (lang) {checks[currentVersions[lang]]=true;}); | |||
var titles=Object.keys(checks),batches=[]; | |||
for(var i=0;i<titles.length;i+=40)batches.push(titles.slice(i,i+40)); | |||
Promise.all(batches.map(function (batch) {return api.get({action:'query',titles:batch.join('|'),prop:'info',formatversion:2});})).then(function (results) { | |||
var exists={};results.forEach(function (result) {(result.query.pages || []).forEach(function (p) {exists[normal(p.title)]=!p.missing && !p.invalid;});}); | |||
links.forEach(function (item) { | |||
var preferred=item.versions[mode],english=item.versions.eng; | |||
var available=preferred && exists[normal(preferred)]; | |||
var target=available ? preferred : english; | |||
if(!target || !exists[normal(target)])return; | |||
item.url.searchParams.delete('title');item.url.searchParams.delete('uselang');item.url.searchParams.delete('redlink');if(item.url.searchParams.get('action')==='edit')item.url.searchParams.delete('action'); | |||
item.element.href=route(target)+(item.url.searchParams.size ? '?'+item.url.searchParams.toString() : '')+item.url.hash; | |||
item.element.classList.remove('new'); | |||
if(!available && mode!=='eng')item.element.addEventListener('click',function () {rememberFallback(mode);}); | |||
// Prefixes are storage details, not part of the displayed article name. | |||
if(item.element.textContent.trim()===item.title)item.element.textContent=bare(item.title); | |||
}); | |||
if(!currentVersions || mw.config.get('wgNamespaceNumber')!==0 || mw.config.get('wgAction')!=='view')return; | |||
var languages=Object.keys(names).filter(function (lang) {return currentVersions[lang] && exists[normal(currentVersions[lang])];}); | |||
if(languages.length<2 || document.getElementById('gd-article-languages'))return; | |||
var nav=document.createElement('nav');nav.id='gd-article-languages';nav.className='gd-article-languages';nav.setAttribute('aria-label',mode==='spa' ? 'Idiomas del artículo' : 'Article languages'); | |||
languages.forEach(function (lang) { | |||
var link=document.createElement('a');link.textContent=names[lang];link.href=route(currentVersions[lang]);link.setAttribute('data-gd-language-tab',''); | |||
if(normal(currentVersions[lang])===normal(current))link.setAttribute('aria-current','page'); | |||
nav.appendChild(link); | |||
}); | |||
var heading=document.getElementById('firstHeading');if(heading){document.body.classList.add('gd-has-language-tabs');heading.appendChild(nav);} | |||
},function () { /* Preserve original working links if availability cannot be checked. */ }); | |||
}); | |||
}); | |||
}); | |||
}()); | |||
/* Infobox labels: reader language on shared pages, article language on articles. */ | |||
(function () { | |||
'use strict'; | |||
var labels={"Born": {"spa": "Nacimiento", "rus": "Дата рождения", "pol": "Data urodzenia"}, "Died": {"spa": "Fallecimiento", "rus": "Дата смерти", "pol": "Data śmierci"}, "Other names": {"spa": "Otros nombres", "rus": "Другие имена", "pol": "Inne nazwy"}, "Country": {"spa": "País", "rus": "Страна", "pol": "Kraj"}, "Mod status": {"spa": "Estado de moderador", "rus": "Статус модератора", "pol": "Status moderatora"}, "Uploaded levels": {"spa": "Niveles publicados", "rus": "Опубликованные уровни", "pol": "Opublikowane poziomy"}, "Rated levels": {"spa": "Niveles calificados", "rus": "Оценённые уровни", "pol": "Ocenione poziomy"}, "Creator points": {"spa": "Puntos de creador", "rus": "Очки создателя", "pol": "Punkty twórcy"}, "GD stats": {"spa": "Estadísticas de GD", "rus": "Статистика GD", "pol": "Statystyki GD"}, "Social media": {"spa": "Redes sociales", "rus": "Социальные сети", "pol": "Media społecznościowe"}, "Other": {"spa": "Otros", "rus": "Другое", "pol": "Inne"}, "Please search": {"spa": "Buscar", "rus": "Найти", "pol": "Wyszukaj"}, "Information": {"spa": "Información", "rus": "Информация", "pol": "Informacje"}, "Statistics": {"spa": "Estadísticas", "rus": "Статистика", "pol": "Statystyki"}, "Total jumps": {"spa": "Saltos totales", "rus": "Всего прыжков", "pol": "Łączna liczba skoków"}, "Total attempts": {"spa": "Intentos totales", "rus": "Всего попыток", "pol": "Łączna liczba prób"}, "Main levels": {"spa": "Niveles principales", "rus": "Основные уровни", "pol": "Główne poziomy"}, "Online levels": {"spa": "Niveles en línea", "rus": "Онлайн-уровни", "pol": "Poziomy online"}, "Daily levels": {"spa": "Niveles diarios", "rus": "Ежедневные уровни", "pol": "Poziomy dzienne"}, "Gauntlets": {"spa": "Gauntlets", "rus": "Испытания", "pol": "Gauntlety"}, "Map packs": {"spa": "Paquetes de mapas", "rus": "Наборы уровней", "pol": "Pakiety map"}, "Liked / disliked": {"spa": "Me gusta / no me gusta", "rus": "Лайки / дизлайки", "pol": "Polubione / nielubiane"}, "Chests opened": {"spa": "Cofres abiertos", "rus": "Открытые сундуки", "pol": "Otwarte skrzynie"}, "Players destroyed": {"spa": "Jugadores destruidos", "rus": "Уничтоженные игроки", "pol": "Zniszczeni gracze"}, "Leaderboard": {"spa": "Clasificación", "rus": "Таблица лидеров", "pol": "Ranking"}, "Last updated": {"spa": "Última actualización", "rus": "Последнее обновление", "pol": "Ostatnia aktualizacja"}}; | |||
function translate(root) { | |||
var page=mw.config.get('wgPageName') || '',match=/^(Spa|Rus|Pol)\//.exec(page),cookie=/(?:^|;\s*)gdwiki-language=(eng|spa|rus|pol)(?:;|$)/.exec(document.cookie); | |||
var lang=mw.config.get('wgNamespaceNumber')===0 ? (match ? match[1].toLowerCase() : 'eng') : (cookie ? cookie[1] : (mw.config.get('wgExpandedActiveLanguage') || 'eng')); | |||
root.querySelectorAll('[data-gd-infobox-label]').forEach(function (el) {var key=el.getAttribute('data-gd-infobox-label');el.textContent=(labels[key] && labels[key][lang]) || key;}); | |||
root.querySelectorAll('[data-gd-stats-name]').forEach(function(el){var name=el.getAttribute('data-gd-stats-name');el.textContent=lang==='spa' ? 'Estadísticas de '+name : lang==='rus' ? 'Статистика '+name : lang==='pol' ? 'Statystyki '+name : name+"’s stats";}); | |||
} | |||
$(function(){translate(document);mw.hook('wikipage.content').add(function(content){translate(content[0] || document);});}); | |||
})(); | |||
Latest revision as of 21:09, 14 October 2026
/* All JavaScript here will be loaded for users of the Vector skin */
/***************************/
/* Interface Modification **/
/***************************/
/* JavaScript Load Class (REQUIRED BY DEFAULT VECTOR.CSS) */
$(function () {
document.body.classList.add('has-vector-mobile-menu');
});
/* Adapt standard Vector's structure for the imported stylesheet. */
$(function () {
if (!document.body.classList.contains('skin-vector-legacy')) return;
var content = document.getElementById('content');
var navigation = document.getElementById('mw-navigation');
if (!content || !navigation) return;
if (!content.parentElement.classList.contains('content-wrapper')) {
var wrapper = document.createElement('div');
wrapper.className = 'content-wrapper';
content.before(wrapper);
wrapper.append(navigation, content);
}
if (!content.querySelector('.content-body')) {
$(content).wrapInner('<div class="content-body"></div>');
}
});
/* Search Toggle Button */
$(function () {
var buttonClass = 'button-toggle button-toggle-search';
var expandedClass = 'search--expanded';
let searchButton = document.createElement('button');
let sidebar = document.getElementById('mw-navigation');
searchButton.className = buttonClass;
searchButton.addEventListener('click', function () {
searchButton.classList.toggle(expandedClass);
sidebar.classList.toggle(expandedClass);
});
sidebar.prepend(searchButton);
});
/* Mobile Sidebar Toggle Button */
$(function () {
var buttonClass = 'button-toggle button-toggle-sidebar-mobile';
var expandedClass = 'sidebar-mobile--expanded';
let mobileSidebarButton = document.createElement('button');
let sidebar = document.getElementById('mw-navigation');
mobileSidebarButton.className = buttonClass;
mobileSidebarButton.addEventListener('click', function () {
mobileSidebarButton.classList.toggle(expandedClass);
sidebar.classList.toggle(expandedClass);
});
sidebar.prepend(mobileSidebarButton);
});
/* Sidebar Toggle Button */
$(function () {
var buttonClass = 'button-toggle button-toggle-sidebar';
var expandedClass = 'sidebar--collapsed';
let sidebarButton = document.createElement('button');
let sidebar = document.getElementById('mw-navigation');
sidebarButton.className = buttonClass;
sidebarButton.addEventListener('click', function () {
sidebarButton.classList.toggle(expandedClass);
sidebar.classList.toggle(expandedClass);
});
sidebar.prepend(sidebarButton);
});
/* Sidebar Box Content Collaspible Toggles */
$(function() {
// configure sections (by header string) to initially collapse for all users by default
var initiallyCollapsedIDs = []; /* e.g. ['Character_Classes', 'Items', 'External_Links'] */
// add the p- onto ids for ease of use, if not present
initiallyCollapsedIDs.forEach(function(id, index) {
if(!id.startsWith('p-')) {initiallyCollapsedIDs[index] = 'p-' + id;}
});
var $portals = $("#mw-panel .vector-menu-portal");
var setup = function() {
$portals.each(function(index, el) {
if(window.innerWidth < 721) {return;}
var $el = $(el);
var $id = $el.attr("id");
if(!$id) {return;}
// check if this portal should be collapsed - portal is set to be initially collapsed and user has not indicated wanting it open || user has indicated wanting this portal collapsed
if(
(initiallyCollapsedIDs.includes($id) && localStorage.getItem('sidebar_c_'+$id) != "n") || (localStorage.getItem('sidebar_c_'+$id) === "y")
) {$el.addClass('collapsed').find('.vector-menu-content').slideUp(0);}
});
};
setup();
$(window).on('resize', setup);
$portals.on("click", "h3", function(event) {
if(window.innerWidth < 721) {return;}
var $el = $(this).parent();
var $id = $el.attr("id");
if(!$id) {return;}
$el.toggleClass('collapsed');
if($el.hasClass('collapsed')) { // more consistent between class and slide status
localStorage.setItem('sidebar_c_'+$id, "y");
$el.find('.vector-menu-content').slideUp('fast');
}
else {
localStorage.setItem('sidebar_c_'+$id, "n");
$el.find('.vector-menu-content').slideDown('fast');
}
});
});
/* Header Dropdown Menu Purge Cache Link */
$(function() {
if (mw.config.get('wgNamespaceNumber') === -1 ) {return;} // disable on special pages
var url = new URL(window.location.href);
url.searchParams.set('action', 'purge');
var button = mw.util.addPortletLink('p-cactions', url.href, 'Purge cache', 'ca-gadget-purgecache', 'Purge the server cache for this page', '1');
button.addEventListener('click', (function(event) {
event.preventDefault();
var api = new mw.Api();
api.post({
action: 'purge',
titles: mw.config.get('wgPageName'),
forcerecursivelinkupdate: true
}).then(function() {
window.location.reload(true);
}).fail(function(code) {
mw.notify('Page purge unsuccessful. Error code: $1'.replace('$1', code));
});
}));
console.log('purge loaded');
});
/* Independent GD Wiki header: themes and existing account links. */
(function () {
'use strict';
var themes = [
['blue', 'Geometry Dash'], ['green', 'Vault'],
['purple', 'Vault of Secrets'], ['red', 'Chamber of Time'],
['dark', 'Dark'], ['blackout', 'Blackout']
];
var storageKey = 'gdwiki-theme';
function applyTheme(key) {
if (!themes.some(function (theme) { return theme[0] === key; })) key = 'blue';
var root = document.documentElement;
themes.forEach(function (theme) { root.classList.remove('theme-' + theme[0]); });
root.classList.remove('view-light');
root.classList.add('view-dark', 'theme-' + key);
return key;
}
var selected = 'blue';
try { selected = localStorage.getItem(storageKey) || selected; } catch (error) {}
selected = applyTheme(selected);
$(function () {
if (!document.body.classList.contains('skin-vector-legacy')) return;
var personal = document.getElementById('p-personal');
if (!personal || personal.querySelector('.gd-header-controls')) return;
var links = personal.querySelector('ul');
if (!links) return;
var controls = document.createElement('div');
controls.className = 'gd-header-controls';
var appearance = document.createElement('details');
appearance.className = 'gd-header-menu';
var appearanceLabel = document.createElement('summary');
appearanceLabel.textContent = 'Appearance';
appearance.appendChild(appearanceLabel);
var themePanel = document.createElement('div');
themePanel.className = 'gd-header-dropdown';
themePanel.setAttribute('role', 'group');
themePanel.setAttribute('aria-label', 'Theme');
themes.forEach(function (theme) {
var button = document.createElement('button');
button.type = 'button';
button.className = 'gd-theme-option';
button.textContent = theme[1];
button.setAttribute('aria-pressed', String(theme[0] === selected));
button.addEventListener('click', function () {
selected = applyTheme(theme[0]);
try { localStorage.setItem(storageKey, selected); } catch (error) {}
themePanel.querySelectorAll('button').forEach(function (item) {
item.setAttribute('aria-pressed', String(item === button));
});
appearance.open = false;
});
themePanel.appendChild(button);
});
appearance.appendChild(themePanel);
controls.appendChild(appearance);
var icons = {
gear: '<path d="m10 2 .5 2a8 8 0 0 1 3 0l.5-2 3 1 0 2a8 8 0 0 1 2 2l2 0 1 3-2 .5a8 8 0 0 1 0 3l2 .5-1 3-2 0a8 8 0 0 1-2 2l0 2-3 1-.5-2a8 8 0 0 1-3 0L10 22l-3-1 0-2a8 8 0 0 1-2-2l-2 0-1-3 2-.5a8 8 0 0 1 0-3L2 10l1-3 2 0a8 8 0 0 1 2-2l0-2z"/><circle cx="12" cy="12" r="3" fill="#03052f"/>',
watch: '<path d="M3 3h18v15h-6l-2 3h-2l-2-3H3zm2 2v11h5l2 3 2-3h5V5z"/>',
user: '<circle cx="12" cy="7" r="4"/><path d="M3 22v-2a9 9 0 0 1 18 0v2z"/>'
};
function iconMarkup(name) {
return '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">' + icons[name] + '</svg>';
}
function iconLink(id, name, label) {
var original = document.querySelector('#' + id + ' a');
if (!original) return;
var link = original.cloneNode(false);
link.className = 'gd-header-icon';
link.title = label;
link.setAttribute('aria-label', label);
link.innerHTML = iconMarkup(name);
controls.appendChild(link);
}
iconLink('pt-preferences', 'gear', 'Preferences');
// Use Echo's actual widgets so alerts and notices retain their behavior.
['pt-notifications-alert', 'pt-notifications-notice'].forEach(function (id) {
var notification = document.getElementById(id);
if (notification) {
notification.classList.add('gd-header-notification');
controls.appendChild(notification);
}
});
var account = document.createElement('details');
account.className = 'gd-header-menu gd-account-menu';
var accountLabel = document.createElement('summary');
accountLabel.setAttribute('aria-label', 'Account menu');
accountLabel.title = 'Account menu';
var accountGroup = document.createElement('div');
accountGroup.className = 'gd-account-group';
var accountName = document.createElement('a');
accountName.className = 'gd-account-talk-link';
var userName = mw.config.get('wgUserName');
accountName.href = mw.util.getUrl(userName ? 'User:' + userName : 'Special:UserLogin');
accountName.innerHTML = iconMarkup('user');
var nameText = document.createElement('span');
nameText.textContent = userName || 'Account';
accountName.appendChild(nameText);
accountName.title = userName ? 'Your user page' : 'Log in';
accountGroup.appendChild(accountName);
account.appendChild(accountLabel);
var duplicateUserPage = links.querySelector('#pt-userpage');
if (duplicateUserPage) duplicateUserPage.remove();
links.classList.add('gd-account-links');
account.appendChild(links);
accountGroup.appendChild(account);
controls.appendChild(accountGroup);
var barLogo = document.createElement('a');
barLogo.className = 'gd-header-bar-logo';
barLogo.href = mw.util.getUrl(mw.config.get('wgMainPageTitle') || 'Main Page');
barLogo.title = mw.config.get('wgSiteName') || 'Geometry Dash Expanded Wiki';
barLogo.setAttribute('aria-label', barLogo.title + ' main page');
var logoImage = document.createElement('img');
logoImage.src = 'https://geometrydashwiki.com/images/d/d4/Logo.jpg';
logoImage.alt = ''; logoImage.width = 32; logoImage.height = 32;
barLogo.appendChild(logoImage);
personal.appendChild(barLogo);
personal.appendChild(controls);
personal.classList.add('gd-header-ready');
document.addEventListener('click', function (event) {
[appearance, account].forEach(function (menu) {
if (!menu.contains(event.target)) menu.open = false;
});
});
document.addEventListener('keydown', function (event) {
if (event.key === 'Escape') { appearance.open = false; account.open = false; }
});
});
}());
/* Expanded multilingual navigation: shared accounts, files and Recent Changes. */
(function () {
'use strict';
mw.loader.using(['mediawiki.api', 'mediawiki.util']).then(function () {
$(function () {
var controls = document.querySelector('.gd-header-controls');
if (!controls || document.getElementById('gd-language-menu')) return;
var page = (mw.config.get('wgPageName') || 'Main_Page').replace(/_/g, ' ');
var match = /^(Spa|Rus|Pol)\/(.+)$/.exec(page);
var pathCode = /^\/(eng|spa|rus|pol)(?:\/|$)/.exec(location.pathname);
var articleCode = match ? match[1].toLowerCase() : 'eng';
var cookie = /(?:^|;\s*)gdwiki-language=(eng|spa|rus|pol)(?:;|$)/.exec(document.cookie);
var code = cookie ? cookie[1] : (mw.config.get('wgExpandedActiveLanguage') || (pathCode ? pathCode[1] : articleCode));
var base = match ? match[2] : page;
var spanish = code === 'spa';
var isArticle = mw.config.get('wgNamespaceNumber') === 0;
document.documentElement.setAttribute('data-gd-language', code);
var definitions = [
{code:'eng', name:'English', lang:'en', flag:'/images/4/49/Flag_gb.svg'},
{code:'spa', name:'Español', lang:'es', flag:'/images/2/2d/Flag_es.svg'}
];
var menu = document.createElement('details');
menu.id = 'gd-language-menu'; menu.className = 'gd-header-menu gd-language-menu';
var summary = document.createElement('summary');
summary.setAttribute('aria-label', spanish ? 'Cambiar idioma' : 'Change language');
summary.title = summary.getAttribute('aria-label');
var current = definitions[spanish ? 1 : 0];
var image = document.createElement('img'); image.src=current.flag; image.alt=''; image.width=24; image.height=16;
summary.appendChild(image);
var label=document.createElement('span'); label.textContent=current.name; summary.appendChild(label);
menu.appendChild(summary);
var panel=document.createElement('div'); panel.className='gd-header-dropdown gd-language-options';
panel.setAttribute('aria-label', spanish ? 'Idiomas' : 'Languages');
menu.appendChild(panel);
var personal = document.getElementById('p-personal');
personal.appendChild(menu);
var api=new mw.Api();
function route(title, lang) {
if (!mw.config.get('wgExpandedLanguageRoutes')) return mw.util.getUrl(title);
var m=/^(Spa|Rus|Pol)\/(.+)$/.exec(title);
var language=m ? m[1].toLowerCase() : 'eng';
var name=m ? m[2] : title;
if (name.indexOf(':')!==-1 && !m) return mw.util.getUrl(title);
return '/'+language+'/'+encodeURIComponent(name.replace(/ /g,'_')).replace(/%2F/g,'/');
}
function build(mapping) {
var entry=mapping[base] || {};
Object.keys(mapping).some(function (key) {
if (mapping[key][articleCode]===page) {base=key;entry=mapping[key];return true;}
return false;
});
var titles=definitions.map(function (d) {
return isArticle ? (entry[d.code] || (d.code==='eng' ? base : 'Spa/'+base)) : page;
});
api.get({action:'query',titles:titles.join('|'),prop:'info',formatversion:2}).then(function (data) {
var existing={};
(data.query.pages || []).forEach(function (p) {existing[p.title]=!p.missing && !p.invalid;});
definitions.forEach(function (d,i) {
var available=existing[titles[i]], target=available || !isArticle ? titles[i] : titles[0];
var link=document.createElement('a');link.lang=d.lang;link.hreflang=d.lang;
var flag=document.createElement('img');flag.src=d.flag;flag.alt='';flag.width=24;flag.height=16;link.appendChild(flag);
var text=document.createElement('span');text.textContent=d.name;link.appendChild(text);
if(d.code===code)link.setAttribute('aria-current','page');
link.href=route(target,d.lang);
link.addEventListener('click',function () {
document.cookie='gdwiki-language='+d.code+'; Path=/; Max-Age=31536000; SameSite=Lax; Secure';
try {
localStorage.setItem('gdwiki-language',d.code);
if(isArticle && !available)sessionStorage.setItem('gdwiki-fallback',JSON.stringify({language:d.code,page:base}));
} catch(error) {}
});
panel.appendChild(link);
});
if(isArticle && !existing[titles[1]]) {
var create=document.createElement('a');create.className='gd-language-create';
create.textContent=spanish ? 'Crear traducción al español' : 'Create Spanish translation';
if(mw.config.get('wgExpandedLanguageEditorSafe')) {
var editParams={action:'edit',preload:titles[0],summary:'Start Español translation from [['+titles[0]+']]'};
create.href=route(titles[1],'es')+'?'+new URLSearchParams(editParams).toString();
} else {create.setAttribute('aria-disabled','true');create.title='Translation setup awaiting server update';}
panel.appendChild(create);
}
var home=document.createElement('a');home.className='gd-language-home';home.textContent=spanish ? 'Inicio' : 'Home';home.href=route('Main Page','en');panel.appendChild(home);
var guide=document.createElement('a');guide.textContent=spanish ? 'Guía de traducción' : 'Translation guide';guide.href=mw.util.getUrl('Help:Translations');panel.appendChild(guide);
}, function () {panel.textContent=spanish ? 'No se pudieron cargar los idiomas. Recarga la página.' : 'Languages could not load. Reload the page.';});
}
api.get({action:'query',titles:'MediaWiki:Expanded-language-pages.json',prop:'revisions',rvprop:'content',rvslots:'main',formatversion:2}).then(function (data) {
try {build(JSON.parse(data.query.pages[0].revisions[0].slots.main.content));} catch (error) {build({});}
},function () {build({});});
document.addEventListener('click',function (event) {if (!menu.contains(event.target)) menu.open=false;});
document.addEventListener('keydown',function (event) {if (event.key==='Escape') menu.open=false;});
if (spanish) {
var interfaceLabels={"Navigation": "Navegación", "Main page": "Página principal", "Recent changes": "Cambios recientes", "New files": "Archivos nuevos", "Random page": "Página aleatoria", "New here? Get started": "¿Eres nuevo? Empieza aquí", ">> Site policy": ">> Normas del sitio", ">> Staff": ">> Administración", "Help using MediaWiki": "Ayuda sobre MediaWiki", "GD Base Content": "Contenido base de GD", "Games": "Juegos", "Main levels": "Niveles principales", "Gameplay": "Jugabilidad", "Rewards": "Recompensas", "Rooms (vaults etc.)": "Salas (bóvedas, etc.)", "Level editing": "Editor de niveles", "Account features": "Funciones de la cuenta", "Updates": "Actualizaciones", "GD Community Content": "Contenido de la comunidad de GD", "Demon List levels": "Niveles de la Demon List", "Gauntlet levels": "Niveles de gauntlets", "Map Pack levels": "Niveles de paquetes de mapas", "Classic levels": "Niveles clásicos", "Platformer levels": "Niveles de plataformas", "Players": "Jugadores", "Community activities": "Actividades de la comunidad", "Wiki Resources": "Recursos de la wiki", "Propose new articles": "Proponer artículos nuevos", "Submit edits for review": "Enviar cambios para revisión", "Admin Dashboard": "Panel de administración", "Images": "Imágenes", "Videos": "Vídeos", "Audio": "Audio", "PDFs": "PDF", "Templates": "Plantillas", "Sandbox": "Zona de pruebas", "Discuss the wiki": "Debatir sobre la wiki", "Guestbook": "Libro de visitas", "Tools": "Herramientas", "What links here": "Lo que enlaza aquí", "Related changes": "Cambios relacionados", "Upload file": "Subir archivo", "Printable version": "Versión para imprimir", "Permanent link": "Enlace permanente", "Page information": "Información de la página", "Account": "Cuenta", "Preferences": "Preferencias", "Your user page": "Tu página de usuario", "Log in": "Iniciar sesión", "Account menu": "Menú de cuenta", "Appearance": "Apariencia"};
document.querySelectorAll('#mw-panel h3, #mw-panel h3 span, #mw-panel a, .gd-account-links a, .gd-account-talk-link span').forEach(function (element) {
var key=element.textContent.trim();
if (interfaceLabels[key]) {
// Translate text nodes without removing colour spans, links or icons.
var walker=document.createTreeWalker(element,NodeFilter.SHOW_TEXT), node;
while ((node=walker.nextNode())) {
var original=node.nodeValue.trim();
if (interfaceLabels[original]) node.nodeValue=node.nodeValue.replace(original,interfaceLabels[original]);
}
}
});
document.querySelectorAll('#p-personal [title], #p-personal [aria-label]').forEach(function (element) {
['title','aria-label'].forEach(function (attr) {var key=element.getAttribute(attr);if(interfaceLabels[key])element.setAttribute(attr,interfaceLabels[key]);});
});
var appearance=controls.querySelector('.gd-header-menu summary');
if (appearance) {appearance.textContent='Apariencia';appearance.title='Apariencia';appearance.setAttribute('aria-label','Apariencia');}
var account=controls.querySelector('.gd-account-menu summary');
if (account) {account.title='Menú de cuenta';account.setAttribute('aria-label','Menú de cuenta');}
var titles={'Blue':'Azul','Purple':'Morado','Green':'Verde','Red':'Rojo','Dark':'Oscuro','Blackout':'Negro','Vault':'La bóveda','Vault of Secrets':'La bóveda de los secretos','Chamber of Time':'La cámara del tiempo'};
controls.querySelectorAll('.gd-theme-option').forEach(function (button) {if(titles[button.textContent])button.textContent=titles[button.textContent];});
}
// Optional translated assets use the same existing theme filters.
var logos=mw.config.get('wgExpandedLanguageLogos') || {};
logos.spa=Object.assign({"header": "https://geometrydashwiki.com/images/4/4a/Logo-spa.jpg", "banner": "https://geometrydashwiki.com/images/a/a7/Site-logo-spa.png"},logos.spa || {});
if (logos[code]) {
if (logos[code].header) {
var header=document.querySelector('.gd-header-bar-logo img');if(header)header.src=logos[code].header;
}
if (logos[code].banner) document.documentElement.style.setProperty('--wiki-logo-image','url("'+logos[code].banner.replace(/["\\]/g,'')+'")');
}
});
});
}());
/* Keep language parameters and script endpoints out of visible navigation URLs. */
(function () {
'use strict';
function clean(raw) {
var url;
try {url=new URL(raw,location.href);} catch(error) {return raw;}
if (url.origin!==location.origin) return raw;
url.searchParams.delete('uselang');
if (/\/index\.php$/.test(url.pathname) && !url.searchParams.has('title') && url.searchParams.has('search')) {url.pathname='/wiki/Special:Search';}
if (/\/index\.php$/.test(url.pathname) && url.searchParams.has('title')) {
var title=url.searchParams.get('title');url.searchParams.delete('title');
var match=/^(Spa|Rus|Pol)\/(.+)$/.exec(title.replace(/_/g,' '));
var ns=title.indexOf(':')!==-1;
var prefix=match ? '/'+match[1].toLowerCase()+'/' : (ns ? '/wiki/' : '/eng/');
var name=match ? match[2] : title;
url.pathname=prefix+encodeURIComponent(name.replace(/ /g,'_')).replace(/%2F/g,'/').replace(/%3A/g,':');
}
return url.pathname+url.search+url.hash;
}
// The current request has already chosen its interface language.
var address=new URL(location.href);
var cleanAddress=clean(location.href);
if (cleanAddress!==address.pathname+address.search+address.hash) history.replaceState(null,'',cleanAddress);
function links() {
document.querySelectorAll('a[href]').forEach(function (link) {
var href=link.getAttribute('href');
if (href && !/^(?:#|javascript:|mailto:)/.test(href)) {
var replacement=clean(href);if(replacement!==href)link.setAttribute('href',replacement);
}
});
}
$(function () {
links();
var pending=false;
new MutationObserver(function () {
if(pending)return;pending=true;
requestAnimationFrame(function () {pending=false;links();});
}).observe(document.body,{childList:true,subtree:true});
});
mw.hook('wikipage.content').add(links);
// Also handles asynchronously built language and account menus.
document.addEventListener('click',function(event) {
var link=event.target.closest && event.target.closest('a[href]');
if(link)link.setAttribute('href',clean(link.getAttribute('href')));
},true);
}());
/* Article-language tabs and links follow the persistent site language. */
(function () {
'use strict';
mw.loader.using(['mediawiki.api','mediawiki.util']).then(function () {
$(function () {
var cookie=/(?:^|;\s*)gdwiki-language=(eng|spa|rus|pol)(?:;|$)/.exec(document.cookie);
var mode=cookie ? cookie[1] : (mw.config.get('wgExpandedActiveLanguage') || mw.config.get('wgExpandedLanguage') || 'eng');
var names={eng:'English',spa:'Español',rus:'Русский',pol:'Polski'};
var notices={eng:'This article is not available in English. Showing the original article.',spa:'Este artículo todavía no está disponible en español. Se muestra la versión en inglés.',rus:'Эта статья пока недоступна на русском языке. Показана английская версия.',pol:'Ten artykuł nie jest jeszcze dostępny po polsku. Wyświetlono wersję angielską.'};
try {
var pending=JSON.parse(sessionStorage.getItem('gdwiki-fallback') || 'null');
sessionStorage.removeItem('gdwiki-fallback');
if(!pending && mw.config.get('wgExpandedLanguageFallback'))pending={language:mw.config.get('wgExpandedLanguageFallback')};
if(pending && notices[pending.language])mw.notify(notices[pending.language],{tag:'gd-language-fallback',autoHideSeconds:10});
} catch(error) {}
function rememberFallback(language) {
try {sessionStorage.setItem('gdwiki-fallback',JSON.stringify({language:language}));} catch(error) {}
}
function normal(title) {title=title.replace(/_/g,' ').trim();return title.charAt(0).toUpperCase()+title.slice(1);}
function bare(title) {return title.replace(/^(?:Spa|Rus|Pol)\//,'');}
function route(title) {
var m=/^(Spa|Rus|Pol)\/(.+)$/.exec(title);
return '/'+(m ? m[1].toLowerCase() : 'eng')+'/'+encodeURIComponent((m ? m[2] : title).replace(/ /g,'_')).replace(/%2F/g,'/');
}
var api=new mw.Api();
api.get({action:'query',titles:'MediaWiki:Expanded-language-pages.json',prop:'revisions',rvprop:'content',rvslots:'main',formatversion:2}).then(function (data) {
var map;
try {map=JSON.parse(data.query.pages[0].revisions[0].slots.main.content);} catch(error) {map={};}
var aliases={};
Object.keys(map).forEach(function (root) {
if(!map[root] || typeof map[root]!=='object')return;
[root].concat(Object.keys(map[root]).map(function (key) {return map[root][key];})).forEach(function (title) {
if(typeof title!=='string')return;
[normal(title),normal(bare(title))].forEach(function (alias) {
if(!aliases[alias])aliases[alias]=[];
if(aliases[alias].indexOf(root)===-1)aliases[alias].push(root);
});
});
});
function group(title) {
var roots=aliases[normal(title)] || [];
if(roots.length===1)return map[roots[0]];
if(roots.length>1)return null; // Never guess between unrelated concepts.
var english=bare(normal(title));return {eng:english,spa:'Spa/'+english,rus:'Rus/'+english,pol:'Pol/'+english};
}
var links=[],checks={},current=(mw.config.get('wgPageName') || '').replace(/_/g,' ');
document.querySelectorAll('#mw-content-text a[href], #mw-panel a[href], .gd-header-bar-logo, .gd-language-home').forEach(function (link) {
var url;try {url=new URL(link.href);}catch(error){return;}
if(url.origin!==location.origin)return;
if(link.getAttribute('href').charAt(0)==='#')return;
var path=/^\/(?:eng|spa|rus|pol|wiki)\/(.+)$/.exec(url.pathname);
if(!path && url.pathname!=='/')return;
var title=path ? decodeURIComponent(path[1]).replace(/_/g,' ') : (mw.config.get('wgMainPageTitle') || 'Main Page');
if(/^\/(spa|rus|pol)\//.test(url.pathname))title=url.pathname.split('/')[1].charAt(0).toUpperCase()+url.pathname.split('/')[1].slice(1)+'/'+title;
if(title.indexOf(':')!==-1)return;
var action=url.searchParams.get('action');
var redlink=url.searchParams.get('redlink')==='1';
if((action && action!=='view' && !redlink) || url.searchParams.has('veaction') || url.searchParams.has('oldid') || url.searchParams.has('diff'))return;
if(normal(title)===normal(current) && url.hash)return;
var versions=group(title);if(!versions)return;
Object.keys(versions).forEach(function (lang) {checks[versions[lang]]=true;});
links.push({element:link,url:url,title:title,versions:versions});
});
var currentVersions=group(current);
if(currentVersions)Object.keys(currentVersions).forEach(function (lang) {checks[currentVersions[lang]]=true;});
var titles=Object.keys(checks),batches=[];
for(var i=0;i<titles.length;i+=40)batches.push(titles.slice(i,i+40));
Promise.all(batches.map(function (batch) {return api.get({action:'query',titles:batch.join('|'),prop:'info',formatversion:2});})).then(function (results) {
var exists={};results.forEach(function (result) {(result.query.pages || []).forEach(function (p) {exists[normal(p.title)]=!p.missing && !p.invalid;});});
links.forEach(function (item) {
var preferred=item.versions[mode],english=item.versions.eng;
var available=preferred && exists[normal(preferred)];
var target=available ? preferred : english;
if(!target || !exists[normal(target)])return;
item.url.searchParams.delete('title');item.url.searchParams.delete('uselang');item.url.searchParams.delete('redlink');if(item.url.searchParams.get('action')==='edit')item.url.searchParams.delete('action');
item.element.href=route(target)+(item.url.searchParams.size ? '?'+item.url.searchParams.toString() : '')+item.url.hash;
item.element.classList.remove('new');
if(!available && mode!=='eng')item.element.addEventListener('click',function () {rememberFallback(mode);});
// Prefixes are storage details, not part of the displayed article name.
if(item.element.textContent.trim()===item.title)item.element.textContent=bare(item.title);
});
if(!currentVersions || mw.config.get('wgNamespaceNumber')!==0 || mw.config.get('wgAction')!=='view')return;
var languages=Object.keys(names).filter(function (lang) {return currentVersions[lang] && exists[normal(currentVersions[lang])];});
if(languages.length<2 || document.getElementById('gd-article-languages'))return;
var nav=document.createElement('nav');nav.id='gd-article-languages';nav.className='gd-article-languages';nav.setAttribute('aria-label',mode==='spa' ? 'Idiomas del artículo' : 'Article languages');
languages.forEach(function (lang) {
var link=document.createElement('a');link.textContent=names[lang];link.href=route(currentVersions[lang]);link.setAttribute('data-gd-language-tab','');
if(normal(currentVersions[lang])===normal(current))link.setAttribute('aria-current','page');
nav.appendChild(link);
});
var heading=document.getElementById('firstHeading');if(heading){document.body.classList.add('gd-has-language-tabs');heading.appendChild(nav);}
},function () { /* Preserve original working links if availability cannot be checked. */ });
});
});
});
}());
/* Infobox labels: reader language on shared pages, article language on articles. */
(function () {
'use strict';
var labels={"Born": {"spa": "Nacimiento", "rus": "Дата рождения", "pol": "Data urodzenia"}, "Died": {"spa": "Fallecimiento", "rus": "Дата смерти", "pol": "Data śmierci"}, "Other names": {"spa": "Otros nombres", "rus": "Другие имена", "pol": "Inne nazwy"}, "Country": {"spa": "País", "rus": "Страна", "pol": "Kraj"}, "Mod status": {"spa": "Estado de moderador", "rus": "Статус модератора", "pol": "Status moderatora"}, "Uploaded levels": {"spa": "Niveles publicados", "rus": "Опубликованные уровни", "pol": "Opublikowane poziomy"}, "Rated levels": {"spa": "Niveles calificados", "rus": "Оценённые уровни", "pol": "Ocenione poziomy"}, "Creator points": {"spa": "Puntos de creador", "rus": "Очки создателя", "pol": "Punkty twórcy"}, "GD stats": {"spa": "Estadísticas de GD", "rus": "Статистика GD", "pol": "Statystyki GD"}, "Social media": {"spa": "Redes sociales", "rus": "Социальные сети", "pol": "Media społecznościowe"}, "Other": {"spa": "Otros", "rus": "Другое", "pol": "Inne"}, "Please search": {"spa": "Buscar", "rus": "Найти", "pol": "Wyszukaj"}, "Information": {"spa": "Información", "rus": "Информация", "pol": "Informacje"}, "Statistics": {"spa": "Estadísticas", "rus": "Статистика", "pol": "Statystyki"}, "Total jumps": {"spa": "Saltos totales", "rus": "Всего прыжков", "pol": "Łączna liczba skoków"}, "Total attempts": {"spa": "Intentos totales", "rus": "Всего попыток", "pol": "Łączna liczba prób"}, "Main levels": {"spa": "Niveles principales", "rus": "Основные уровни", "pol": "Główne poziomy"}, "Online levels": {"spa": "Niveles en línea", "rus": "Онлайн-уровни", "pol": "Poziomy online"}, "Daily levels": {"spa": "Niveles diarios", "rus": "Ежедневные уровни", "pol": "Poziomy dzienne"}, "Gauntlets": {"spa": "Gauntlets", "rus": "Испытания", "pol": "Gauntlety"}, "Map packs": {"spa": "Paquetes de mapas", "rus": "Наборы уровней", "pol": "Pakiety map"}, "Liked / disliked": {"spa": "Me gusta / no me gusta", "rus": "Лайки / дизлайки", "pol": "Polubione / nielubiane"}, "Chests opened": {"spa": "Cofres abiertos", "rus": "Открытые сундуки", "pol": "Otwarte skrzynie"}, "Players destroyed": {"spa": "Jugadores destruidos", "rus": "Уничтоженные игроки", "pol": "Zniszczeni gracze"}, "Leaderboard": {"spa": "Clasificación", "rus": "Таблица лидеров", "pol": "Ranking"}, "Last updated": {"spa": "Última actualización", "rus": "Последнее обновление", "pol": "Ostatnia aktualizacja"}};
function translate(root) {
var page=mw.config.get('wgPageName') || '',match=/^(Spa|Rus|Pol)\//.exec(page),cookie=/(?:^|;\s*)gdwiki-language=(eng|spa|rus|pol)(?:;|$)/.exec(document.cookie);
var lang=mw.config.get('wgNamespaceNumber')===0 ? (match ? match[1].toLowerCase() : 'eng') : (cookie ? cookie[1] : (mw.config.get('wgExpandedActiveLanguage') || 'eng'));
root.querySelectorAll('[data-gd-infobox-label]').forEach(function (el) {var key=el.getAttribute('data-gd-infobox-label');el.textContent=(labels[key] && labels[key][lang]) || key;});
root.querySelectorAll('[data-gd-stats-name]').forEach(function(el){var name=el.getAttribute('data-gd-stats-name');el.textContent=lang==='spa' ? 'Estadísticas de '+name : lang==='rus' ? 'Статистика '+name : lang==='pol' ? 'Statystyki '+name : name+"’s stats";});
}
$(function(){translate(document);mw.hook('wikipage.content').add(function(content){translate(content[0] || document);});});
})();