Mudanças entre as edições de "Widget:C.Translator"
Ir para navegação
Ir para pesquisar
m |
m |
||
| Linha 1: | Linha 1: | ||
<!-- CHARACTER TRANSLATOR SYSTEM --> | <!-- CHARACTER TRANSLATOR SYSTEM --> | ||
<script> | <script> | ||
(() => { | |||
let __langReqSeq = 0; | |||
// ---------- helpers ---------- | |||
const normalizeLang = (s) => { | |||
s = (s || "").toLowerCase(); | |||
if (s === "pt-br" || s === "pt_br" || s === "ptbr") return "pt"; | |||
return s.split("-")[0] || "pt"; | |||
}; | |||
const markActive = (langFull) => { | |||
const lang = (langFull || "pt-br").toLowerCase(); | |||
document.querySelectorAll(".char-flag[data-lang]").forEach((b) => { | |||
b.classList.toggle("active", b.dataset.lang === lang); | |||
}); | |||
}; | }; | ||
const updateSkillsTabLabel = (norm) => { | |||
const map = { | |||
en: "Skills", | |||
pt: "Habilidades", | |||
es: "Habilidades", | |||
pl: "Umiejętności", | |||
}; | |||
const btn = | |||
document.querySelector('.character-tabs .tab-btn[data-tab="skills"]') || | |||
Array.from(document.querySelectorAll(".character-tabs .tab-btn")).find( | |||
(b) => /skill|habil|umiej/i.test(b.textContent || "") | |||
); | |||
if (btn) btn.textContent = map[norm] || map.pt; | |||
}; | |||
// ---------- skills ---------- | |||
const pickDescFor = (icon, norm) => { | |||
const keyMap = { pt: "descPt", en: "descEn", es: "descEs", pl: "descPl" }; | |||
const order = [ | |||
keyMap[norm], | |||
"descPt", | |||
"descEn", | |||
"descEs", | |||
"descPl", | |||
].filter(Boolean); | |||
for (const k of order) { | |||
const v = (icon.dataset[k] || "").trim(); | |||
if (v) return v; | |||
} | |||
return ""; | |||
}; | |||
const updateAllSkillDescs = (norm) => { | |||
document.querySelectorAll(".icon-bar .skill-icon").forEach((icon) => { | |||
icon.dataset.desc = pickDescFor(icon, norm); | |||
}); | |||
}; | |||
// ---------- tier & tags ---------- | |||
const updateTierAndTags = (norm) => { | |||
const cont = document.querySelector(".class-tags"); | |||
if (!cont) return; | |||
const | const tier = cont.querySelector(".class-tag.tier"); | ||
if (tier) { | |||
const t = | |||
tier.getAttribute("data-tier-" + norm) || | |||
tier.getAttribute("data-tier-pt") || | |||
tier.getAttribute("data-tier-en") || | |||
tier.getAttribute("data-tier-es") || | |||
tier.getAttribute("data-tier-pl") || | |||
""; | |||
if (t) tier.textContent = t; | |||
} | |||
let tags = []; | |||
const | const pack = cont.getAttribute("data-tags-i18n"); | ||
if (pack) { | |||
try { | |||
const obj = JSON.parse(pack); | |||
const arr = | |||
obj?.[norm] || obj?.pt || obj?.en || obj?.es || obj?.pl || []; | |||
if (Array.isArray(arr)) tags = arr; | |||
} catch (e) { } | |||
} | |||
if (!tags.length) { | |||
const raw = | |||
cont.getAttribute("data-tags-" + norm) || | |||
cont.getAttribute("data-tags-pt") || | |||
cont.getAttribute("data-tags-en") || | |||
cont.getAttribute("data-tags-es") || | |||
cont.getAttribute("data-tags-pl") || | |||
""; | |||
} | if (raw) { | ||
try { | |||
const maybe = JSON.parse(raw); | |||
if (Array.isArray(maybe)) tags = maybe; | |||
} catch (e) { } | |||
if (!tags.length && typeof raw === "string") { | |||
tags = raw | |||
.split(",") | |||
.map((s) => s.trim()) | |||
.filter(Boolean); | |||
} | |||
} | |||
} | |||
if (!tags.length) return; | |||
// Tags invisíveis (não devem ser exibidas na wiki) | |||
const HIDDEN_TAGS = { | |||
mulher: true, | |||
woman: true, | |||
mujer: true, | |||
kobieta: true, | |||
}; | |||
cont | |||
.querySelectorAll(".class-tag:not(.tier)") | |||
.forEach((el) => el.remove()); | |||
tags.forEach((t) => { | |||
// Filtra tags invisíveis | |||
const normalized = (t || "").toLowerCase().trim(); | |||
if (HIDDEN_TAGS[normalized]) return; | |||
const chip = document.createElement("span"); | |||
chip.className = "class-tag"; | |||
chip.textContent = t; | |||
cont.appendChild(chip); | |||
}); | |||
}; | |||
// ---------- FLAGS: tooltips i18n ---------- | |||
const updateFlagTooltips = (norm) => { | |||
const skillsRoot = document.querySelector("#skills"); | |||
if (!skillsRoot) return; | |||
let pack = {}; | |||
try { | |||
pack = JSON.parse(skillsRoot.dataset.i18nFlags || "{}"); | |||
} catch (e) { } | |||
const dict = pack[norm] || pack.pt || {}; | |||
const tooltip = window.__globalSkillTooltip; | |||
if (!tooltip) return; | |||
document | |||
.querySelectorAll(".skill-flags .skill-flag[data-flag]") | |||
.forEach((el) => { | |||
delete el.dataset.flagTipWired; | |||
}); | |||
const descBoxes = document.querySelectorAll(".desc-box"); | |||
descBoxes.forEach((box) => { | |||
if (box.querySelector(".skill-flags")) { | |||
const flags = box.querySelectorAll( | |||
".skill-flags .skill-flag[data-flag]" | |||
); | |||
flags.forEach((el) => { | |||
const key = el.getAttribute("data-flag"); | |||
const tip = (dict && dict[key]) || ""; | |||
if (!tip) return; | |||
delete el.dataset.flagTipWired; | |||
el.setAttribute("aria-label", tip); | |||
if (el.hasAttribute("title")) el.removeAttribute("title"); | |||
el.addEventListener("mouseenter", () => { | |||
const tipEl = document.querySelector(".skill-tooltip"); | |||
if (tipEl) tipEl.classList.add("flag-tooltip"); | |||
tooltip.show(el, tip); | |||
}); | }); | ||
}; | el.addEventListener("mousemove", () => { | ||
if (performance.now() >= tooltip.lockUntil.value) { | |||
tooltip.measureAndPos(el); | |||
} | |||
}); | |||
el.addEventListener("click", () => { | |||
tooltip.lockUntil.value = performance.now() + 240; | |||
tooltip.measureAndPos(el); | |||
}); | |||
el.addEventListener("mouseleave", () => { | |||
const tipEl = document.querySelector(".skill-tooltip"); | |||
if (tipEl) tipEl.classList.remove("flag-tooltip"); | |||
tooltip.hide(); | |||
}); | |||
el.dataset.flagTipWired = "1"; | |||
}); | |||
} | |||
}); | |||
}; | |||
// ---------- SKINS: tooltips i18n ---------- | |||
const updateSkinTooltips = (norm) => { | |||
const root = document.querySelector("#skins"); | |||
if (!root) return; | |||
const slots = root.querySelectorAll(".podium-slot"); | |||
if (!slots.length) return; | |||
slots.forEach((slot) => { | |||
const title = slot.getAttribute("data-skin-title") || ""; | |||
const pack = slot.getAttribute("data-skin-tooltip-i18n"); | |||
const titleHtml = title | |||
? '<div class="skin-tooltip-title" style="margin:0">' + | |||
title + | |||
"</div>" | |||
: ""; | |||
if (pack) { | |||
let chosen = ""; | |||
try { | |||
const obj = JSON.parse(pack); | |||
chosen = ( | |||
obj[norm] || | |||
obj.pt || | |||
obj.en || | |||
obj.es || | |||
obj.pl || | |||
"" | |||
).trim(); | |||
} catch (e) { } | |||
if (chosen) { | |||
let bodyHtml = chosen | |||
.replace(/'''([^']+)'''/g, "<b>$1</b>") | |||
.replace(/\n/g, "<br>"); | |||
bodyHtml = "<b>" + bodyHtml + "</b>"; | |||
slot.setAttribute("data-skin-tooltip", titleHtml + bodyHtml); | |||
} | |||
return; | |||
} | |||
if (title) { | |||
const current = slot.getAttribute("data-skin-tooltip") || ""; | |||
if (!/skin-tooltip-title/.test(current)) { | |||
let bodyHtml = current; | |||
if (!/^<b>[\s\S]*<\/b>$/.test(bodyHtml)) { | |||
bodyHtml = "<b>" + bodyHtml + "</b>"; | |||
} | |||
slot.setAttribute("data-skin-tooltip", titleHtml + bodyHtml); | |||
} | |||
} | |||
}); | |||
const hovered = root.querySelector(".podium-slot.hovered"); | |||
const liveTip = document.querySelector( | |||
'.skin-tooltip[aria-hidden="false"], .skin-tooltip.show' | |||
); | |||
if (hovered && liveTip) { | |||
liveTip.innerHTML = hovered.getAttribute("data-skin-tooltip") || ""; | |||
} | |||
}; | |||
// ---------- APPLY ---------- | |||
const applyLang = (langFull) => { | |||
const myReq = ++__langReqSeq; | |||
const norm = normalizeLang(langFull); | |||
const langTag = (langFull || "pt-br").toLowerCase(); | |||
markActive(langFull); | |||
document.documentElement.lang = langTag; | |||
try { | |||
localStorage.setItem("glaLang", langTag); | |||
} catch (e) { } | |||
updateSkillsTabLabel(norm); | |||
updateAllSkillDescs(norm); | |||
updateTierAndTags(norm); | |||
updateSkinTooltips(norm); | |||
updateFlagTooltips(norm); | |||
try { | |||
window.dispatchEvent( | |||
new CustomEvent("gla:langChanged", { detail: { norm } }) | |||
); | |||
} catch (e) { } | |||
document.body.dataset.suppressSkillPlay = "1"; | |||
requestAnimationFrame(() => { | |||
if (myReq !== __langReqSeq) { | |||
delete document.body.dataset.suppressSkillPlay; | |||
return; | |||
} | |||
const lastIcon = window.__lastActiveSkillIcon; | |||
if (lastIcon && typeof lastIcon.click === "function") { | |||
lastIcon.click(); | |||
} | |||
setTimeout(() => { | |||
if (myReq === __langReqSeq) | |||
delete document.body.dataset.suppressSkillPlay; | |||
}, 120); | |||
}); | |||
}; | |||
// ---------- BOOT ---------- | |||
const ensureControlsPosition = () => { | |||
const controls = document.querySelector(".character-header-controls"); | |||
const header = document.querySelector(".character-header"); | |||
if (controls && header && !header.contains(controls)) { | |||
header.appendChild(controls); | |||
return true; | |||
} | |||
return false; | |||
}; | |||
const boot = () => { | |||
// Tenta mover o character-header-controls para dentro do character-header | |||
// Se não conseguir, tenta novamente após um delay | |||
const tryMove = () => { | |||
const controls = document.querySelector(".character-header-controls"); | |||
const header = document.querySelector(".character-header"); | |||
if (controls && header) { | |||
if (!header.contains(controls)) { | |||
header.appendChild(controls); | |||
} | |||
return true; | |||
} | |||
return false; | |||
}; | |||
if (!tryMove()) { | |||
let attempts = 0; | |||
const maxAttempts = 20; | |||
const checkInterval = setInterval(() => { | |||
attempts++; | |||
if (tryMove() || attempts >= maxAttempts) { | |||
clearInterval(checkInterval); | |||
} | |||
}, 100); | |||
} | |||
document.addEventListener("click", (ev) => { | |||
const btn = ev.target.closest(".char-flag[data-lang]"); | |||
if (!btn) return; | |||
ev.preventDefault(); | |||
applyLang(btn.dataset.lang || "pt-br"); | |||
}); | |||
let start = "pt-br"; | |||
try { | |||
const saved = localStorage.getItem("glaLang"); | |||
if (saved) start = saved; | |||
} catch (e) { } | |||
applyLang(start); | |||
}; | |||
if (document.readyState === "loading") { | |||
document.addEventListener("DOMContentLoaded", boot); | |||
} else { | |||
boot(); | |||
} | |||
})(); | |||
</script> | </script> | ||
<div class="character-header-controls"> | <div class="character-header-controls"> | ||
<div id="char-translator" class="char-translator" role="group" aria-label="Language switch"> | |||
<button class="char-flag" data-lang="pt-br" title="Português (Brasil)" aria-label="Português (Brasil)"> | |||
<img src="https://wiki.gla.com.br/images/8/8c/Brazil.png" alt="Português (Brasil)" /> | |||
</button> | |||
<button class="char-flag" data-lang="en" title="English" aria-label="English"> | |||
<img src="https://wiki.gla.com.br/images/0/0a/Usa.png" alt="English" /> | |||
</button> | |||
<button class="char-flag" data-lang="es" title="Español" aria-label="Español"> | |||
<img src="https://wiki.gla.com.br/images/5/58/Spain.png" alt="Español" /> | |||
</button> | |||
<button class="char-flag" data-lang="pl" title="Polski" aria-label="Polski"> | |||
<img src="https://wiki.gla.com.br/images/9/99/Poland.png" alt="Polski" /> | |||
</button> | |||
</div> | |||
</div> | </div> | ||
<style> | <style> | ||
:root { | |||
--ct-bg: rgba(0, 0, 0, 0.35); | |||
--ct-bd: rgba(255, 255, 255, 0.15); | |||
--ct-active: #3b82f6; | |||
--ct-active-bg: rgba(59, 130, 246, 0.14); | |||
--ct-active-bd: rgba(59, 130, 246, 0.45); | |||
--ct-hover-bd: rgba(255, 255, 255, 0.3); | |||
} | } | ||
.character-box .character-header { | |||
position: relative; | |||
} | |||
/* Container para organizar translator e weapon toggle em blocos separados */ | |||
.character-header-controls { | |||
position: absolute; | |||
top: 8px; | |||
right: 8px; | |||
display: flex; | |||
flex-direction: column; | |||
gap: 8px; | |||
z-index: 10; | |||
align-items: flex-end; | |||
} | |||
.char-translator { | |||
display: flex; | |||
} | gap: 6px; | ||
background: var(--ct-bg); | |||
padding: 4px; | |||
border-radius: 8px; | |||
border: 1px solid var(--ct-bd); | |||
-webkit-backdrop-filter: blur(2px); | |||
backdrop-filter: blur(2px); | |||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25); | |||
} | |||
.char-flag { | |||
width: 32px; | |||
height: 24px; | |||
padding: 0; | |||
border-radius: 6px; | |||
border: 1px solid rgba(255, 255, 255, 0.18); | |||
background: rgba(255, 255, 255, 0.06); | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
cursor: pointer; | |||
overflow: hidden; | |||
transition: transform 0.08s ease, border-color 0.15s ease, | |||
background 0.15s ease, outline-color 0.15s ease; | |||
outline: 2px solid transparent; | |||
box-sizing: border-box; | |||
} | |||
.char-flag:hover { | |||
border-color: var(--ct-hover-bd); | |||
transform: translateY(-1px); | |||
} | |||
.char-flag:focus-visible { | |||
outline-color: var(--ct-active); | |||
outline-offset: 2px; | |||
} | |||
.char-flag img { | |||
width: 100%; | |||
height: 100%; | |||
object-fit: cover; | |||
display: block; | |||
pointer-events: none; | |||
} | |||
.char-flag.active { | |||
outline-color: var(--ct-active); | |||
background: var(--ct-active-bg); | |||
border-color: var(--ct-active-bd); | |||
} | |||
. | @media (max-width: 600px) { | ||
.character-header-controls { | |||
top: 6px; | |||
right: 6px; | |||
gap: 6px; | |||
} | } | ||
.char- | .char-translator { | ||
gap: 4px; | |||
padding: 3px; | |||
} | } | ||
.char-flag { | |||
width: 28px; | |||
height: 20px; | |||
padding: 0; | |||
border-radius: 5px; | |||
} | } | ||
} | |||
</style> | </style> | ||
Edição atual tal como às 14h18min de 22 de janeiro de 2026
<script>
(() => {
let __langReqSeq = 0;
// ---------- helpers ----------
const normalizeLang = (s) => {
s = (s || "").toLowerCase();
if (s === "pt-br" || s === "pt_br" || s === "ptbr") return "pt";
return s.split("-")[0] || "pt";
};
const markActive = (langFull) => {
const lang = (langFull || "pt-br").toLowerCase();
document.querySelectorAll(".char-flag[data-lang]").forEach((b) => {
b.classList.toggle("active", b.dataset.lang === lang);
});
};
const updateSkillsTabLabel = (norm) => {
const map = {
en: "Skills",
pt: "Habilidades",
es: "Habilidades",
pl: "Umiejętności",
};
const btn =
document.querySelector('.character-tabs .tab-btn[data-tab="skills"]') ||
Array.from(document.querySelectorAll(".character-tabs .tab-btn")).find(
(b) => /skill|habil|umiej/i.test(b.textContent || "")
);
if (btn) btn.textContent = map[norm] || map.pt;
};
// ---------- skills ----------
const pickDescFor = (icon, norm) => {
const keyMap = { pt: "descPt", en: "descEn", es: "descEs", pl: "descPl" };
const order = [
keyMap[norm],
"descPt",
"descEn",
"descEs",
"descPl",
].filter(Boolean);
for (const k of order) {
const v = (icon.dataset[k] || "").trim();
if (v) return v;
}
return "";
};
const updateAllSkillDescs = (norm) => {
document.querySelectorAll(".icon-bar .skill-icon").forEach((icon) => {
icon.dataset.desc = pickDescFor(icon, norm);
});
};
// ---------- tier & tags ----------
const updateTierAndTags = (norm) => {
const cont = document.querySelector(".class-tags");
if (!cont) return;
const tier = cont.querySelector(".class-tag.tier");
if (tier) {
const t =
tier.getAttribute("data-tier-" + norm) ||
tier.getAttribute("data-tier-pt") ||
tier.getAttribute("data-tier-en") ||
tier.getAttribute("data-tier-es") ||
tier.getAttribute("data-tier-pl") ||
"";
if (t) tier.textContent = t;
}
let tags = [];
const pack = cont.getAttribute("data-tags-i18n");
if (pack) {
try {
const obj = JSON.parse(pack);
const arr =
obj?.[norm] || obj?.pt || obj?.en || obj?.es || obj?.pl || [];
if (Array.isArray(arr)) tags = arr;
} catch (e) { }
}
if (!tags.length) {
const raw =
cont.getAttribute("data-tags-" + norm) ||
cont.getAttribute("data-tags-pt") ||
cont.getAttribute("data-tags-en") ||
cont.getAttribute("data-tags-es") ||
cont.getAttribute("data-tags-pl") ||
"";
if (raw) {
try {
const maybe = JSON.parse(raw);
if (Array.isArray(maybe)) tags = maybe;
} catch (e) { }
if (!tags.length && typeof raw === "string") {
tags = raw
.split(",")
.map((s) => s.trim())
.filter(Boolean);
}
}
}
if (!tags.length) return;
// Tags invisíveis (não devem ser exibidas na wiki)
const HIDDEN_TAGS = {
mulher: true,
woman: true,
mujer: true,
kobieta: true,
};
cont
.querySelectorAll(".class-tag:not(.tier)")
.forEach((el) => el.remove());
tags.forEach((t) => {
// Filtra tags invisíveis
const normalized = (t || "").toLowerCase().trim();
if (HIDDEN_TAGS[normalized]) return;
const chip = document.createElement("span");
chip.className = "class-tag";
chip.textContent = t;
cont.appendChild(chip);
});
};
// ---------- FLAGS: tooltips i18n ----------
const updateFlagTooltips = (norm) => {
const skillsRoot = document.querySelector("#skills");
if (!skillsRoot) return;
let pack = {};
try {
pack = JSON.parse(skillsRoot.dataset.i18nFlags || "{}");
} catch (e) { }
const dict = pack[norm] || pack.pt || {};
const tooltip = window.__globalSkillTooltip;
if (!tooltip) return;
document
.querySelectorAll(".skill-flags .skill-flag[data-flag]")
.forEach((el) => {
delete el.dataset.flagTipWired;
});
const descBoxes = document.querySelectorAll(".desc-box");
descBoxes.forEach((box) => {
if (box.querySelector(".skill-flags")) {
const flags = box.querySelectorAll(
".skill-flags .skill-flag[data-flag]"
);
flags.forEach((el) => {
const key = el.getAttribute("data-flag");
const tip = (dict && dict[key]) || "";
if (!tip) return;
delete el.dataset.flagTipWired;
el.setAttribute("aria-label", tip);
if (el.hasAttribute("title")) el.removeAttribute("title");
el.addEventListener("mouseenter", () => {
const tipEl = document.querySelector(".skill-tooltip");
if (tipEl) tipEl.classList.add("flag-tooltip");
tooltip.show(el, tip);
});
el.addEventListener("mousemove", () => {
if (performance.now() >= tooltip.lockUntil.value) {
tooltip.measureAndPos(el);
}
});
el.addEventListener("click", () => {
tooltip.lockUntil.value = performance.now() + 240;
tooltip.measureAndPos(el);
});
el.addEventListener("mouseleave", () => {
const tipEl = document.querySelector(".skill-tooltip");
if (tipEl) tipEl.classList.remove("flag-tooltip");
tooltip.hide();
});
el.dataset.flagTipWired = "1";
});
}
});
};
// ---------- SKINS: tooltips i18n ----------
const updateSkinTooltips = (norm) => {
const root = document.querySelector("#skins");
if (!root) return;
const slots = root.querySelectorAll(".podium-slot");
if (!slots.length) return;
slots.forEach((slot) => {
const title = slot.getAttribute("data-skin-title") || "";
const pack = slot.getAttribute("data-skin-tooltip-i18n");
const titleHtml = title
? '
' +
title +"
"
: "";
if (pack) {
let chosen = "";
try {
const obj = JSON.parse(pack);
chosen = (
obj[norm] ||
obj.pt ||
obj.en ||
obj.es ||
obj.pl ||
""
).trim();
} catch (e) { }
if (chosen) {
let bodyHtml = chosen
.replace(/([^']+)/g, "$1")
.replace(/\n/g, "
");
bodyHtml = "" + bodyHtml + "";
slot.setAttribute("data-skin-tooltip", titleHtml + bodyHtml);
}
return;
}
if (title) {
const current = slot.getAttribute("data-skin-tooltip") || "";
if (!/skin-tooltip-title/.test(current)) {
let bodyHtml = current;
if (!/^[\s\S]*<\/b>$/.test(bodyHtml)) {
bodyHtml = "" + bodyHtml + "";
}
slot.setAttribute("data-skin-tooltip", titleHtml + bodyHtml);
}
}
});
const hovered = root.querySelector(".podium-slot.hovered");
const liveTip = document.querySelector(
'.skin-tooltip[aria-hidden="false"], .skin-tooltip.show'
);
if (hovered && liveTip) {
liveTip.innerHTML = hovered.getAttribute("data-skin-tooltip") || "";
}
};
// ---------- APPLY ----------
const applyLang = (langFull) => {
const myReq = ++__langReqSeq;
const norm = normalizeLang(langFull);
const langTag = (langFull || "pt-br").toLowerCase();
markActive(langFull);
document.documentElement.lang = langTag;
try {
localStorage.setItem("glaLang", langTag);
} catch (e) { }
updateSkillsTabLabel(norm);
updateAllSkillDescs(norm);
updateTierAndTags(norm);
updateSkinTooltips(norm);
updateFlagTooltips(norm);
try {
window.dispatchEvent(
new CustomEvent("gla:langChanged", { detail: { norm } })
);
} catch (e) { }
document.body.dataset.suppressSkillPlay = "1";
requestAnimationFrame(() => {
if (myReq !== __langReqSeq) {
delete document.body.dataset.suppressSkillPlay;
return;
}
const lastIcon = window.__lastActiveSkillIcon;
if (lastIcon && typeof lastIcon.click === "function") {
lastIcon.click();
}
setTimeout(() => {
if (myReq === __langReqSeq)
delete document.body.dataset.suppressSkillPlay;
}, 120);
});
};
// ---------- BOOT ----------
const ensureControlsPosition = () => {
const controls = document.querySelector(".character-header-controls");
const header = document.querySelector(".character-header");
if (controls && header && !header.contains(controls)) {
header.appendChild(controls);
return true;
}
return false;
};
const boot = () => {
// Tenta mover o character-header-controls para dentro do character-header
// Se não conseguir, tenta novamente após um delay
const tryMove = () => {
const controls = document.querySelector(".character-header-controls");
const header = document.querySelector(".character-header");
if (controls && header) {
if (!header.contains(controls)) {
header.appendChild(controls);
}
return true;
}
return false;
};
if (!tryMove()) {
let attempts = 0;
const maxAttempts = 20;
const checkInterval = setInterval(() => {
attempts++;
if (tryMove() || attempts >= maxAttempts) {
clearInterval(checkInterval);
}
}, 100);
}
document.addEventListener("click", (ev) => {
const btn = ev.target.closest(".char-flag[data-lang]");
if (!btn) return;
ev.preventDefault();
applyLang(btn.dataset.lang || "pt-br");
});
let start = "pt-br";
try {
const saved = localStorage.getItem("glaLang");
if (saved) start = saved;
} catch (e) { }
applyLang(start);
};
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", boot);
} else {
boot();
}
})();
</script>
<button class="char-flag" data-lang="pt-br" title="Português (Brasil)" aria-label="Português (Brasil)">
<img src="https://wiki.gla.com.br/images/8/8c/Brazil.png" alt="Português (Brasil)" />
</button>
<button class="char-flag" data-lang="en" title="English" aria-label="English">
<img src="https://wiki.gla.com.br/images/0/0a/Usa.png" alt="English" />
</button>
<button class="char-flag" data-lang="es" title="Español" aria-label="Español">
<img src="https://wiki.gla.com.br/images/5/58/Spain.png" alt="Español" />
</button>
<button class="char-flag" data-lang="pl" title="Polski" aria-label="Polski">
<img src="https://wiki.gla.com.br/images/9/99/Poland.png" alt="Polski" />
</button>
<style>
:root {
--ct-bg: rgba(0, 0, 0, 0.35);
--ct-bd: rgba(255, 255, 255, 0.15);
--ct-active: #3b82f6;
--ct-active-bg: rgba(59, 130, 246, 0.14);
--ct-active-bd: rgba(59, 130, 246, 0.45);
--ct-hover-bd: rgba(255, 255, 255, 0.3);
}
.character-box .character-header {
position: relative;
}
/* Container para organizar translator e weapon toggle em blocos separados */
.character-header-controls {
position: absolute;
top: 8px;
right: 8px;
display: flex;
flex-direction: column;
gap: 8px;
z-index: 10;
align-items: flex-end;
}
.char-translator {
display: flex;
gap: 6px;
background: var(--ct-bg);
padding: 4px;
border-radius: 8px;
border: 1px solid var(--ct-bd);
-webkit-backdrop-filter: blur(2px);
backdrop-filter: blur(2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
}
.char-flag {
width: 32px;
height: 24px;
padding: 0;
border-radius: 6px;
border: 1px solid rgba(255, 255, 255, 0.18);
background: rgba(255, 255, 255, 0.06);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
overflow: hidden;
transition: transform 0.08s ease, border-color 0.15s ease,
background 0.15s ease, outline-color 0.15s ease;
outline: 2px solid transparent;
box-sizing: border-box;
}
.char-flag:hover {
border-color: var(--ct-hover-bd);
transform: translateY(-1px);
}
.char-flag:focus-visible {
outline-color: var(--ct-active);
outline-offset: 2px;
}
.char-flag img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
pointer-events: none;
}
.char-flag.active {
outline-color: var(--ct-active);
background: var(--ct-active-bg);
border-color: var(--ct-active-bd);
}
@media (max-width: 600px) {
.character-header-controls {
top: 6px;
right: 6px;
gap: 6px;
}
.char-translator {
gap: 4px;
padding: 3px;
}
.char-flag {
width: 28px;
height: 20px;
padding: 0;
border-radius: 5px;
}
}
</style>