You've already forked joplin
							
							
				mirror of
				https://github.com/laurent22/joplin.git
				synced 2025-10-31 00:07:48 +02:00 
			
		
		
		
	Desktop: Add support for multi-language spell check (#6617)
This commit is contained in:
		| @@ -35,23 +35,33 @@ export default class SpellCheckerService { | ||||
| 	} | ||||
|  | ||||
| 	private async addLatestSelectedLanguage(language: string) { | ||||
| 		// This function will add selected languages to the history. History size will be capped at languagesHistorySizeMax, | ||||
| 		// but it can be bigger. Enabled languages will always be in the history, even if it count greater then | ||||
| 		// languagesHistorySizeMax, in such case if one of the languages will be disabled it will disappear from history. | ||||
| 		const languagesHistorySizeMax = 5; | ||||
| 		const languages = this.latestSelectedLanguages_.slice(); | ||||
| 		if (languages.length > 5) languages.splice(0, 1); | ||||
|  | ||||
| 		if (languages.includes(language)) { | ||||
| 			languages.splice(languages.indexOf(language), 1); | ||||
| 		if (!languages.includes(language)) { | ||||
| 			languages.push(language); | ||||
| 		} | ||||
|  | ||||
| 		languages.splice(0, 0, language); | ||||
| 		if (languages.length > languagesHistorySizeMax) { | ||||
| 			this.latestSelectedLanguages_.forEach(l => { | ||||
| 				if (!this.languages.includes(l) && languages.length > languagesHistorySizeMax) languages.splice(languages.indexOf(l), 1); | ||||
| 			}); | ||||
| 		} | ||||
|  | ||||
| 		this.latestSelectedLanguages_ = languages; | ||||
| 		await KvStore.instance().setValue('spellCheckerService.latestSelectedLanguages', JSON.stringify(this.latestSelectedLanguages_)); | ||||
| 	} | ||||
|  | ||||
| 	public setupDefaultLanguage() { | ||||
| 		if (!Setting.value('spellChecker.language')) { | ||||
| 		if (Setting.value('spellChecker.languages').length === 0) { | ||||
| 			const l = this.driver_.language; | ||||
| 			this.setLanguage(l ? l : this.defaultLanguage); | ||||
| 			if (this.availableLanguages.includes(l)) { | ||||
| 				this.setLanguage(l); | ||||
| 			} else { | ||||
| 				this.setLanguage(this.defaultLanguage); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -60,17 +70,23 @@ export default class SpellCheckerService { | ||||
| 	} | ||||
|  | ||||
| 	private applyStateToDriver() { | ||||
| 		this.driver_.setLanguage(this.enabled ? this.language : ''); | ||||
| 		this.driver_.setLanguages(this.enabled ? this.languages : []); | ||||
| 	} | ||||
|  | ||||
| 	public setLanguage(language: string) { | ||||
| 		Setting.setValue('spellChecker.language', language); | ||||
| 		let enabledLanguages: string[] = [...this.languages]; | ||||
| 		if (enabledLanguages.includes(language)) { | ||||
| 			enabledLanguages = enabledLanguages.filter(obj => obj !== language); | ||||
| 		} else { | ||||
| 			enabledLanguages.push(language); | ||||
| 		} | ||||
| 		Setting.setValue('spellChecker.languages', enabledLanguages); | ||||
| 		this.applyStateToDriver(); | ||||
| 		void this.addLatestSelectedLanguage(language); | ||||
| 	} | ||||
|  | ||||
| 	public get language(): string { | ||||
| 		return Setting.value('spellChecker.language'); | ||||
| 	public get languages(): string[] { | ||||
| 		return Setting.value('spellChecker.languages'); | ||||
| 	} | ||||
|  | ||||
| 	public get enabled(): boolean { | ||||
| @@ -115,7 +131,7 @@ export default class SpellCheckerService { | ||||
| 		output.push({ | ||||
| 			label: _('Add to dictionary'), | ||||
| 			click: () => { | ||||
| 				void this.addToDictionary(this.language, misspelledWord); | ||||
| 				void this.addToDictionary(this.languages[0], misspelledWord); | ||||
| 			}, | ||||
| 		}); | ||||
|  | ||||
| @@ -125,7 +141,7 @@ export default class SpellCheckerService { | ||||
| 	private changeLanguageMenuItem(language: string, enabled: boolean, checked: boolean) { | ||||
| 		return { | ||||
| 			label: countryDisplayName(language), | ||||
| 			type: 'radio', | ||||
| 			type: 'checkbox', | ||||
| 			checked: checked, | ||||
| 			enabled: enabled, | ||||
| 			click: () => { | ||||
| @@ -134,11 +150,11 @@ export default class SpellCheckerService { | ||||
| 		}; | ||||
| 	} | ||||
|  | ||||
| 	private changeLanguageMenuItems(selectedLanguage: string, enabled: boolean) { | ||||
| 	private changeLanguageMenuItems(selectedLanguages: string[], enabled: boolean) { | ||||
| 		const languageMenuItems = []; | ||||
|  | ||||
| 		for (const locale of this.driver_.availableLanguages) { | ||||
| 			languageMenuItems.push(this.changeLanguageMenuItem(locale, enabled, locale === selectedLanguage)); | ||||
| 			languageMenuItems.push(this.changeLanguageMenuItem(locale, enabled, selectedLanguages.includes(locale))); | ||||
| 		} | ||||
|  | ||||
| 		languageMenuItems.sort((a: any, b: any) => { | ||||
| @@ -148,9 +164,9 @@ export default class SpellCheckerService { | ||||
| 		return languageMenuItems; | ||||
| 	} | ||||
|  | ||||
| 	public spellCheckerConfigMenuItems(selectedLanguage: string, useSpellChecker: boolean) { | ||||
| 	public spellCheckerConfigMenuItems(selectedLanguages: string[], useSpellChecker: boolean) { | ||||
| 		const latestLanguageItems = this.latestSelectedLanguages_.map((language: string) => { | ||||
| 			return this.changeLanguageMenuItem(language, true, language === selectedLanguage); | ||||
| 			return this.changeLanguageMenuItem(language, true, selectedLanguages.includes(language)); | ||||
| 		}); | ||||
|  | ||||
| 		if (latestLanguageItems.length) latestLanguageItems.splice(0, 0, { type: 'separator' } as any); | ||||
| @@ -187,15 +203,15 @@ export default class SpellCheckerService { | ||||
|  | ||||
| 			{ | ||||
| 				label: _('Change language'), | ||||
| 				submenu: this.changeLanguageMenuItems(selectedLanguage, useSpellChecker), | ||||
| 				submenu: this.changeLanguageMenuItems(selectedLanguages, useSpellChecker), | ||||
| 			}, | ||||
| 		]; | ||||
| 	} | ||||
|  | ||||
| 	public spellCheckerConfigMenuItem(selectedLanguage: string, useSpellChecker: boolean) { | ||||
| 	public spellCheckerConfigMenuItem(selectedLanguages: string[], useSpellChecker: boolean) { | ||||
| 		return { | ||||
| 			label: _('Spell checker'), | ||||
| 			submenu: this.spellCheckerConfigMenuItems(selectedLanguage, useSpellChecker), | ||||
| 			submenu: this.spellCheckerConfigMenuItems(selectedLanguages, useSpellChecker), | ||||
| 		}; | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -4,7 +4,7 @@ export default class SpellCheckerServiceDriverBase { | ||||
| 		throw new Error('Not implemented'); | ||||
| 	} | ||||
|  | ||||
| 	public setLanguage(_v: string) { | ||||
| 	public setLanguages(_v: string[]) { | ||||
| 		throw new Error('Not implemented'); | ||||
| 	} | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user