Alexei
Alexei

Reputation: 15716

Emacs. Spell check "on fly" for 2 languages

Windows 7, Emacs 25.1

I need to spell check "on fly" for my custom text (e.g. to emphasize the incorrect words). But I write text in two languages: English and Russian. And I want easy to switch between spell checking for 2 languages.

What is the best emacs package for this? Thanks.

Upvotes: 7

Views: 2602

Answers (2)

Rick-Hunter
Rick-Hunter

Reputation: 21

I had a similar problem, the solution I found manages two or more languages at the same time without using guess_language package. This solution is based on Hunspell spelling checker.

SYSTEM: Windows 7 SP1, GNU Emacs 26.1

First, perform a Ispell/Hunspell configuration after Hunspell installation. Insert the next code in the .emacs file, usually located within C:/Users/Account.

;; START BLOCK1 <-- Ispell/Hunspell setting
;;                          e.g., "C:/Hunspell/bin/hunspell.exe"
(setq-default ispell-program-name "hunspell.exe FULL PATH")
(setq-default ispell-extra-args  '("--sug-mode=ultra"))
;; Set "DICTDIR" variable, e.g., "C:/Hunspell/share/hunspell"
(setenv "DICTDIR" "hunspell DICTIONARY PATH")
;; Uncomment next line to set English or another dictionary
;; (setq ispell-dictionary "en_US")

;; Automatically enable flyspell-mode in text-mode
(setq text-mode-hook '(lambda() (flyspell-mode t) ))

(require 'ispell)
;; END BLOCK1 <-- Ispell/Hunspell setting

This code is based on the spelling configuration section of another discussion, see M Parashar - Load Theme. The block code 1 works for the default dictionary, which can be changed uncommenting the line with the ispell-dictionary variable. This code works perfectly for me.

The second code block enable us to use multiple dictionaries, is based on AM Lafon - Multi Spell Checking. For me, this code block works only next of code block 1.

;;START BLOCK2<-- Multiple dictionaries. Only works with BLOCK1
(with-eval-after-load "ispell"
  ;; Configure `LANG`, otherwise ispell.el cannot find a 'default
  ;; dictionary' even though multiple dictionaries will be configured
  ;; in next line.
  (setenv "LANG" "es_ES")
  ;; English/spanish configuration.
  (setq ispell-dictionary "en_US,es_ES")
  ;; ispell-set-spellchecker-params has to be called
  ;; before ispell-hunspell-add-multi-dic will work
  (ispell-set-spellchecker-params)
  (ispell-hunspell-add-multi-dic "en_US,es_ES")
  ;; For saving words to the personal dictionary, don't infer it from
  ;; the locale, otherwise it would save to ~/.hunspell_de_DE.
  (setq ispell-personal-dictionary "~/.hunspell_personal"))
;; The personal dictionary file has to exist, otherwise hunspell will
;; silently not use it.
(unless (file-exists-p ispell-personal-dictionary)
  (write-region "" nil ispell-personal-dictionary nil 0))
;;END BLOCK2<-- Multiple dictionaries. Only works with BLOCK1

These two code blocks enable the spell checking for the english/spanish languages at the same time. More languages can be added to the checking system expanding the "en_US,es_ES" strings with the appropriate dictionary names. I used that ones located in the Share/Hunspell directory. There is no keybinding to change between languages and no per file dictionary assignation at the beginning of files, like this:

# -\*- ispell-dictionary: "castellano8" -\*-. 

A context menu is displayed when clicking the middle mouse button over the misspelled word, an option is the Save Word entry. These words will be saved using the variable ispell-personal-dictionary in the new file called .hunspell_personal, located on the usual path.

The inclusion of the two code blocks gave the expected results. Just including the second block of code threw the error 'wrong-type-argument stringp nil'.

Upvotes: 2

SerialDev
SerialDev

Reputation: 2847

You want this: guess_language.el

(use-package guess-language         ; Automatically detect language for Flyspell
  :ensure t
  :defer t
  :init (add-hook 'text-mode-hook #'guess-language-mode)
  :config
  (setq guess-language-langcodes '((en . ("en_GB" "English"))
                                   (it . ("it_IT" "Italian")))
        guess-language-languages '(en it)
        guess-language-min-paragraph-length 45)
  :diminish guess-language-mode)

Alternatively if you just want to cycle through them:

(defvar mu-languages-ring nil "Languages ring for Ispell")

(let ((languages '("en_GB" "it_IT")))
  (validate-setq mu-languages-ring (make-ring (length languages)))
  (dolist (elem languages) (ring-insert mu-languages-ring elem)))

(defun mu-cycle-ispell-languages ()
  (interactive)
  (let ((language (ring-ref mu-languages-ring -1)))
    (ring-insert mu-languages-ring language)
    (ispell-change-dictionary language)))

These should work with FlySpell

Upvotes: 6

Related Questions