/** * Latin → Elder Futhark transliteration for the "Runic browser * names" display option. Each letter maps to a single rune chosen * for phonetic or visual fit; letters without a clean Futhark * match (Q, X, Y) fall back to multi-rune combinations or the * closest phoneme. Runes have no case, so the mapping is * case-insensitive and the input is lowercased before lookup. * * Tested on the installed browser list — every name remains * readable (each glyph is distinct, lengths comparable to the * Latin original): * Brave → ᛒᚱᚨᚹᛖ * Chrome → ᚲᚺᚱᛟᛗᛖ * DuckDuckGo → ᛞᚢᚲᚲᛞᚢᚲᚲᚷᛟ * Firefox → ᚠᛁᚱᛖᚠᛟᚲᛋ * Firefox Nightly → ᚠᛁᚱᛖᚠᛟᚲᛋ ᚾᛁᚷᚺᛏᛚᛁ * Helium → ᚺᛖᛚᛁᚢᛗ * IronFox → ᛁᚱᛟᚾᚠᛟᚲᛋ * Tor Browser → ᛏᛟᚱ ᛒᚱᛟᚹᛋᛖᚱ * Vanadium → ᚹᚨᚾᚨᛞᛁᚢᛗ */ const LATIN_TO_RUNE: Record = { a: 'ᚨ', b: 'ᛒ', c: 'ᚲ', d: 'ᛞ', e: 'ᛖ', f: 'ᚠ', g: 'ᚷ', h: 'ᚺ', i: 'ᛁ', j: 'ᛃ', k: 'ᚲ', l: 'ᛚ', m: 'ᛗ', n: 'ᚾ', o: 'ᛟ', p: 'ᛈ', q: 'ᚲᚹ', r: 'ᚱ', s: 'ᛋ', t: 'ᛏ', u: 'ᚢ', v: 'ᚹ', w: 'ᚹ', x: 'ᚲᛋ', y: 'ᛁ', z: 'ᛉ', }; /** * Transliterates a Latin-letter string to Elder Futhark runes. * Non-letter characters (spaces, punctuation, digits) pass through * unchanged. */ export function transliterateToRunes(input: string): string { let out = ''; for (const ch of input) { const lower = ch.toLowerCase(); out += LATIN_TO_RUNE[lower] ?? ch; } return out; } /** * Convenience wrapper used by display components: returns the * runic transliteration when the runic-names toggle is on, * otherwise the original string verbatim. */ export function formatRunicName(name: string, runic: boolean): string { return runic ? transliterateToRunes(name) : name; }