Mudanças entre as edições de "Widget:C.Translator"

De Wiki Gla
Ir para navegação Ir para pesquisar
m
m
 
Linha 1: Linha 1:
<!-- CHARACTER TRANSLATOR SYSTEM -->
<!-- CHARACTER TRANSLATOR SYSTEM -->
<script>
<script>
    (() => {
  (() => {
        let __langReqSeq = 0;
    let __langReqSeq = 0;


        // ---------- helpers ----------
    // ---------- helpers ----------
        const normalizeLang = (s) => {
    const normalizeLang = (s) => {
            s = (s || '').toLowerCase();
      s = (s || "").toLowerCase();
            if (s === 'pt-br' || s === 'pt_br' || s === 'ptbr') return 'pt';
      if (s === "pt-br" || s === "pt_br" || s === "ptbr") return "pt";
            return (s.split('-')[0] || 'pt');
      return s.split("-")[0] || "pt";
        };
    };


        const markActive = (langFull) => {
    const markActive = (langFull) => {
            const lang = (langFull || 'pt-br').toLowerCase();
      const lang = (langFull || "pt-br").toLowerCase();
            document.querySelectorAll('.char-flag[data-lang]').forEach(b => {
      document.querySelectorAll(".char-flag[data-lang]").forEach((b) => {
                b.classList.toggle('active', b.dataset.lang === lang);
        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 updateSkillsTabLabel = (norm) => {
    const updateAllSkillDescs = (norm) => {
            const map = { en: 'Skills', pt: 'Habilidades', es: 'Habilidades', pl: 'Umiejętności' };
      document.querySelectorAll(".icon-bar .skill-icon").forEach((icon) => {
            const btn = document.querySelector('.character-tabs .tab-btn[data-tab="skills"]')
        icon.dataset.desc = pickDescFor(icon, norm);
                || 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 ----------
    // ---------- tier & tags ----------
        const pickDescFor = (icon, norm) => {
    const updateTierAndTags = (norm) => {
            const keyMap = { pt: 'descPt', en: 'descEn', es: 'descEs', pl: 'descPl' };
      const cont = document.querySelector(".class-tags");
            const order = [keyMap[norm], 'descPt', 'descEn', 'descEs', 'descPl'].filter(Boolean);
      if (!cont) return;
            for (const k of order) {
                const v = (icon.dataset[k] || '').trim();
                if (v) return v;
            }
            return '';
        };


         const updateAllSkillDescs = (norm) => {
      const tier = cont.querySelector(".class-tag.tier");
            document.querySelectorAll('.icon-bar .skill-icon').forEach(icon => {
      if (tier) {
                icon.dataset.desc = pickDescFor(icon, norm);
         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;
      }


        // ---------- tier & tags ----------
      let tags = [];
         const updateTierAndTags = (norm) => {
      const pack = cont.getAttribute("data-tags-i18n");
             const cont = document.querySelector('.class-tags');
      if (pack) {
            if (!cont) return;
         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) { }
      }


            const tier = cont.querySelector('.class-tag.tier');
      if (!tags.length) {
            if (tier) {
        const raw =
                const t = tier.getAttribute('data-tier-' + norm)
          cont.getAttribute("data-tags-" + norm) ||
                    || tier.getAttribute('data-tier-pt')
          cont.getAttribute("data-tags-pt") ||
                    || tier.getAttribute('data-tier-en')
          cont.getAttribute("data-tags-en") ||
                    || tier.getAttribute('data-tier-es')
          cont.getAttribute("data-tags-es") ||
                    || tier.getAttribute('data-tier-pl') || '';
          cont.getAttribute("data-tags-pl") ||
                if (t) tier.textContent = t;
          "";
             }
        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);
          }
        }
      }


            let tags = [];
      if (!tags.length) return;
            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) {
      // Tags invisíveis (não devem ser exibidas na wiki)
                const raw = cont.getAttribute('data-tags-' + norm)
      const HIDDEN_TAGS = {
                    || cont.getAttribute('data-tags-pt')
        mulher: true,
                    || cont.getAttribute('data-tags-en')
        woman: true,
                    || cont.getAttribute('data-tags-es')
        mujer: true,
                    || cont.getAttribute('data-tags-pl')
        kobieta: true,
                    || '';
      };
                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;
      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;


            cont.querySelectorAll('.class-tag:not(.tier)').forEach(el => el.remove());
        const chip = document.createElement("span");
            tags.forEach(t => {
        chip.className = "class-tag";
                const chip = document.createElement('span');
        chip.textContent = t;
                chip.className = 'class-tag';
        cont.appendChild(chip);
                chip.textContent = t;
      });
                cont.appendChild(chip);
    };
            });
        };


        // ---------- FLAGS: tooltips i18n ----------
    // ---------- FLAGS: tooltips i18n ----------
        const updateFlagTooltips = (norm) => {
    const updateFlagTooltips = (norm) => {
            const skillsRoot = document.querySelector('#skills');
      const skillsRoot = document.querySelector("#skills");
            if (!skillsRoot) return;
      if (!skillsRoot) return;
            let pack = {};
      let pack = {};
            try { pack = JSON.parse(skillsRoot.dataset.i18nFlags || '{}'); } catch (e) { }
      try {
            const dict = pack[norm] || pack.pt || {};
        pack = JSON.parse(skillsRoot.dataset.i18nFlags || "{}");
            const tooltip = window.__globalSkillTooltip;
      } catch (e) { }
            if (!tooltip) return;
      const dict = pack[norm] || pack.pt || {};
      const tooltip = window.__globalSkillTooltip;
      if (!tooltip) return;


            document.querySelectorAll('.skill-flags .skill-flag[data-flag]').forEach(el => {
      document
                delete el.dataset.flagTipWired;
        .querySelectorAll(".skill-flags .skill-flag[data-flag]")
            });
        .forEach((el) => {
          delete el.dataset.flagTipWired;
        });


            const descBoxes = document.querySelectorAll('.desc-box');
      const descBoxes = document.querySelectorAll(".desc-box");
            descBoxes.forEach(box => {
      descBoxes.forEach((box) => {
                if (box.querySelector('.skill-flags')) {
        if (box.querySelector(".skill-flags")) {
                    const flags = box.querySelectorAll('.skill-flags .skill-flag[data-flag]');
          const flags = box.querySelectorAll(
                    flags.forEach(el => {
            ".skill-flags .skill-flag[data-flag]"
                        const key = el.getAttribute('data-flag');
          );
                        const tip = (dict && dict[key]) || '';
          flags.forEach((el) => {
                        if (!tip) return;
            const key = el.getAttribute("data-flag");
                        delete el.dataset.flagTipWired;
            const tip = (dict && dict[key]) || "";
                        el.setAttribute('aria-label', tip);
            if (!tip) return;
                        if (el.hasAttribute('title')) el.removeAttribute('title');
            delete el.dataset.flagTipWired;
            el.setAttribute("aria-label", tip);
            if (el.hasAttribute("title")) el.removeAttribute("title");


                        el.addEventListener('mouseenter', () => {
            el.addEventListener("mouseenter", () => {
                            const tipEl = document.querySelector('.skill-tooltip');
              const tipEl = document.querySelector(".skill-tooltip");
                            if (tipEl) tipEl.classList.add('flag-tooltip');
              if (tipEl) tipEl.classList.add("flag-tooltip");
                            tooltip.show(el, tip);
              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';
                    });
                }
             });
             });
         };
            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 ----------
    // ---------- SKINS: tooltips i18n ----------
        const updateSkinTooltips = (norm) => {
    const updateSkinTooltips = (norm) => {
            const root = document.querySelector('#skins');
      const root = document.querySelector("#skins");
            if (!root) return;
      if (!root) return;
            const slots = root.querySelectorAll('.podium-slot');
      const slots = root.querySelectorAll(".podium-slot");
            if (!slots.length) return;
      if (!slots.length) return;


            slots.forEach(slot => {
      slots.forEach((slot) => {
                const title = slot.getAttribute('data-skin-title') || '';
        const title = slot.getAttribute("data-skin-title") || "";
                const pack = slot.getAttribute('data-skin-tooltip-i18n');
        const pack = slot.getAttribute("data-skin-tooltip-i18n");
                const titleHtml = title ? ('<div class="skin-tooltip-title" style="margin:0">' + title + '</div>') : '';
        const titleHtml = title
          ? '<div class="skin-tooltip-title" style="margin:0">' +
          title +
          "</div>"
          : "";


                if (pack) {
        if (pack) {
                    let chosen = '';
          let chosen = "";
                    try {
          try {
                        const obj = JSON.parse(pack);
            const obj = JSON.parse(pack);
                        chosen = (obj[norm] || obj.pt || obj.en || obj.es || obj.pl || '').trim();
            chosen = (
                    } catch (e) { }
              obj[norm] ||
                    if (chosen) {
              obj.pt ||
                        let bodyHtml = chosen.replace(/'''([^']+)'''/g, '<b>$1</b>').replace(/\n/g, '<br>');
              obj.en ||
                        bodyHtml = '<b>' + bodyHtml + '</b>';
              obj.es ||
                        slot.setAttribute('data-skin-tooltip', titleHtml + bodyHtml);
              obj.pl ||
                    }
              ""
                    return;
            ).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) {
        if (title) {
                    const current = slot.getAttribute('data-skin-tooltip') || '';
          const current = slot.getAttribute("data-skin-tooltip") || "";
                    if (!/skin-tooltip-title/.test(current)) {
          if (!/skin-tooltip-title/.test(current)) {
                        let bodyHtml = current;
            let bodyHtml = current;
                        if (!/^<b>[\s\S]*<\/b>$/.test(bodyHtml)) {
            if (!/^<b>[\s\S]*<\/b>$/.test(bodyHtml)) {
                            bodyHtml = '<b>' + bodyHtml + '</b>';
              bodyHtml = "<b>" + bodyHtml + "</b>";
                        }
            }
                        slot.setAttribute('data-skin-tooltip', titleHtml + bodyHtml);
            slot.setAttribute("data-skin-tooltip", titleHtml + bodyHtml);
                    }
          }
                }
        }
            });
      });


            const hovered = root.querySelector('.podium-slot.hovered');
      const hovered = root.querySelector(".podium-slot.hovered");
            const liveTip = document.querySelector('.skin-tooltip[aria-hidden="false"], .skin-tooltip.show');
      const liveTip = document.querySelector(
            if (hovered && liveTip) {
        '.skin-tooltip[aria-hidden="false"], .skin-tooltip.show'
                liveTip.innerHTML = hovered.getAttribute('data-skin-tooltip') || '';
      );
            }
      if (hovered && liveTip) {
        };
        liveTip.innerHTML = hovered.getAttribute("data-skin-tooltip") || "";
      }
    };


        // ---------- APPLY ----------
    // ---------- APPLY ----------
        const applyLang = (langFull) => {
    const applyLang = (langFull) => {
            const myReq = ++__langReqSeq;
      const myReq = ++__langReqSeq;
            const norm = normalizeLang(langFull);
      const norm = normalizeLang(langFull);
            const langTag = (langFull || 'pt-br').toLowerCase();
      const langTag = (langFull || "pt-br").toLowerCase();


            markActive(langFull);
      markActive(langFull);
            document.documentElement.lang = langTag;
      document.documentElement.lang = langTag;
            try { localStorage.setItem('glaLang', langTag); } catch (e) { }
      try {
        localStorage.setItem("glaLang", langTag);
      } catch (e) { }


            updateSkillsTabLabel(norm);
      updateSkillsTabLabel(norm);
            updateAllSkillDescs(norm);
      updateAllSkillDescs(norm);
            updateTierAndTags(norm);
      updateTierAndTags(norm);
            updateSkinTooltips(norm);
      updateSkinTooltips(norm);
            updateFlagTooltips(norm);
      updateFlagTooltips(norm);


            try {
      try {
                window.dispatchEvent(new CustomEvent('gla:langChanged', { detail: { norm } }));
        window.dispatchEvent(
            } catch (e) { }
          new CustomEvent("gla:langChanged", { detail: { norm } })
        );
      } catch (e) { }


            document.body.dataset.suppressSkillPlay = '1';
      document.body.dataset.suppressSkillPlay = "1";
            requestAnimationFrame(() => {
      requestAnimationFrame(() => {
                if (myReq !== __langReqSeq) {
        if (myReq !== __langReqSeq) {
                    delete document.body.dataset.suppressSkillPlay;
          delete document.body.dataset.suppressSkillPlay;
                    return;
          return;
                }
        }
                const lastIcon = window.__lastActiveSkillIcon;
        const lastIcon = window.__lastActiveSkillIcon;
                if (lastIcon && typeof lastIcon.click === 'function') {
        if (lastIcon && typeof lastIcon.click === "function") {
                    lastIcon.click();
          lastIcon.click();
                }
        }
                setTimeout(() => {
        setTimeout(() => {
                    if (myReq === __langReqSeq) delete document.body.dataset.suppressSkillPlay;
          if (myReq === __langReqSeq)
                }, 120);
            delete document.body.dataset.suppressSkillPlay;
            });
        }, 120);
        };
      });
    };


        // ---------- BOOT ----------
    // ---------- BOOT ----------
        const ensureControlsPosition = () => {
    const ensureControlsPosition = () => {
            const controls = document.querySelector('.character-header-controls');
      const controls = document.querySelector(".character-header-controls");
            const header = document.querySelector('.character-header');
      const header = document.querySelector(".character-header");
            if (controls && header && !header.contains(controls)) {
      if (controls && header && !header.contains(controls)) {
                header.appendChild(controls);
        header.appendChild(controls);
                return true;
        return true;
            }
      }
            return false;
      return false;
        };
    };


        const boot = () => {
    const boot = () => {
            // Tenta mover o character-header-controls para dentro do character-header
      // Tenta mover o character-header-controls para dentro do character-header
            // Se não conseguir, tenta novamente após um delay
      // Se não conseguir, tenta novamente após um delay
            const tryMove = () => {
      const tryMove = () => {
                const controls = document.querySelector('.character-header-controls');
        const controls = document.querySelector(".character-header-controls");
                const header = document.querySelector('.character-header');
        const header = document.querySelector(".character-header");
                if (controls && header) {
        if (controls && header) {
                    if (!header.contains(controls)) {
          if (!header.contains(controls)) {
                        header.appendChild(controls);
            header.appendChild(controls);
                    }
          }
                    return true;
          return true;
                }
        }
                return false;
        return false;
            };
      };


            if (!tryMove()) {
      if (!tryMove()) {
                let attempts = 0;
        let attempts = 0;
                const maxAttempts = 20;
        const maxAttempts = 20;
                const checkInterval = setInterval(() => {
        const checkInterval = setInterval(() => {
                    attempts++;
          attempts++;
                    if (tryMove() || attempts >= maxAttempts) {
          if (tryMove() || attempts >= maxAttempts) {
                        clearInterval(checkInterval);
            clearInterval(checkInterval);
                    }
          }
                }, 100);
        }, 100);
            }
      }


            document.addEventListener('click', (ev) => {
      document.addEventListener("click", (ev) => {
                const btn = ev.target.closest('.char-flag[data-lang]');
        const btn = ev.target.closest(".char-flag[data-lang]");
                if (!btn) return;
        if (!btn) return;
                ev.preventDefault();
        ev.preventDefault();
                applyLang(btn.dataset.lang || 'pt-br');
        applyLang(btn.dataset.lang || "pt-br");
            });
      });


            let start = 'pt-br';
      let start = "pt-br";
            try {
      try {
                const saved = localStorage.getItem('glaLang');
        const saved = localStorage.getItem("glaLang");
                if (saved) start = saved;
        if (saved) start = saved;
            } catch (e) { }
      } catch (e) { }
            applyLang(start);
      applyLang(start);
        };
    };


        if (document.readyState === 'loading') {
    if (document.readyState === "loading") {
            document.addEventListener('DOMContentLoaded', boot);
      document.addEventListener("DOMContentLoaded", boot);
        } else {
    } else {
            boot();
      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">
  <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)">
    <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)" />
      <img src="https://wiki.gla.com.br/images/8/8c/Brazil.png" alt="Português (Brasil)" />
        </button>
    </button>
        <button class="char-flag" data-lang="en" title="English" aria-label="English">
    <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" />
      <img src="https://wiki.gla.com.br/images/0/0a/Usa.png" alt="English" />
        </button>
    </button>
        <button class="char-flag" data-lang="es" title="Español" aria-label="Español">
    <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" />
      <img src="https://wiki.gla.com.br/images/5/58/Spain.png" alt="Español" />
        </button>
    </button>
        <button class="char-flag" data-lang="pl" title="Polski" aria-label="Polski">
    <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" />
      <img src="https://wiki.gla.com.br/images/9/99/Poland.png" alt="Polski" />
        </button>
    </button>
    </div>
  </div>
</div>
</div>
<style>
<style>
    :root {
  :root {
        --ct-bg: rgba(0, 0, 0, .35);
    --ct-bg: rgba(0, 0, 0, 0.35);
        --ct-bd: rgba(255, 255, 255, .15);
    --ct-bd: rgba(255, 255, 255, 0.15);
        --ct-active: #3b82f6;
    --ct-active: #3b82f6;
        --ct-active-bg: rgba(59, 130, 246, .14);
    --ct-active-bg: rgba(59, 130, 246, 0.14);
        --ct-active-bd: rgba(59, 130, 246, .45);
    --ct-active-bd: rgba(59, 130, 246, 0.45);
        --ct-hover-bd: rgba(255, 255, 255, .30);
    --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;
  }


     .character-box .character-header {
  .char-translator {
        position: relative;
    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);
  }


     /* Container para organizar translator e weapon toggle em blocos separados */
  .char-flag {
     .character-header-controls {
    width: 32px;
        position: absolute;
     height: 24px;
        top: 8px;
     padding: 0;
        right: 8px;
    border-radius: 6px;
        display: flex;
    border: 1px solid rgba(255, 255, 255, 0.18);
        flex-direction: column;
    background: rgba(255, 255, 255, 0.06);
        gap: 8px;
    display: flex;
        z-index: 10;
    align-items: center;
        align-items: flex-end;
    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-translator {
  .char-flag:hover {
        display: flex;
    border-color: var(--ct-hover-bd);
        gap: 6px;
    transform: translateY(-1px);
        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, .25);
    }


    .char-flag {
  .char-flag:focus-visible {
        width: 32px;
    outline-color: var(--ct-active);
        height: 24px;
    outline-offset: 2px;
        padding: 0;
  }
        border-radius: 6px;
        border: 1px solid rgba(255, 255, 255, .18);
        background: rgba(255, 255, 255, .06);
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        overflow: hidden;
        transition: transform .08s ease, border-color .15s ease, background .15s ease, outline-color .15s ease;
        outline: 2px solid transparent;
        box-sizing: border-box;
    }


    .char-flag:hover {
  .char-flag img {
        border-color: var(--ct-hover-bd);
    width: 100%;
        transform: translateY(-1px);
    height: 100%;
    }
    object-fit: cover;
    display: block;
    pointer-events: none;
  }


    .char-flag:focus-visible {
  .char-flag.active {
        outline-color: var(--ct-active);
    outline-color: var(--ct-active);
        outline-offset: 2px;
    background: var(--ct-active-bg);
    }
    border-color: var(--ct-active-bd);
  }


     .char-flag img {
  @media (max-width: 600px) {
        width: 100%;
     .character-header-controls {
        height: 100%;
      top: 6px;
        object-fit: cover;
      right: 6px;
        display: block;
      gap: 6px;
        pointer-events: none;
     }
     }


     .char-flag.active {
     .char-translator {
        outline-color: var(--ct-active);
      gap: 4px;
        background: var(--ct-active-bg);
      padding: 3px;
        border-color: var(--ct-active-bd);
     }
     }


     @media (max-width: 600px) {
     .char-flag {
        .character-header-controls {
      width: 28px;
            top: 6px;
      height: 20px;
            right: 6px;
      padding: 0;
            gap: 6px;
      border-radius: 5px;
        }
 
        .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>