diff --git a/electron/Window.vue b/electron/Window.vue
index c18f52d..9a28008 100644
--- a/electron/Window.vue
+++ b/electron/Window.vue
@@ -35,6 +35,7 @@
 
 <script lang="ts">
     import Sortable = require('sortablejs'); //tslint:disable-line:no-require-imports
+    import * as _ from 'lodash';
 
     import {Component, Hook} from '@f-list/vue-ts';
     import * as electron from 'electron';
@@ -44,6 +45,7 @@
     import Vue from 'vue';
     import l from '../chat/localize';
     import {GeneralSettings} from './common';
+    import { getSafeLanguages } from './language';
 
     const browserWindow = electron.remote.getCurrentWindow();
 
@@ -87,15 +89,26 @@
             // top bar devtools
             // browserWindow.webContents.openDevTools({ mode: 'detach' });
 
+            browserWindow.webContents.session.setSpellCheckerLanguages(getSafeLanguages(this.settings.spellcheckLang));
+
             await this.addTab();
 
-            electron.ipcRenderer.on('settings', (_: Event, settings: GeneralSettings) => this.settings = settings);
-            electron.ipcRenderer.on('allow-new-tabs', (_: Event, allow: boolean) => this.canOpenTab = allow);
+            electron.ipcRenderer.on('settings', (_e: Event, settings: GeneralSettings) => this.settings = settings);
+            electron.ipcRenderer.on('allow-new-tabs', (_e: Event, allow: boolean) => this.canOpenTab = allow);
             electron.ipcRenderer.on('open-tab', () => this.addTab());
-            electron.ipcRenderer.on('update-available', (_: Event, available: boolean) => this.hasUpdate = available);
+            electron.ipcRenderer.on('update-available', (_e: Event, available: boolean) => this.hasUpdate = available);
             electron.ipcRenderer.on('fix-logs', () => this.activeTab!.view.webContents.send('fix-logs'));
             electron.ipcRenderer.on('quit', () => this.destroyAllTabs());
