// ==UserScript== // @name Show account names (all locales) + Force English + Auto-press Translate + De-locale redirect // @namespace io.inp // @match https://*.esologs.com/* // @grant none // @version 1.6 // @author Xandaros (tweaked by Kwiebe-Kwibus) // @license BSD-2-Clause // @run-at document-start // @description Forces English on esologs.com, redirects locale subdomains (e.g., ru.esologs.com) to esologs.com, auto-presses "Translate" button, and replaces character names with account names // @downloadURL none // ==/UserScript== (function () { "use strict"; // --- 0) If on a locale subdomain (e.g., ru.esologs.com), redirect to the root domain (esologs.com) --- (function redirectLocaleSubdomain() { try { const host = location.hostname; // e.g., ru.esologs.com const m = host.match(/^([a-z]{2})\.esologs\.com$/i); // Redirect any 2-letter locale (ru, de, fr, etc.) EXCEPT "en" (just in case) if (m && m[1].toLowerCase() !== "en") { const targetHost = "esologs.com"; // user explicitly asked for root, not www const newUrl = location.protocol + "//" + targetHost + location.pathname + location.search + location.hash; // Use replace() to avoid back button ping-pong location.replace(newUrl); return; // stop running rest on this page; the new page will run the script again } } catch (_) {} })(); // --- 1) Force site language to English (works on esologs.com & subdomains) --- (function ensureEnglish() { try { const desired = "en"; const hasEnCookie = (name) => document.cookie.split(";").some((c) => c.trim().startsWith(name + "=en")); const setCookie = (name, value, domain) => { const maxAge = 60 * 60 * 24 * 365; // 1 year const parts = [ `${name}=${value}`, "path=/", `max-age=${maxAge}`, "samesite=lax", "secure", ]; if (domain) parts.push(`domain=${domain}`); document.cookie = parts.join("; "); }; const needSet = !hasEnCookie("NEXT_LOCALE") || (typeof localStorage !== "undefined" && (localStorage.getItem("NEXT_LOCALE") !== desired || localStorage.getItem("locale") !== desired || localStorage.getItem("language") !== desired)); if (needSet) { const host = location.hostname; // Root cookie so it applies on all subdomains too setCookie("NEXT_LOCALE", desired, ".esologs.com"); // Also set on current host in case root is blocked for any reason setCookie("NEXT_LOCALE", desired, undefined); try { localStorage.setItem("NEXT_LOCALE", desired); localStorage.setItem("locale", desired); localStorage.setItem("language", desired); } catch (_) {} try { sessionStorage.setItem("NEXT_LOCALE", desired); } catch (_) {} if (!sessionStorage.getItem("esologs_forced_en_reloaded")) { sessionStorage.setItem("esologs_forced_en_reloaded", "1"); location.reload(); } } } catch (_) {} })(); // --- 2) Auto-press the "Translate"/"Show Original" button --- function autoPressTranslate() { function clickButton() { const btn = document.querySelector("input.translator-button"); if (btn && btn.value && /Show Original|Translate/i.test(btn.value)) { btn.click(); return true; } return false; } // Try a few times (button appears late) let tries = 0; const maxTries = 20; const timer = setInterval(() => { tries++; if (clickButton() || tries >= maxTries) clearInterval(timer); }, 500); // Watch for future appearances const mo = new MutationObserver(() => clickButton()); const startObs = () => { if (document.body) { mo.observe(document.body, { childList: true, subtree: true }); } else { requestAnimationFrame(startObs); } }; startObs(); } // --- 3) Replace character names with account display names --- function replaceNames(nodeOr$) { const $root = window.jQuery ? window.jQuery(nodeOr$) : null; const nodeList = $root ? $root.contents().toArray() : nodeOr$?.childNodes ? Array.from(nodeOr$.childNodes) : []; for (const inner of nodeList) { if (!inner) continue; if (inner.nodeType === Node.TEXT_NODE && inner.parentElement) { const tag = inner.parentElement.tagName; if (["SCRIPT", "STYLE", "TEXTAREA", "INPUT"].includes(tag)) continue; const txt = inner.textContent; if (!txt || !Array.isArray(window.players)) continue; let out = txt; for (const player of window.players) { if (!player) continue; if (player.type === "NPC" || player.anonymous) continue; if (!player.name || !player.displayName) continue; if (out.includes(player.displayName)) continue; out = out.replaceAll(player.name, player.displayName); } if (out !== txt) inner.textContent = out; } if (inner.childNodes && inner.childNodes.length) replaceNames(inner); } } function initWhenReady() { if (Array.isArray(window.players) && window.players.length > 0) { replaceNames(document.documentElement); const obs = new MutationObserver((mutations) => { for (const m of mutations) { if (m.type === "childList") { m.addedNodes.forEach((n) => replaceNames(n)); } else if (m.type === "characterData" && m.target?.parentElement) { replaceNames(m.target.parentElement); } } }); obs.observe(document.documentElement, { childList: true, characterData: true, subtree: true, }); return true; } return false; } function startNameReplacement() { if (!initWhenReady()) { const maxTries = 30; let tries = 0; const timer = setInterval(() => { tries++; if (initWhenReady() || tries >= maxTries) clearInterval(timer); }, 500); } } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", () => { autoPressTranslate(); startNameReplacement(); }, { once: true }); } else { autoPressTranslate(); startNameReplacement(); } })();