Subject: bug#13460: Issue to change dictionary when using hunspell on emacs

From: Agustin Martin <[email-masked]>
Date: Fri, 18 Jan 2013 18:05:01 +0100

On Thu, Jan 17, 2013 at 08:30:29PM +0100, Agustin Martin wrote:
> From: Jochen Schmitt
> > 
> > I have try to create a suggestion for a general solution for
> > this issue in the next release of emacs.
> > 
> > I have attached a patch on this mail which introduced a alist to
> > translate the dictionary names like 'english' in the form which will
> > be accepted by hunspell.
> > 
> > I have done a first short test to check out, that this is a
> > working solution.
> >  
> > Of course the ispell-hunspell-dictionary-alist need extension because 
> > I have put only two entries to be able to check out my solution.
> 
> Hi Jochen. Thanks a lot for your feedback (and to Glenn for forwarding it),
> you can send your followups to the bug address.
> 
> I remember to have done some initial work with an alias file for hunspell,
> but I do not find that now.
> 
> I'd keep the name `ispell-hunspell-dictionary-alist' for the alist of
> actually found dicts, once implemented in one way or another. I vaguely
> remember using something like `ispell-hunspell-dictionary-equivs-alist' for
> the purpose of having a list of equivalences. I'd also not hardcode nil to
> "en_GB".
> 
> For the rest I think it can be useful as a temporary workaround, but I'd
> prefer to see these changes in a sanitized dictionary alist for hunspell,
> something similar to what is done in `ispell-set-spellchecker-params' to use
> [:alpha:] when possible, but for this purpose and limited to the original
> base alist. Otherwise will only work for entries not using explicit "-d"
> and may hide personal choices in ~/.emacs pointing to non-standard locations
> (e.g., "american" using "~/personal/en_US". (Looked quickly, may be I missed
> something)
> 
> Let me try to find where I have my previous work and what is harder, try to
> find the time. This should not be that time consuming, so I expect to look
> at this shortly.

I have been playing with this. Please see attached patch for current status.
There are a couple of minor things I would like to think about first.

Current changes explicitly set "english" to one of the two main choices
("en_GB"). This  is not something I like very much and I am aware that
people is sensitive about this. I'd prefer to associate it with plain "en",
but hunspell has some pending issues regarding fallback values.

Since there should be mapppings for all (but nil) default dict definitions, 
and this is only done for those dicts I am also considering to show an error
if an expected mappping is not found, but this is a really minor internal
issue just to help finding missing mappings early.

I will test these changes a bit more and if no problems appear will commit
early next week. Feedback is welcome.

Thanks again for your suggestions.

-- 
Agustin
--- ispell.el.orig	2013-01-18 15:35:17.804804007 +0100
+++ ispell.el	2013-01-18 18:03:01.017847901 +0100
@@ -773,6 +773,41 @@
 (make-obsolete-variable 'ispell-aspell-supports-utf8
                         'ispell-encoding8-command "23.1")
 
+(defvar ispell-hunspell-dictionary-equivs-alist
+  '(("american"      "en_US")
+    ("brasileiro"    "pt_BR")
+    ("british"       "en_GB")
+    ("castellano"    "es_ES")
+    ("castellano8"   "es_ES")
+    ("czech"         "cs_CZ")
+    ("dansk"         "da_DK")
+    ("deutsch"       "de_DE")
+    ("deutsch8"      "de_DE")
+    ("english"       "en_GB")
+    ("esperanto"     "eo")
+    ("esperanto-tex" "eo")
+    ("finnish"       "fi_FI")
+    ("francais7"     "fr_FR")
+    ("francais"      "fr_FR")
+    ("francais-tex"  "fr_FR")
+    ("german"        "de_DE")
+    ("german8"       "de_DE")
+    ("italiano"      "it_IT")
+    ("nederlands"    "nl_NL")
+    ("nederlands8"   "nl_NL")
+    ("norsk"         "nn_NO")
+    ("norsk7-tex"    "nn_NO")
+    ("polish"        "pl_PL")
+    ("portugues"     "pt_PT")
+    ("russian"       "ru_RU")
+    ("russianw"      "ru_RU")
+    ("slovak"        "sk_SK")
+    ("slovenian"     "sl_SI")
+    ("svenska"       "sv_SE")
+    ("hebrew"        "he_IL"))
+  "Alist with matching hunspell dict names for standard dict names in
+  `ispell-dictionary-base-alist'.")
+
 (defvar ispell-emacs-alpha-regexp
   (if (string-match "^[[:alpha:]]+$" "abcde")
       "[[:alpha:]]"
@@ -1134,9 +1169,52 @@
 		    ispell-encoding8-command)
 	       ispell-aspell-dictionary-alist
 	     nil))
+	  (ispell-dictionary-base-alist ispell-dictionary-base-alist)
 	  ispell-base-dicts-override-alist ; Override only base-dicts-alist
 	  all-dicts-alist)
 
+      ;; While ispell and aspell (through aliases) use the traditional
+      ;; dict naming originally expected by ispell.el, hunspell
+      ;; uses locale based names with no alias.  We need to map
+      ;; standard names to locale based names to make default dict
+      ;; definitions available for hunspell.
+      (if ispell-really-hunspell
+	  (let (tmp-dicts-alist)
+	    (dolist (adict ispell-dictionary-base-alist)
+	      (let* ((dict-name (nth 0 adict))
+		     (ispell-args (nth 5 adict))
+		     (ispell-args-has-d (member "-d" ispell-args)))
+		;; Remove "-d" option from `ispell-args' if present
+		(if ispell-args-has-d
+		    (let ((ispell-args-after-d
+			   (cdr (cdr ispell-args-has-d)))
+			  (ispell-args-before-d
+			   (butlast ispell-args (length ispell-args-has-d))))
+		      (setq ispell-args
+			    (nconc ispell-args-before-d
+				   ispell-args-after-d))))
+		;; Unless default dict, re-add "-d" option with the mapped value
+		(if dict-name
+		    (nconc ispell-args
+			   (list "-d"
+				 (or (cadr (assoc
+					    dict-name
+					    ispell-hunspell-dictionary-equivs-alist))
+				     dict-name))))
+
+		(add-to-list 'tmp-dicts-alist
+			     (list
+			      dict-name      ; dict name
+			      (nth 1 adict)  ; casechars
+			      (nth 2 adict)  ; not-casechars
+			      (nth 3 adict)  ; otherchars
+			      (nth 4 adict)  ; many-otherchars-p
+			      ispell-args    ; ispell-args
+			      (nth 6 adict)  ; extended-character-mode
+			      (nth 7 adict)  ; dict encoding
+			      )))
+	      (setq ispell-dictionary-base-alist tmp-dicts-alist))))
+
       (run-hooks 'ispell-initialize-spellchecker-hook)
 
       ;; Add dicts to ``ispell-dictionary-alist'' unless already present.