From 467be38bd1fa5899856aa4f229a059b978b9e3c5 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 6 Apr 2026 21:39:38 +0300 Subject: [PATCH] feat(options/spellcheck): improve language selection --- .../src/translations/en/translation.json | 7 +- .../type_widgets/options/spellcheck.tsx | 104 ++++++++++++------ 2 files changed, 70 insertions(+), 41 deletions(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 9605212f6e..b6b8ae6281 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -1498,11 +1498,8 @@ "spellcheck": { "title": "Spell Check", "description": "These options apply only for desktop builds, browsers will use their own native spell check.", - "enable": "Enable spellcheck", - "language_code_label": "Language code(s)", - "language_code_placeholder": "for example \"en-US\", \"de-AT\"", - "multiple_languages_info": "Multiple languages can be separated by comma, e.g. \"en-US, de-DE, cs\". ", - "available_language_codes_label": "Available language codes:", + "enable": "Check spelling", + "language_code_label": "Spell Check Languages", "restart-required": "Changes to the spell check options will take effect after application restart." }, "sync_2": { diff --git a/apps/client/src/widgets/type_widgets/options/spellcheck.tsx b/apps/client/src/widgets/type_widgets/options/spellcheck.tsx index 68a63d6ada..d602f6c0a6 100644 --- a/apps/client/src/widgets/type_widgets/options/spellcheck.tsx +++ b/apps/client/src/widgets/type_widgets/options/spellcheck.tsx @@ -1,57 +1,89 @@ -import { useMemo } from "preact/hooks"; +import { useCallback, useMemo } from "preact/hooks"; + import { t } from "../../../services/i18n"; -import FormCheckbox from "../../react/FormCheckbox"; -import FormGroup from "../../react/FormGroup"; -import FormText from "../../react/FormText"; -import FormTextBox from "../../react/FormTextBox"; -import { useTriliumOption, useTriliumOptionBool } from "../../react/hooks"; -import OptionsSection from "./components/OptionsSection"; import { dynamicRequire, isElectron } from "../../../services/utils"; +import FormText from "../../react/FormText"; +import FormToggle from "../../react/FormToggle"; +import { useTriliumOption, useTriliumOptionBool } from "../../react/hooks"; +import CheckboxList from "./components/CheckboxList"; +import OptionsRow from "./components/OptionsRow"; +import OptionsSection from "./components/OptionsSection"; export default function SpellcheckSettings() { if (isElectron()) { - return - } else { - return + return ; } + return ; +} + +interface SpellcheckLanguage { + code: string; + name: string; } function ElectronSpellcheckSettings() { const [ spellCheckEnabled, setSpellCheckEnabled ] = useTriliumOptionBool("spellCheckEnabled"); + + return ( + <> + + {t("spellcheck.restart-required")} + + + + + + + {spellCheckEnabled && } + + ); +} + +function SpellcheckLanguages() { const [ spellCheckLanguageCode, setSpellCheckLanguageCode ] = useTriliumOption("spellCheckLanguageCode"); - const availableLanguageCodes = useMemo(() => { + const selectedCodes = useMemo(() => + (spellCheckLanguageCode ?? "") + .split(",") + .map((c) => c.trim()) + .filter((c) => c.length > 0), + [spellCheckLanguageCode] + ); + + const setSelectedCodes = useCallback((codes: string[]) => { + setSpellCheckLanguageCode(codes.join(", ")); + }, [setSpellCheckLanguageCode]); + + const availableLanguages = useMemo(() => { if (!isElectron()) { return []; } - const { webContents } = dynamicRequire("@electron/remote").getCurrentWindow(); - return webContents.session.availableSpellCheckerLanguages as string[]; - }, []) + const { webContents } = dynamicRequire("@electron/remote").getCurrentWindow(); + const codes = webContents.session.availableSpellCheckerLanguages as string[]; + const displayNames = new Intl.DisplayNames([navigator.language], { type: "language" }); + + return codes.map((code) => ({ + code, + name: displayNames.of(code) ?? code + })).sort((a, b) => a.name.localeCompare(b.name)); + }, []); return ( - - {t("spellcheck.restart-required")} - - + - - - - - - - {t("spellcheck.available_language_codes_label")} - {availableLanguageCodes.join(", ")} - - ) + ); } function WebSpellcheckSettings() { @@ -59,5 +91,5 @@ function WebSpellcheckSettings() {

{t("spellcheck.description")}

- ) -} \ No newline at end of file + ); +}