From 0900a0139ebeac3f66b185c9f4271c93b498eb16 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Thu, 7 Feb 2019 20:48:57 +0100 Subject: Spellcheck language autodetection First prototype is based on slack --- src/webview/contextMenu.js | 11 +++++++++++ src/webview/recipe.js | 44 ++++++++++++++++++++++++++++++++++++++++++-- src/webview/spellchecker.js | 11 +++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/webview/contextMenu.js b/src/webview/contextMenu.js index a76c03e5a..7fadfa72b 100644 --- a/src/webview/contextMenu.js +++ b/src/webview/contextMenu.js @@ -237,6 +237,17 @@ const buildMenuTpl = (props, suggestions, isSpellcheckEnabled, defaultSpellcheck type: 'separator', visible: defaultSpellcheckerLanguage !== spellcheckerLanguage, }, + { + id: 'automaticDetection', + label: 'Automatic language detection', + type: 'radio', + visible: defaultSpellcheckerLanguage !== spellcheckerLanguage, + checked: spellcheckerLanguage === 'automatic', + click() { + debug('Detect spellchecker language automatically'); + ipcRenderer.sendToHost('set-service-spellchecker-language', 'automatic'); + }, + }, ...spellcheckingLanguages], }); diff --git a/src/webview/recipe.js b/src/webview/recipe.js index c718b348e..38a65276e 100644 --- a/src/webview/recipe.js +++ b/src/webview/recipe.js @@ -1,10 +1,12 @@ import { ipcRenderer } from 'electron'; import path from 'path'; import { autorun, computed, observable } from 'mobx'; +import { loadModule } from 'cld3-asm'; +import { debounce } from 'lodash'; import RecipeWebview from './lib/RecipeWebview'; -import spellchecker, { switchDict, disable as disableSpellchecker } from './spellchecker'; +import spellchecker, { switchDict, disable as disableSpellchecker, getSpellcheckerLocaleByFuzzyIdentifier } from './spellchecker'; import { injectDarkModeStyle, isDarkModeStyleInjected, removeDarkModeStyle } from './darkmode'; import contextMenu from './contextMenu'; import './notifications'; @@ -60,6 +62,39 @@ class RecipeController { ); autorun(() => this.update()); + + console.log(JSON.parse(JSON.stringify(this.settings))); + + const cldFactory = await loadModule(); + const identifier = cldFactory.create(0, 1000); + + window.addEventListener('keyup', debounce((e) => { + const elem = e.target; + + let value = ''; + if (elem.isContentEditable) { + value = elem.textContent; + } else { + // + } + + // Force a minimum length to get better detection results + if (value.length < 30) return; + + debug('Detecting language for', value); + const findResult = identifier.findLanguage(value); + + debug('Language detection result', findResult); + + if (findResult.is_reliable) { + debug('Language detected reliably, setting spellchecker language to', findResult.language); + const spellcheckerLocale = getSpellcheckerLocaleByFuzzyIdentifier(findResult.language); + debug('reported back', spellcheckerLocale); + if (spellcheckerLocale) { + switchDict(spellcheckerLocale); + } + } + }, 200)); } loadRecipeModule(event, config, recipe) { @@ -87,7 +122,12 @@ class RecipeController { if (this.settings.app.enableSpellchecking) { debug('Setting spellchecker language to', this.spellcheckerLanguage); - switchDict(this.spellcheckerLanguage); + let { spellcheckerLanguage } = this; + if (spellcheckerLanguage === 'automatic') { + debug('Found `automatic` locale, falling back to user locale until detected', this.settings.app.locale); + spellcheckerLanguage = this.settings.app.locale; + } + switchDict(spellcheckerLanguage); } else { debug('Disable spellchecker'); disableSpellchecker(); diff --git a/src/webview/spellchecker.js b/src/webview/spellchecker.js index becaed449..c711382be 100644 --- a/src/webview/spellchecker.js +++ b/src/webview/spellchecker.js @@ -3,6 +3,7 @@ import { SpellCheckerProvider } from 'electron-hunspell'; import path from 'path'; import { DICTIONARY_PATH } from '../config'; +import { SPELLCHECKER_LOCALES } from '../i18n/languages'; const debug = require('debug')('Franz:spellchecker'); @@ -82,3 +83,13 @@ export function disable() { currentDict = null; } } + +export function getSpellcheckerLocaleByFuzzyIdentifier(identifier) { + const locales = Object.keys(SPELLCHECKER_LOCALES).filter(key => key.split('-')[0] === identifier); + + if (locales.length >= 1) { + return locales[0]; + } + + return null; +} -- cgit v1.2.3-54-g00ecf From 75fc8f0867f222e1918c1ea430aeb26be9390fda Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Thu, 7 Feb 2019 20:49:22 +0100 Subject: improved fuzzy search --- src/webview/spellchecker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/webview/spellchecker.js b/src/webview/spellchecker.js index c711382be..9158b3b94 100644 --- a/src/webview/spellchecker.js +++ b/src/webview/spellchecker.js @@ -85,7 +85,7 @@ export function disable() { } export function getSpellcheckerLocaleByFuzzyIdentifier(identifier) { - const locales = Object.keys(SPELLCHECKER_LOCALES).filter(key => key.split('-')[0] === identifier); + const locales = Object.keys(SPELLCHECKER_LOCALES).filter(key => key === identifier.toLowerCase() || key.split('-')[0] === identifier.toLowerCase()); if (locales.length >= 1) { return locales[0]; -- cgit v1.2.3-54-g00ecf From 3e0e220908f137344f423a80958ca8672fbf64c1 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Thu, 7 Feb 2019 20:51:48 +0100 Subject: set trigger threshhold to 40 characters --- src/webview/recipe.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/webview/recipe.js b/src/webview/recipe.js index 38a65276e..fa107ba1a 100644 --- a/src/webview/recipe.js +++ b/src/webview/recipe.js @@ -63,8 +63,6 @@ class RecipeController { autorun(() => this.update()); - console.log(JSON.parse(JSON.stringify(this.settings))); - const cldFactory = await loadModule(); const identifier = cldFactory.create(0, 1000); @@ -79,7 +77,7 @@ class RecipeController { } // Force a minimum length to get better detection results - if (value.length < 30) return; + if (value.length < 40) return; debug('Detecting language for', value); const findResult = identifier.findLanguage(value); -- cgit v1.2.3-54-g00ecf From b56673e93b162addf34f037a9db2b396ec2644b0 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Thu, 7 Feb 2019 20:51:53 +0100 Subject: Remove debugging output --- src/webview/contextMenu.js | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/webview/contextMenu.js b/src/webview/contextMenu.js index 7fadfa72b..75915851d 100644 --- a/src/webview/contextMenu.js +++ b/src/webview/contextMenu.js @@ -207,8 +207,6 @@ const buildMenuTpl = (props, suggestions, isSpellcheckEnabled, defaultSpellcheck }); }); - console.log('isSpellcheckEnabled', isSpellcheckEnabled); - menuTpl.push({ type: 'separator', }, { -- cgit v1.2.3-54-g00ecf From e2437f27ccd1c7646accc75b819fff3295c7a2e2 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Fri, 8 Feb 2019 11:32:20 +0100 Subject: feat(Spell checking): Add option to automatically detect language --- .../settings/services/EditServiceForm.js | 10 +-- src/containers/settings/EditServiceScreen.js | 40 +++++++----- src/containers/settings/EditSettingsScreen.js | 16 ++--- src/features/spellchecker/index.js | 8 ++- src/helpers/i18n-helpers.js | 27 +++++--- src/i18n/globalMessages.js | 16 +++++ src/i18n/locales/en-US.json | 4 ++ src/webview/contextMenu.js | 11 ++-- src/webview/recipe.js | 76 +++++++++++++--------- 9 files changed, 132 insertions(+), 76 deletions(-) (limited to 'src') diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js index 468d85c45..21616b5de 100644 --- a/src/components/settings/services/EditServiceForm.js +++ b/src/components/settings/services/EditServiceForm.js @@ -128,7 +128,8 @@ export default @observer class EditServiceForm extends Component { isSaving: PropTypes.bool.isRequired, isDeleting: PropTypes.bool.isRequired, isProxyFeatureEnabled: PropTypes.bool.isRequired, - isProxyFeaturePremiumFeature: PropTypes.bool.isRequired, + isProxyPremiumFeature: PropTypes.bool.isRequired, + isSpellcheckerPremiumFeature: PropTypes.bool.isRequired, }; static defaultProps = { @@ -191,7 +192,8 @@ export default @observer class EditServiceForm extends Component { isDeleting, onDelete, isProxyFeatureEnabled, - isProxyFeaturePremiumFeature, + isProxyPremiumFeature, + isSpellcheckerPremiumFeature, } = this.props; const { intl } = this.context; @@ -339,14 +341,14 @@ export default @observer class EditServiceForm extends Component { - +