From cb696276daba7913f6ece022e5552c04fff38f25 Mon Sep 17 00:00:00 2001 From: Laurent Cozic Date: Fri, 27 Nov 2020 11:12:28 +0000 Subject: [PATCH] Desktop: Fixes #4146: Prevents crash when invalid spell checker language is selected, and provide fallback for invalid language codes --- .../SpellCheckerServiceDriverNative.ts | 29 ++++++++++++++++++- packages/lib/locale.ts | 8 ++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/packages/app-desktop/services/spellChecker/SpellCheckerServiceDriverNative.ts b/packages/app-desktop/services/spellChecker/SpellCheckerServiceDriverNative.ts index 72538a740c..9ed44652e5 100644 --- a/packages/app-desktop/services/spellChecker/SpellCheckerServiceDriverNative.ts +++ b/packages/app-desktop/services/spellChecker/SpellCheckerServiceDriverNative.ts @@ -2,6 +2,10 @@ import SpellCheckerServiceDriverBase from '@joplin/lib/services/spellChecker/SpellCheckerServiceDriverBase'; import bridge from '../bridge'; +import { languageCodeOnly, localesFromLanguageCode } from '@joplin/lib/locale'; +import Logger from '@joplin/lib/Logger'; + +const logger = Logger.create('SpellCheckerServiceDriverNative'); export default class SpellCheckerServiceDriverNative extends SpellCheckerServiceDriverBase { @@ -17,7 +21,30 @@ export default class SpellCheckerServiceDriverNative extends SpellCheckerService public setLanguage(v: string) { // If we pass an empty array, it disables spell checking // https://github.com/electron/electron/issues/25228 - this.session().setSpellCheckerLanguages(v ? [v] : []); + if (!v) { + this.session().setSpellCheckerLanguages(''); + return; + } + + // The below function will throw an error if the provided language is + // not supported, so we provide fallbacks. + // https://github.com/laurent22/joplin/issues/4146 + const languagesToTry = [ + v, + languageCodeOnly(v), + ].concat(localesFromLanguageCode(languageCodeOnly(v), this.availableLanguages)); + + for (const toTry of languagesToTry) { + try { + this.session().setSpellCheckerLanguages([toTry]); + return; + } catch (error) { + logger.warn(`Failed to set language to "${toTry}". Will try the next one in this list: ${JSON.stringify(languagesToTry)}`); + logger.warn('Error was:', error); + } + } + + logger.error(`Could not set language to: ${v}`); } public get language(): string { diff --git a/packages/lib/locale.ts b/packages/lib/locale.ts index dbe32d1abf..d8901340e9 100644 --- a/packages/lib/locale.ts +++ b/packages/lib/locale.ts @@ -572,6 +572,12 @@ function languageCode() { return languageCodeOnly(currentLocale_); } +function localesFromLanguageCode(languageCode: string, locales: string[]): string[] { + return locales.filter((l: string) => { + return languageCodeOnly(l) === languageCode; + }); +} + function _(s: string, ...args: any[]) { const strings = localeStrings(currentLocale_); let result = strings[s]; @@ -588,4 +594,4 @@ function _n(singular: string, plural: string, n: number, ...args: any[]) { return _(singular, ...args); } -export { _, _n, supportedLocales, countryDisplayName, localeStrings, setLocale, supportedLocalesToLanguages, defaultLocale, closestSupportedLocale, languageCode, countryCodeOnly }; +export { _, _n, supportedLocales, localesFromLanguageCode, languageCodeOnly, countryDisplayName, localeStrings, setLocale, supportedLocalesToLanguages, defaultLocale, closestSupportedLocale, languageCode, countryCodeOnly };