Open alexstrat opened 7 years ago
@alexstrat I can reproduce. Any workaround for this?
@alexstrat same on Linux as well.
Hmm. This used to work for me, but not anymore.
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.
This is a little suspect: https://github.com/atom/node-spellchecker/blob/master/src/spellchecker_mac.mm#L149-L154
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)
}
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).
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: https://github.com/electron/electron/pull/20692
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