Emacs, Linux and international keyboard layouts

You can set input method (kudos go to kindahero) by typing

M-x set-input-method RET cyrillic-yawerty RET

or

M-x set-input-method RET cyrillic-jcuken RET

To store it permanently, add

(setq default-input-method "cyrillic-yawerty")

to ~/.emacs config (and use C-\ to switch between keyboard layouts).


I use following snippet for Cyrillic keyboard and it works fine for me:

(defun reverse-input-method (input-method)
  "Build the reverse mapping of single letters from INPUT-METHOD."
  (interactive
   (list (read-input-method-name "Use input method (default current): ")))
  (if (and input-method (symbolp input-method))
      (setq input-method (symbol-name input-method)))
  (let ((current current-input-method)
        (modifiers '(nil (control) (meta) (control meta))))
    (when input-method
      (activate-input-method input-method))
    (when (and current-input-method quail-keyboard-layout)
      (dolist (map (cdr (quail-map)))
        (let* ((to (car map))
               (from (quail-get-translation
                      (cadr map) (char-to-string to) 1)))
          (when (and (characterp from) (characterp to))
            (dolist (mod modifiers)
              (define-key local-function-key-map
                (vector (append mod (list from)))
                (vector (append mod (list to)))))))))
    (when input-method
      (activate-input-method current))))

(reverse-input-method 'russian-computer)

Except:

The only issue I know is that recalculation of OrgTable formulas isn't working in Russian layout because it is mapped to C-c-* and * change its location.

source


Here is an alternative solution that uses the OS language, based on syndikat's answer.

Some key translations are missing, but it should be easy to add them.

;; USAGE:
;; Put in your .emacs:
;; 
;; (translate-keystrokes-ru->en)
;; (add-hook 'text-mode-hook
;;           (lambda () (literal-insert-mode 1)))
;; 
;; Only buffers with literal-insert-mode active will be sensitive to the
;; environment language. Prefixed keybindings will still be usable.

(defun translate-keystrokes-ru->en ()
  "Make emacs output english characters, regardless whether
the OS keyboard is english or russian"
  (flet ((make-key-stroke (prefix char)
           (eval `(kbd ,(if (and (string-match "^C-" prefix)
                                 (string-match "[A-Z]" (string char)))
                            (concat "S-" prefix (string (downcase char)))
                            (concat prefix (string char)))))))
    (let ((case-fold-search nil)
          (keys-pairs (mapcar* 'cons
                               "йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖ\ЭЯЧСМИТЬБЮ№"
                               "qwertyuiop[]asdfghjkl;'zxcvbnm,.QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>#"))
          (prefixes '(""    "s-"    "M-"    "M-s-"
                      "C-"  "C-s-"  "C-M-"  "C-M-s-")))
      (mapc (lambda (prefix)
              (mapc (lambda (pair)
                      (define-key key-translation-map
                          (make-key-stroke prefix (car pair))
                        (make-key-stroke prefix (cdr pair))))
                    keys-pairs))
            prefixes))))

(defun literal-insert ()
  (interactive)
  (insert-char last-input-event 1))

(define-minor-mode literal-insert-mode
    "Make emacs output characters corresponging to the OS keyboard,
 ignoring the key-translation-map"
  :keymap (let ((new-map (make-sparse-keymap))
                (english-chars "qwertyuiop[]asdfghjkl;'zxcvbnm,.QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>#"))
            (mapc (lambda (char)
                    (define-key new-map (string char)
                      'literal-insert))
                  english-chars)
            new-map))

Not sure, where did sabof got 150 billion. I ran this code (thanks to Yuri Khan, taken from EmacsWiki):

(loop
 for from across "йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖ\ЭЯЧСМИТЬБЮ№"
 for to   across "qwertyuiop[]asdfghjkl;'zxcvbnm,.QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>#"
 do
 (eval `(define-key key-translation-map (kbd ,(concat "C-" (string from))) (kbd ,(concat     "C-" (string to)))))
 (eval `(define-key key-translation-map (kbd ,(concat "M-" (string from))) (kbd ,(concat     "M-" (string to))))))

It's only 128 combinations. Unfortunately, combinations with single letters like C-x b don't work. I'm still trying to find a better solution.