// Inject a language toggle button into the topbar (sphinx-book-theme compatible)
(function(){
const STORAGE_KEY = 'slime-doc-lang';
// Default language EN has no URL prefix; Chinese uses '/zh/' inserted after optional repo root.
function detectCurrent(){
const { zhIndex } = analyzePath();
return zhIndex !== -1 ? 'zh' : 'en';
}
function otherLang(lang){ return lang === 'zh' ? 'en' : 'zh'; }
/**
* Analyze current pathname to figure out repo root + language segment pattern.
* Supports patterns:
* /en/… (language as first segment)
* /slime/en/… (GitHub Pages project site repo root, language second)
* /slime/ (no lang yet) -> insert /slime/zh/
* / (no lang) -> insert /zh/
*/
function analyzePath(){
const rawParts = window.location.pathname.split('/').filter(Boolean);
const parts = rawParts.slice();
let repoRoot = null;
if(parts.length > 0 && (window.location.host.endsWith('github.io') || parts[0] === 'slime')){
repoRoot = parts[0];
}
let zhIndex = -1;
if(parts[0] === 'zh') zhIndex = 0; else if(parts[1] === 'zh') zhIndex = 1;
return { parts, repoRoot, zhIndex };
}
function buildTargetUrl(target){
const url = new URL(window.location.href);
const trailingSlash = url.pathname.endsWith('/') || url.pathname === '/';
const { parts, repoRoot, zhIndex } = analyzePath();
if(target === 'zh'){
if(zhIndex === -1){
if(repoRoot){
if(parts.length === 1) parts.push('zh'); else parts.splice(1,0,'zh');
} else {
parts.unshift('zh');
}
}
} else { // target en => remove zh if present
if(zhIndex !== -1) parts.splice(zhIndex,1);
}
let newPath = '/' + parts.join('/');
if(newPath === '/') {
// stay root
} else if(trailingSlash && !/\.[a-zA-Z0-9]+$/.test(parts[parts.length-1] || '')) newPath += '/';
url.pathname = newPath;
return url.toString();
}
function createButton(){
const current = detectCurrent();
const tgt = otherLang(current);
const btn = document.createElement('button');
btn.className = 'btn btn-sm lang-toggle-btn';
btn.type = 'button';
btn.setAttribute('data-current', current);
btn.title = current === 'en' ? '切换到中文 (当前 EN)' : 'Switch to English (当前 中文)';
// Show two labels with active highlighted via CSS
btn.innerHTML = `
EN
/
中
`;
btn.addEventListener('click', ()=>{
const targetUrl = buildTargetUrl(tgt);
try{ localStorage.setItem(STORAGE_KEY, tgt);}catch(e){}
window.location.href = targetUrl;
});
return btn;
}
function findContainer(){
// Priority: sidebar end area or header button groups
return document.querySelector(
'.article-header-buttons, .header-article-items__end, .sidebar-header-items, .sidebar-primary-items__end, .bd-header, .bd-sidebar'
);
}
function idealContainer(){
return document.querySelector('.article-header-buttons');
}
function insert(attempt=0){
// Prefer final header buttons group
let c = idealContainer();
if(!c) c = findContainer();
if(!c){
if(attempt < 40) return setTimeout(()=>insert(attempt+1), 125);
return;
}
// If button exists elsewhere but not inside ideal container, move it
const existing = document.querySelector('.lang-toggle-btn');
if(existing && c !== existing.parentElement){
c.appendChild(existing);
return;
}
if(existing) return; // already good
const btn = createButton();
// Insert near theme switch button if present
const themeBtn = c.querySelector('.theme-switch-button');
// Insert just before theme switch if found, else at end
if(themeBtn){
const parent = themeBtn.parentElement;
if(parent === c) c.insertBefore(btn, themeBtn);
else c.appendChild(btn);
} else c.appendChild(btn);
// If current is zh ensure active highlighting reflects zh
btn.setAttribute('data-current', detectCurrent());
}
document.addEventListener('DOMContentLoaded', ()=>{
insert();
// Observe for dynamic header injection
const obs = new MutationObserver(()=>{ insert(); });
obs.observe(document.body, {childList:true, subtree:true});
// Stop observing after 5s
setTimeout(()=>obs.disconnect(), 5000);
});
})();
// Minimal styling; can be overridden in custom css
// Light structural styling now moved to CSS file; keep minimal runtime if CSS missing.
(function(){
if(document.querySelector('style[data-lang-toggle-style]')) return;
const style = document.createElement('style');
style.setAttribute('data-lang-toggle-style','');
style.textContent = `.lang-toggle-btn{display:inline-flex;align-items:center;gap:2px}`;
document.head.appendChild(style);
})();