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