Theseus: Settings language dropdown — supported first, in their own optgroup

The dropdown mixed supported and unsupported languages in one list ranked
by global speakers, so the six languages the translator actually handles
today (en, es, fr, de, el, ru) were scattered between greyed rows. The
user had to scan every entry to find the ones they could pick. The
dropdown is now partitioned into two <optgroup>s — "Supported today"
first with the enabled languages, "Translator coming later (Accept-
Language only)" below with the greyed rows — so the top of the list
is actionable and the roadmap is still visible underneath.
This commit is contained in:
Silent Mode 2026-10-03 23:27:05 +02:00
parent 8b74f5cbf9
commit 5f02973597

View file

@ -1248,22 +1248,26 @@
if (!webLangPick) return; if (!webLangPick) return;
let osLoc = "en-US"; let osLoc = "en-US";
try { osLoc = (C.systemLocale && await C.systemLocale()) || "en-US"; } catch {} try { osLoc = (C.systemLocale && await C.systemLocale()) || "en-US"; } catch {}
// Supported-by-the-translator languages come enabled; the rest are // Partitioned into two <optgroup>s so the dropdown reads as a map,
// shown but disabled with a "— coming later" suffix, so the picker is // not a lottery: the languages the translator actually handles come
// a roadmap, not a lie — the user sees which languages the chip will // first in their own group, every other entry sits under the second
// actually translate pages into today. "Other…" is still here for a // group with a greyed "— translator coming later" tail. "Other…"
// user who needs to pin an unlisted BCP-47 tag for Accept-Language // stays below for a user who needs to pin a tag that is not on the
// alone, but it's marked so they know translation won't follow. // list for Accept-Language purposes only.
const SUPPORTED = new Set(["en", "es", "fr", "de", "el", "ru"]); const SUPPORTED = new Set(["en", "es", "fr", "de", "el", "ru"]);
const baseOf = (t) => String(t || "").split("-")[0].toLowerCase(); const baseOf = (t) => String(t || "").split("-")[0].toLowerCase();
const opts = [`<option value="__auto__">Automatic (${langNameFor(osLoc)})</option>`, const supportedLangs = WEB_LANG_QUICK.filter((L) => SUPPORTED.has(baseOf(L.tag)));
...WEB_LANG_QUICK.map((L) => { const otherLangs = WEB_LANG_QUICK.filter((L) => !SUPPORTED.has(baseOf(L.tag)));
const supported = SUPPORTED.has(baseOf(L.tag)); const opts = [
return supported `<option value="__auto__">Automatic (${langNameFor(osLoc)})</option>`,
? `<option value="${L.tag}">${L.label}</option>` `<optgroup label="Supported today">`,
: `<option value="${L.tag}" disabled>${L.label} — translator coming later</option>`; ...supportedLangs.map((L) => `<option value="${L.tag}">${L.label}</option>`),
}), `</optgroup>`,
`<option value="__other__">Other… (Accept-Language only, no translation)</option>`]; `<optgroup label="Translator coming later (Accept-Language only)">`,
...otherLangs.map((L) => `<option value="${L.tag}" disabled>${L.label}</option>`),
`</optgroup>`,
`<option value="__other__">Other… (Accept-Language only, no translation)</option>`,
];
webLangPick.innerHTML = opts.join(""); webLangPick.innerHTML = opts.join("");
const paint = (cur) => { const paint = (cur) => {
const mode = cur.languageMode || "show"; const mode = cur.languageMode || "show";