-            electron.ipcRenderer.on('connect', (_: Event, id: number, name: string) => {
+
+            electron.ipcRenderer.on('update-dictionaries', (_e: Event, langs: string[]) => {
+                browserWindow.webContents.session.setSpellCheckerLanguages(langs);
+
+                for (const t of this.tabs) {
+                    t.view.webContents.session.setSpellCheckerLanguages(langs);
+                }
+            });
+
+            electron.ipcRenderer.on('connect', (_e: Event, id: number, name: string) => {
                 const tab = this.tabMap[id];
                 tab.user = name;
                 tab.tray.setToolTip(`${l('title')} - ${tab.user}`);
@@ -103,7 +116,7 @@
                 menu.unshift({label: tab.user, enabled: false}, {type: 'separator'});
                 tab.tray.setContextMenu(electron.remote.Menu.buildFromTemplate(menu));
             });
-            electron.ipcRenderer.on('disconnect', (_: Event, id: number) => {
+            electron.ipcRenderer.on('disconnect', (_e: Event, id: number) => {
                 const tab = this.tabMap[id];
                 if(tab.hasNew) {
                     tab.hasNew = false;
@@ -113,18 +126,18 @@
                 tab.tray.setToolTip(l('title'));
                 tab.tray.setContextMenu(electron.remote.Menu.buildFromTemplate(this.createTrayMenu(tab)));
             });
-            electron.ipcRenderer.on('has-new', (_: Event, id: number, hasNew: boolean) => {
+            electron.ipcRenderer.on('has-new', (_e: Event, id: number, hasNew: boolean) => {
                 const tab = this.tabMap[id];
                 tab.hasNew = hasNew;
                 electron.ipcRenderer.send('has-new', this.tabs.reduce((cur, t) => cur || t.hasNew, false));
             });
             browserWindow.on('maximize', () => this.isMaximized = true);
             browserWindow.on('unmaximize', () => this.isMaximized = false);
-            electron.ipcRenderer.on('switch-tab', (_: Event) => {
+            electron.ipcRenderer.on('switch-tab', (_e: Event) => {
                 const index = this.tabs.indexOf(this.activeTab!);
                 this.show(this.tabs[index + 1 === this.tabs.length ? 0 : index + 1]);
             });
-            electron.ipcRenderer.on('show-tab', (_: Event, id: number) => {
+            electron.ipcRenderer.on('show-tab', (_e: Event, id: number) => {
                 this.show(this.tabMap[id]);
             });
             document.addEventListener('click', () => this.activeTab!.view.webContents.focus());
@@ -195,12 +208,14 @@
             if(this.lockTab) return;
             const tray = new electron.remote.Tray(trayIcon);
             tray.setToolTip(l('title'));
-            tray.on('click', (_) => this.trayClicked(tab));
+            tray.on('click', (_e) => this.trayClicked(tab));
             const view = new electron.remote.BrowserView({webPreferences: {webviewTag: true, nodeIntegration: true, spellcheck: true}});
 
             // tab devtools
             // view.webContents.openDevTools();
 
+            view.webContents.session.setSpellCheckerLanguages(getSafeLanguages(this.settings.spellcheckLang));
+
             view.setAutoResize({width: true, height: true});
             electron.ipcRenderer.send('tab-added', view.webContents.id);
             const tab = {active: false, view, user: undefined, hasNew: false, tray};
diff --git a/electron/chat.ts b/electron/chat.ts
index 6e1a65a..0d34286 100644
--- a/electron/chat.ts
+++ b/electron/chat.ts
@@ -161,17 +161,17 @@ webContents.on('context-menu', (_, props) => {
             click: () => electron.clipboard.writeText(props.selectionText)
         });
     if(props.misspelledWord !== '') {
-        // const corrections = spellchecker.getCorrectionsForMisspelling(props.misspelledWord);
-        // menuTemplate.unshift({
-        //     label: l('spellchecker.add'),
-        //     click: () => electron.ipcRenderer.send('dictionary-add', props.misspelledWord)
-        // }, {type: 'separator'});
-        // if(corrections.length > 0)
-        //     menuTemplate.unshift(...corrections.map((correction: string) => ({
-        //         label: correction,
-        //         click: () => webContents.replaceMisspelling(correction)
-        //     })));
-        // else menuTemplate.unshift({enabled: false, label: l('spellchecker.noCorrections')});
+        const corrections = props.dictionarySuggestions; //spellchecker.getCorrectionsForMisspelling(props.misspelledWord);
+        menuTemplate.unshift({
+            label: l('spellchecker.add'),
+            click: () => electron.ipcRenderer.send('dictionary-add', props.misspelledWord)
+        }, {type: 'separator'});
+        if(corrections.length > 0)
+            menuTemplate.unshift(...corrections.map((correction: string) => ({
+                label: correction,
+                click: () => webContents.replaceMisspelling(correction)
+            })));
+        else menuTemplate.unshift({enabled: false, label: l('spellchecker.noCorrections')});
     } else if(settings.customDictionary.indexOf(props.selectionText) !== -1)
         menuTemplate.unshift({
             label: l('spellchecker.remove'),
diff --git a/electron/common.ts b/electron/common.ts
index 978082b..733754d 100644
--- a/electron/common.ts
+++ b/electron/common.ts
@@ -9,7 +9,7 @@ export class GeneralSettings {
     profileViewer = true;
     host = defaultHost;
     logDirectory = path.join(electron.app.getPath('userData'), 'data');
-    spellcheckLang: string | undefined = 'en_GB';
+    spellcheckLang: string[] | string | undefined = 'en_GB';
     theme = 'default';
     version = electron.app.getVersion();
     beta = false;
@@ -24,4 +24,4 @@ export function nativeRequire<T>(module: string): T {
     return Module.prototype.require.call({paths: Module._nodeModulePaths(__dirname)}, module);
 }
 
-//tslint:enable
\ No newline at end of file
+//tslint:enable
diff --git a/electron/dictionaries.ts b/electron/dictionaries.ts
index a309018..a2ccf10 100644
--- a/electron/dictionaries.ts
+++ b/electron/dictionaries.ts
@@ -4,6 +4,7 @@ import log from 'electron-log';  //tslint:disable-line:match-default-export-name
 import * as fs from 'fs';
 import * as path from 'path';
 import {promisify} from 'util';
+import * as _ from 'lodash';
 
 const dictDir = path.join(electron.app.getPath('userData'), 'spellchecker');
 fs.mkdirSync(dictDir, {recursive: true});
@@ -46,4 +47,4 @@ export async function ensureDictionary(lang: string): Promise<void> {
     }
     await ensure('aff');
     await ensure('dic');
-}
\ No newline at end of file
+}
diff --git a/electron/language.ts b/electron/language.ts
new file mode 100644
index 0000000..546793d
--- /dev/null
+++ b/electron/language.ts
@@ -0,0 +1,67 @@
+import * as _ from 'lodash';
+
+
+export function getSafeLanguages(langs: string | string[] | undefined): string[] {
+    return langs ? _.castArray(langs) : [];
+}
+
+
+export const knownLanguageNames = {
+    af: 'Afrikaans',
+    bg: 'Bulgarian',
+    ca: 'Catalan',
+    cs: 'Czech',
+    cy: 'Welsh',
+    da: 'Danish',
+    de: 'German',
+    el: 'Greek',
+
+    'en-AU': 'English, Australian',
+    'en-CA': 'English, Canadian',
+    'en-GB': 'English, British',
+    'en-US': 'English, American',
+
+    es: 'Spanish',
+    'es-419': 'Spanish, Latin America and Caribbean',
+    'es-AR': 'Spanish, Argentine',
+    'es-ES': 'Spanish, Castilian',
+    'es-MX': 'Spanish, Mexican',
+    'es-US': 'Spanish, American',
+
+    et: 'Estonian',
+    fa: 'Persian',
+    fi: 'Finnish',
+    fo: 'Faroese',
+    fr: 'French',
+    he: 'Hebrew',
+    hi: 'Hindi',
+    hr: 'Croatian',
+    hu: 'Hungarian',
+    hy: 'Armenian',
+    id: 'Indonesian',
+    it: 'Italian',
+    ko: 'Korean',
+    lt: 'Lithuanian',
+    lv: 'Latvian',
+    nb: 'Norwegian',
+    nl: 'Dutch',
+    pl: 'Polish',
+
+    'pt-BR': 'Portuguese, Brazilian',
+    'pt-PT': 'Portuguese, European',
+
+    ro: 'Romanian',
+    ru: 'Russian',
+    sh: 'Serbo-Croatian',
+    sk: 'Slovak',
+    sl: 'Slovenian',
+    sq: 'Albanian',
+    sr: 'Serbian',
+    sv: 'Swedish',
+    ta: 'Tamil',
+    tg: 'Tajik',
+    tr: 'Turkish',
+    uk: 'Ukranian',
+    vi: 'Vietnamese'
+};
+
diff --git a/electron/main.ts b/electron/main.ts
index 76fe371..9278796 100644
--- a/electron/main.ts
+++ b/electron/main.ts
@@ -41,13 +41,14 @@ import * as path from 'path';
 // import * as url from 'url';
 import l from '../chat/localize';
 import {defaultHost, GeneralSettings} from './common';
-import {ensureDictionary, getAvailableDictionaries} from './dictionaries';
+import { getSafeLanguages, knownLanguageNames } from './language';
 import * as windowState from './window_state';
 import BrowserWindow = Electron.BrowserWindow;
 import MenuItem = Electron.MenuItem;
 import { ElectronBlocker } from '@cliqz/adblocker-electron';
 import fetch from 'node-fetch';
 import MenuItemConstructorOptions = Electron.MenuItemConstructorOptions;
+import * as _ from 'lodash';
 
 // Module to control application life.
 const app = electron.app;
@@ -80,10 +81,46 @@ if(!settings.hwAcceleration) {
     app.disableHardwareAcceleration();
 }
 
-async function setDictionary(lang: string | undefined): Promise<void> {
-    if(lang !== undefined) await ensureDictionary(lang);
-    settings.spellcheckLang = lang;
+// async function setDictionary(lang: string | undefined): Promise<void> {
+//     if(lang !== undefined) await ensureDictionary(lang);
+//     settings.spellcheckLang = lang;
+//     setGeneralSettings(settings);
+// }
+
+
+export function updateSpellCheckerLanguages(langs: string[]): void {
+    // console.log('Language support:', langs);
+
+    for (const w of windows) {
+        // console.log('LANG SEND');
+        w.webContents.send('update-dictionaries', langs);
+    }
+
+    electron.session.defaultSession.setSpellCheckerLanguages(langs);
+}
+
+
+async function toggleDictionary(lang: string): Promise<void> {
+    const activeLangs = getSafeLanguages(settings.spellcheckLang);
+
+    // console.log('INITIAL LANG', activeLangs, lang);
+
+    let newLangs: string[] = [];
+
+    if (_.indexOf(activeLangs, lang) >= 0) {
+        newLangs = _.reject(activeLangs, (al) => (al === lang));
+    } else {
+        activeLangs.push(lang);
+        newLangs = activeLangs;
+    }
+
+    settings.spellcheckLang = newLangs;
+
     setGeneralSettings(settings);
+
+    // console.log('NEW LANG', newLangs);
+
+    updateSpellCheckerLanguages(newLangs);
 }
 
 function setGeneralSettings(value: GeneralSettings): void {
@@ -93,20 +130,23 @@ function setGeneralSettings(value: GeneralSettings): void {
 }
 
 async function addSpellcheckerItems(menu: Electron.Menu): Promise<void> {
-    if(settings.spellcheckLang !== undefined) await ensureDictionary(settings.spellcheckLang);
-    const dictionaries = await getAvailableDictionaries();
-    const selected = settings.spellcheckLang;
-    menu.append(new electron.MenuItem({
-        type: 'radio',
-        label: l('settings.spellcheck.disabled'),
-        click: async() => setDictionary(undefined)
-    }));
-    for(const lang of dictionaries)
+    const selected = getSafeLanguages(settings.spellcheckLang);
+    const langs = electron.session.defaultSession.availableSpellCheckerLanguages;
+
+    const sortedLangs = _.sortBy(
+        _.map(
+            langs,
+            (lang) => ({lang, name: (lang in knownLanguageNames) ? `${(knownLanguageNames as any)[lang]} (${lang})` : lang})
+        ),
+        'name'
+    );
+
+    for (const lang of sortedLangs)
         menu.append(new electron.MenuItem({
-            type: 'radio',
-            label: lang,
-            checked: lang === selected,
-            click: async() => setDictionary(lang)
+            type: 'checkbox',
+            label: lang.name,
+            checked: (_.indexOf(selected, lang.lang) >= 0),
+            click: async() => toggleDictionary(lang.lang)
         }));
 }
 
@@ -140,6 +180,9 @@ function createWindow(): Electron.BrowserWindow | undefined {
     const window = new electron.BrowserWindow(windowProperties);
     windows.push(window);
 
+    const safeLanguages = settings.spellcheckLang ? _.castArray(settings.spellcheckLang) : [];
+    electron.session.defaultSession.setSpellCheckerLanguages(safeLanguages);
+
     // tslint:disable-next-line:no-floating-promises
     ElectronBlocker.fromLists(
         fetch,
@@ -160,31 +203,31 @@ function createWindow(): Electron.BrowserWindow | undefined {
         (blocker) => {
             blocker.enableBlockingInSession(electron.session.defaultSession);
 
-            // console.log('Got this far!!!!');
-
-            blocker.on('request-blocked', (request: Request) => {
-                console.log('blocked', request.url);
-            });
-
-            blocker.on('request-redirected', (request: Request) => {
-                console.log('redirected', request.url);
-            });
-
-            blocker.on('request-whitelisted', (request: Request) => {
-                console.log('whitelisted', request.url);
-            });
-
-            blocker.on('csp-injected', (request: Request) => {
-                console.log('csp', request.url);
-            });
-
-            blocker.on('script-injected', (script: string, url: string) => {
-                console.log('script', script.length, url);
-            });
-
-            blocker.on('style-injected', (style: string, url: string) => {
-                console.log('style', style.length, url);
-            });
+            // // console.log('Got this far!!!!');
+            //
+            // blocker.on('request-blocked', (request: Request) => {
+            //     console.log('blocked', request.url);
+            // });
+            //
+            // blocker.on('request-redirected', (request: Request) => {
+            //     console.log('redirected', request.url);
+            // });
+            //
+            // blocker.on('request-whitelisted', (request: Request) => {
+            //     console.log('whitelisted', request.url);
+            // });
+            //
+            // blocker.on('csp-injected', (request: Request) => {
+            //     console.log('csp', request.url);
+            // });
+            //
+            // blocker.on('script-injected', (script: string, url: string) => {
+            //     console.log('script', script.length, url);
+            // });
+            //
+            // blocker.on('style-injected', (style: string, url: string) => {
+            //     console.log('style', style.length, url);
+            // });
         }
       );
 
@@ -302,14 +345,14 @@ function onReady(): void {
                 {label: l('action.newWindow'), click: createWindow, accelerator: 'CmdOrCtrl+n'},
                 {
                     label: l('action.newTab'),
-                    click: (_: Electron.MenuItem, w: Electron.BrowserWindow) => {
+                    click: (_m: Electron.MenuItem, w: Electron.BrowserWindow) => {
                         if(tabCount < 3) w.webContents.send('open-tab');
                     },
                     accelerator: 'CmdOrCtrl+t'
                 },
                 {
                     label: l('settings.logDir'),
-                    click: (_, window: BrowserWindow) => {
+                    click: (_m, window: BrowserWindow) => {
                         const dir = electron.dialog.showOpenDialogSync(
                             {defaultPath: settings.logDirectory, properties: ['openDirectory']});
                         if(dir !== undefined) {
@@ -367,14 +410,14 @@ function onReady(): void {
                     }
                 }, {
                     label: l('fixLogs.action'),
-                    click: (_, window: BrowserWindow) => window.webContents.send('fix-logs')
+                    click: (_m, window: BrowserWindow) => window.webContents.send('fix-logs')
                 },
                 {type: 'separator'},
                 {role: 'minimize'},
                 {
                     accelerator: process.platform === 'darwin' ? 'Cmd+Q' : undefined,
                     label: l('action.quit'),
-                    click(_: Electron.MenuItem, window: Electron.BrowserWindow): void {
+                    click(_m: Electron.MenuItem, window: Electron.BrowserWindow): void {
                         if(characters.length === 0) return app.quit();
                         const button = electron.dialog.showMessageBoxSync(window, {
                             message: l('chat.confirmLeave'),
@@ -426,7 +469,7 @@ function onReady(): void {
             ]
         }
     ]));
-    electron.ipcMain.on('tab-added', (_: Event, id: number) => {
+    electron.ipcMain.on('tab-added', (_event: Event, id: number) => {
         const webContents = electron.webContents.fromId(id);
         setUpWebContents(webContents);
         ++tabCount;
@@ -437,7 +480,7 @@ function onReady(): void {
         --tabCount;
         for(const w of windows) w.webContents.send('allow-new-tabs', true);
     });
-    electron.ipcMain.on('save-login', (_: Event, account: string, host: string) => {
+    electron.ipcMain.on('save-login', (_event: Event, account: string, host: string) => {
         settings.account = account;
         settings.host = host;
         setGeneralSettings(settings);
@@ -447,16 +490,17 @@ function onReady(): void {
         characters.push(character);
         e.returnValue = true;
     });
-    electron.ipcMain.on('dictionary-add', (_: Event, word: string) => {
-        if(settings.customDictionary.indexOf(word) !== -1) return;
-        settings.customDictionary.push(word);
-        setGeneralSettings(settings);
+    electron.ipcMain.on('dictionary-add', (_event: Event, word: string) => {
+        // if(settings.customDictionary.indexOf(word) !== -1) return;
+        // settings.customDictionary.push(word);
+        // setGeneralSettings(settings);
+        for(const w of windows) w.webContents.session.addWordToSpellCheckerDictionary(word);
     });
-    electron.ipcMain.on('dictionary-remove', (_: Event, word: string) => {
-        settings.customDictionary.splice(settings.customDictionary.indexOf(word), 1);
-        setGeneralSettings(settings);
+    electron.ipcMain.on('dictionary-remove', (_event: Event /*, word: string*/) => {
+        // settings.customDictionary.splice(settings.customDictionary.indexOf(word), 1);
+        // setGeneralSettings(settings);
     });
-    electron.ipcMain.on('disconnect', (_: Event, character: string) => {
+    electron.ipcMain.on('disconnect', (_event: Event, character: string) => {
         const index = characters.indexOf(character);
         if(index !== -1) characters.splice(index, 1);
     });
diff --git a/readme.md b/readme.md
index 06f5bec..9172e82 100644
--- a/readme.md
+++ b/readme.md
@@ -20,12 +20,13 @@ This repository contains a heavily customized version of the mainline F-Chat 3.0
 *   Ad auto-posting
     *    Manage channel ad settings via "Tab Settings"
     *    Automatically re-post ads every 11-18 minutes (randomized) for up to 180 minutes
-    *    Rotate multiple ads on a single channel by entering multiple ads in "Tab Settings"
+    *    Rotate multiple ads on a single channel by entering multiple ads in "Ad Settings"
 *   Ad ratings
-    *    LFP ads are automatically rated and matched against your profile
+    *    LFP ads are automatically rated (great/good/maybe/no) and matched against your profile
 *   Link previews
     *    Hover cursor over any `[url]` to see a preview of it
     *    Middle click any `[url]` to turn the preview into a sticky / interactive mode
+    *    Link preview has an ad-blocker to minimize page load times and protect against unfriendly scripts 
 *   Profile
     *    Kinks are auto-compared when viewing character profile
     *    Custom kink explanations can be expanded inline
@@ -51,6 +52,10 @@ This repository contains a heavily customized version of the mainline F-Chat 3.0
     *    Conversation dialog can be opened by typing in a character name
     *    Message search matches character names
     *    PM list shows characters' online status as a colored icon
+*   Details for Nerds
+    *    Upgraded to Electron 8.x
+    *    Replaced node-spellchecker with the built-in spellchecker of Electron 8
+    *    Multi-language support for spell checking (Windows only – language support is fully automatic on MacOS) 
 
 
 ## How to Set Up Ads