Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

macOS does NOT do automatic language detection #85

Open
alexstrat opened this issue Aug 10, 2017 · 8 comments
Open

macOS does NOT do automatic language detection #85

alexstrat opened this issue Aug 10, 2017 · 8 comments

Comments

@alexstrat
Copy link

In opposite to what is assumed here it does not look like macOS is doing automatic language detection.

My guess is that because we use node-spellchecker#setDictionary, the automatic language detection is deactivated given what is done in MacSpellchecker::UpdateGlobalSpellchecker

@akashnimare
Copy link

@alexstrat I can reproduce. Any workaround for this?

@akashnimare
Copy link

@alexstrat same on Linux as well.

@ccorcos
Copy link

ccorcos commented Mar 1, 2018

Hmm. This used to work for me, but not anymore.

@ccorcos
Copy link

ccorcos commented Apr 5, 2018

I just wanted to loop back around to this. It appears that somewhere in the past 6 months, the language auto detect has stopped working. @paulcbetts any ideas how to fix this? I'm more than happy to help.

@ccorcos
Copy link

ccorcos commented Apr 5, 2018

@ccorcos
Copy link

ccorcos commented Apr 6, 2018

Here's my attempt for language detection:

import * as _ from "lodash"
import { webFrame } from "electron"

interface Spellchecker {
	isMisspelled: (word: string) => boolean
	getCorrectionsForMisspelling: (word: string) => Array<string>
	checkSpelling: (corpus: string) => Array<{ start: number; end: number }>
	checkSpellingAsync: (
		corpus: string
	) => Promise<Array<{ start: number; end: number }>>
	add: (word: string) => void
	remove: (word: string) => void
	getAvailableDictionaries: () => Array<string>
	setDictionary: (lang: string) => void
}

interface Cld {
	detect: (text: string, fn: (err: Error, result: any) => void) => void
}

class SpellCheck {
	// cld is a native C program by google for determining the language
	// of a body of text. Note: it can handle HTML with the right options.
	private cld?: Cld

	// Native bindings to Mac and Windows spellcheckers.
	private spellchecker?: Spellchecker

	// Language that we're spell-checking
	private currentLanguage: string | undefined

	// Dynamically import the native modules in case they fail.
	async initialize() {
		this.spellchecker = await import("spellchecker")
		this.cld = await import("cld")
		document.addEventListener("selectionchange", this.handleSelectionChange)
	}

	// Detect language as the selection changes.
	private currentInputElement: HTMLElement | undefined
	private handleSelectionChange = () => {
		const inputElement = this.getInputElement()
		if (inputElement && inputElement !== this.currentInputElement) {
			// If the selection changed inputs, compute new language immediately.
			this.currentInputElement = inputElement
			this.handleDetectLanguageChange(inputElement)
		} else if (inputElement) {
			this.handleDetectLanguageChangeThrottled(inputElement)
		}
	}

	private handleDetectLanguageChange = (element: HTMLElement) => {
		const text = element.textContent
		if (text) {
			const lang = this.detectLanguage(text)
			if (lang) {
				this.setLanguage(lang)
			}
		}
	}

	private handleDetectLanguageChangeThrottled = _.throttle(
		this.handleDetectLanguageChange,
		500
	)

	private detectLanguage(text: string) {
		let lang: string | undefined
		if (this.cld) {
			this.cld.detect(text, (err, result) => {
				if (result && result.reliable) {
					if (result.languages) {
						const language = result.languages[0]
						if (language && language.code) {
							lang = language.code
						}
					}
				}
			})
		}
		return lang
	}

	private setLanguage(lang: string) {
		if (this.currentLanguage !== lang) {
			this.currentLanguage = lang
			webFrame.setSpellCheckProvider(lang, true, {
				spellCheck: word => {
					if (this.spellchecker) {
						// Note: you can iterate through multiple languages here.
						this.spellchecker.setDictionary(lang)
						if (!this.spellchecker.isMisspelled(word)) {
							return true
						}
					}
					return false
				},
			})
		}
	}

	private getInputElement() {
		const element = document.activeElement
		if (element instanceof HTMLElement) {
			if (element.tagName === "input" || element.contentEditable === "true") {
				return element
			}
		}
	}
}

const spellcheck = new SpellCheck()

try {
	spellcheck.initialize()
} catch (error) {
	console.error(error)
}

@will-russell
Copy link

Just to expand (confound?) the issue; this is also not working on Windows 10 (64-bit) (discovered in GitKraken, which uses electron for spell checking).

@quanglam2807
Copy link

quanglam2807 commented Nov 30, 2019

I confirm language detection still doesn't work. It'd be great if this can be fixed.

@ccorcos Is there an easy way to use your patch?

Update: it seems like Electron now supports spellchecker natively: electron/electron#20692

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants