commit 054374cf4c3b8a984e5fb64aa0a9b61bdd9be314
Author: Udi Fogiel <[email protected]>
Date:   Sun Aug 2 14:20:58 2026 +0300

    keyboard maps: replace primary/secondary with per-language selection
    
    The old code auto-switched between exactly two maps based on the
    text direction unconditionally on every keystroke,
    any manual switch was silently reverted on the very next character typed.
    
    keymap-select "<name>" is a new LFUN to switch to any configured map
    by name, or back to the configured default with no argument.
    
    Fixes #4051.
---
 lib/RELEASE-NOTES                  |  28 +++++++-
 lib/bind/de/menus.bind             |   3 -
 lib/bind/menus.bind                |   3 -
 lib/bind/ru/menus.bind             |   6 --
 lib/configure.py                   |   2 +-
 lib/doc/UserGuide.lyx              |  61 +++++++++++++++-
 lib/scripts/prefs2prefs_prefs.py   |  33 ++++++++-
 src/BufferView.cpp                 |  32 +++------
 src/FuncCode.h                     |   4 +-
 src/Intl.cpp                       | 109 +++++++++++++++++-----------
 src/Intl.h                         |  61 +++++++++-------
 src/LyXAction.cpp                  |  41 +++++------
 src/LyXRC.cpp                      |  70 ++++++++++++------
 src/LyXRC.h                        |  13 ++--
 src/Trans.cpp                      |  45 +++++-------
 src/Trans.h                        |  19 +++--
 src/frontends/qt/GuiPrefs.cpp      | 139 +++++++++++++++++++++++++++++++-----
 src/frontends/qt/GuiPrefs.h        |   7 +-
 src/frontends/qt/ui/PrefInputUi.ui | 141 +++++++++++++++++++++++++++++--------
 19 files changed, 569 insertions(+), 248 deletions(-)

diff --git a/lib/RELEASE-NOTES b/lib/RELEASE-NOTES
index 672c03e531..e4b2583e45 100644
--- a/lib/RELEASE-NOTES
+++ b/lib/RELEASE-NOTES
@@ -10,8 +10,22 @@
   argument of the buffer-load-graphics lfun.
 
 
+!!Keyboard maps
+
+- The old primary/secondary keyboard map scheme has been replaced with
+  explicit per-language keyboard maps. Instead of toggling between two
+  fixed maps, a keyboard map can now be selected by name (keymap-select
+  lfun) and, optionally, chosen automatically according to the language
+  at the cursor (Preferences > Language > Keyboard).
+
+
 !!!The following pref variables were added in 2.:
 
+- \kbmap_follow_language: select the keyboard map automatically according
+  to the language at the cursor.
+
+- \kbmap_lang: assigns a keyboard map to a given language, used when
+  \kbmap_follow_language is set.
 
 
 !!!The following pref variables were changed in 2.6:
@@ -24,12 +38,21 @@
 
 !!!The following pref variables are obsoleted in 2.6:
 
+- \kbmap_secondary has been replaced by \kbmap_follow_language and
+  \kbmap_lang (see "Keyboard maps" above).
+
 !!!The following new LyX functions have been introduced in 2.6:
 
 - buffer-load-graphics: triggers preview conversion for every image in
   the current buffer at once, instead of waiting for each image to be
   scrolled into view.
 
+- keymap-select <NAME>: turns on and selects a keyboard map by name
+  (the base name of a .kmap file). If NAME is omitted, any manual
+  selection is dropped and the configured default (or, if
+  \kbmap_follow_language is set, the map for the language at the
+  cursor) is applied again.
+
 !!!The following LyX functions have been changed in 2.6:
 
 - The function newpage-insert has been renamed to textbreak-insert
@@ -37,9 +60,12 @@
 
 - The function language now accepts an additional "local" argument
   which ensures the language switch is an inline one (e.g. \foreignlanguage).
-  
+
 !!!The following LyX functions have been removed in 2.6:
 
+- keymap-primary, keymap-secondary and keymap-toggle have been removed
+  in favor of keymap-select (see above).
+
 !!!The following LyX function has been added and then removed in 2.6 
development cycle:
 
 !!!The following layout-related changes has been done in 2.6 development cycle:
diff --git a/lib/bind/de/menus.bind b/lib/bind/de/menus.bind
index a194b64f24..fff7133e7e 100644
--- a/lib/bind/de/menus.bind
+++ b/lib/bind/de/menus.bind
@@ -162,8 +162,5 @@ Format 5
 #
 # Menü Tastatur
 #
-\bind "M-t 1"                  "keymap-primary"
-\bind "M-t 2"                  "keymap-secondary"
 \bind "M-t o"                  "keymap-off"
-\bind "M-t t"                  "keymap-toggle"
 \bind "M-t x"                  "keymap-off"
diff --git a/lib/bind/menus.bind b/lib/bind/menus.bind
index ced3cd9df0..697b56d5ff 100644
--- a/lib/bind/menus.bind
+++ b/lib/bind/menus.bind
@@ -165,8 +165,5 @@ Format 5
 # Keyboard menu
 #
 
-\bind "M-k 1"                  "keymap-primary"
-\bind "M-k 2"                  "keymap-secondary"
 \bind "M-k o"                  "keymap-off"
-\bind "M-k t"                  "keymap-toggle"
 \bind "M-k x"                  "keymap-off"
diff --git a/lib/bind/ru/menus.bind b/lib/bind/ru/menus.bind
index c535abe8b5..50b1568168 100644
--- a/lib/bind/ru/menus.bind
+++ b/lib/bind/ru/menus.bind
@@ -258,14 +258,8 @@ Format 5
 # Keyboard menu
 #
 
-\bind "M-k 1"                  "keymap-primary"
-\bind "M-k 2"                  "keymap-secondary"
 \bind "M-k o"                  "keymap-off"
-\bind "M-k t"                  "keymap-toggle"
 \bind "M-k x"                  "keymap-off"
 
-\bind "M-л 1"                  "keymap-primary"
-\bind "M-л 2"                  "keymap-secondary"
 \bind "M-л щ"                  "keymap-off"
-\bind "M-л е"                  "keymap-toggle"
 \bind "M-л ч"                  "keymap-off"
diff --git a/lib/configure.py b/lib/configure.py
index c168d01ed4..5f53d135c7 100644
--- a/lib/configure.py
+++ b/lib/configure.py
@@ -2111,7 +2111,7 @@ if __name__ == '__main__':
     lyx_check_config = True
     lyx_kpsewhich = True
     outfile = 'lyxrc.defaults'
-    lyxrc_fileformat = 42
+    lyxrc_fileformat = 43
     rc_entries = ''
     lyx_keep_temps = False
     version_suffix = ''
diff --git a/lib/doc/UserGuide.lyx b/lib/doc/UserGuide.lyx
index 862210ddca..ecfd4ec5d5 100644
--- a/lib/doc/UserGuide.lyx
+++ b/lib/doc/UserGuide.lyx
@@ -186,6 +186,7 @@ logicalmkup
 \docbook_mathml_prefix 1
 \docbook_mathml_version 0
 \author -712698321 "Jürgen Spitzmüller"
+\author 673085648 "ufogiel"
 \author 1064312605 "Udi Fogiel"
 \end_header
 
@@ -43793,7 +43794,14 @@ Preferences\SpecialChar menuseparator
 Editing\SpecialChar menuseparator
 Keyboard/Mouse
 \family default
- dialog allows you to choose up to two keyboard mappings,
+ dialog 
+\change_deleted 673085648 1785137856
+allows you to choose up to two keyboard mappings
+\change_inserted 673085648 1785141903
+lets you set a default keyboard map,
+ or have LyX select one automatically according to the language of the text 
under the cursor
+\change_unchanged
+,
  see section
 \begin_inset space ~
 \end_inset
@@ -43807,7 +43815,14 @@ nolink "false"
 \end_inset
 
 .
+
+\change_deleted 673085648 1785137891
  You can choose primary and secondary keyboard languages and then select which 
one you want to use.
+
+\change_inserted 673085648 1785141829
+ 
+\change_unchanged
+
 \end_layout
 
 \begin_layout Standard
@@ -55876,14 +55891,30 @@ keyboard
 
 map
 \family default
- and select the keyboard map file named 
+ and 
+\change_deleted 673085648 1785141037
+select the keyboard map file named
+\change_inserted 673085648 1785141079
+set the 
+\family sans
+Default
+\family default
+ field to the keyboard map named
+\change_unchanged
+ 
 \shape italic
-romanian.kmap
+romanian
+\change_deleted 673085648 1785141089
+.kmap
+\change_unchanged
+
 \shape default
 .
 \end_layout
 
 \begin_layout Standard
+
+\change_deleted 673085648 1785141098
 You can specify a 
 \family sans
 First
@@ -55917,6 +55948,30 @@ arg   "keymap-toggle"
 \end_inset
 
 .
+\change_inserted 673085648 1785141671
+If you regularly work with more than one language,
+ you can instead let \SpecialChar LyX
+ select the keyboard map automatically according to the language of the text 
under the cursor:
+ enable Select keyboard map automatically by language and assign a keyboard 
map to each language you use,
+ in addition to the 
+\family sans
+Default
+\family default
+ map used for languages that don't have their own assignment.
+ You can also switch to any configured keyboard map manually at any time,
+ or turn key mapping off,
+ by binding a key of your choice to the 
+\family sans
+keymap-select
+\family default
+ and 
+\family sans
+keymap-off
+\family default
+ \SpecialChar LyX
+ functions respectively.
+\change_unchanged
+
 \end_layout
 
 \begin_layout Standard
diff --git a/lib/scripts/prefs2prefs_prefs.py b/lib/scripts/prefs2prefs_prefs.py
index 6f0ba8002d..c78fd34b90 100644
--- a/lib/scripts/prefs2prefs_prefs.py
+++ b/lib/scripts/prefs2prefs_prefs.py
@@ -186,6 +186,15 @@
 #   default is true, so this keeps behavior the same for existing
 #   users)
 
+# Incremented to format 43, by ufogiel
+#   Replace \kbmap_secondary (used for the old automatic switch between
+#   a primary and a secondary keyboard map depending on the direction
+#   of the text at the cursor) with \kbmap_follow_language and
+#   \kbmap_lang (explicit per-language keyboard-map assignment).
+#   Existing \kbmap_secondary settings are migrated to a \kbmap_lang
+#   assignment for every right-to-left language in lib/languages, with
+#   \kbmap_follow_language turned on, to approximate prior behavior.
+
 # NOTE: The format should also be updated in LYXRC.cpp and
 # in configure.py (search for lyxrc_fileformat).
 
@@ -558,6 +567,27 @@ def add_visual_cursor_default(lines):
        lines.append("\\visual_cursor false")
 
 
+# right-to-left languages defined in lib/languages (RTL true)
+rtl_languages = ("arabic_arabtex", "arabic_arabi", "farsi", "hebrew",
+                 "nko", "syriac", "urdu", "uyghur")
+
+def migrate_kbmap_secondary(lines):
+       secondary = None
+       newlines = []
+       for l in lines:
+               if l.strip().lower().startswith("\\kbmap_secondary"):
+                       entries = get_format(l)
+                       if len(entries) > 1 and entries[1]:
+                               secondary = entries[1]
+                       continue
+               newlines.append(l)
+       if secondary:
+               newlines.append("\\kbmap_follow_language true")
+               for lang in rtl_languages:
+                       newlines.append('\\kbmap_lang "%s" "%s"' % (lang, 
secondary))
+       lines[:] = newlines
+
+
 # End conversions for LyX 2.5 to 2.6
 ####################################
 
@@ -613,5 +643,6 @@ conversions = [
        [ 39, []],
     [ 40, [bookmarks_visibility]],
     [ 41, [rename_langpack]],
-       [ 42, [add_visual_cursor_default]]
+       [ 42, [add_visual_cursor_default]],
+       [ 43, [migrate_kbmap_secondary]]
 ]
diff --git a/src/BufferView.cpp b/src/BufferView.cpp
index 0cdf5d24bb..304a939c5b 100644
--- a/src/BufferView.cpp
+++ b/src/BufferView.cpp
@@ -1006,14 +1006,7 @@ bool BufferView::moveToPosition(pit_type bottom_pit, 
pos_type bottom_pos,
 
 void BufferView::translateAndInsert(char_type c, Text * t, Cursor & cur)
 {
-       if (d->cursor_.real_current_font.isRightToLeft()) {
-               if (d->intl_.keymap == Intl::PRIMARY)
-                       d->intl_.keyMapSec();
-       } else {
-               if (d->intl_.keymap == Intl::SECONDARY)
-                       d->intl_.keyMapPrim();
-       }
-
+       d->intl_.syncActiveMap(d->cursor_.real_current_font.language()->lang());
        d->intl_.getTransManager().translateAndInsert(c, t, cur);
 }
 
@@ -1308,9 +1301,7 @@ bool BufferView::getStatus(FuncRequest const & cmd, 
FuncStatus & flag)
        case LFUN_BIBTEX_DATABASE_LIST:
        case LFUN_STATISTICS:
        case LFUN_KEYMAP_OFF:
-       case LFUN_KEYMAP_PRIMARY:
-       case LFUN_KEYMAP_SECONDARY:
-       case LFUN_KEYMAP_TOGGLE:
+       case LFUN_KEYMAP_SELECT:
        case LFUN_INSET_SELECT_ALL:
        case LFUN_SERVER_GET_XY:
                flag.setEnabled(true);
@@ -2539,20 +2530,17 @@ void BufferView::dispatch(FuncRequest const & cmd, 
DispatchResult & dr)
        }
 
        case LFUN_KEYMAP_OFF:
-               getIntl().keyMapOn(false);
-               break;
-
-       case LFUN_KEYMAP_PRIMARY:
-               getIntl().keyMapPrim();
+               getIntl().deselectMap();
                break;
 
-       case LFUN_KEYMAP_SECONDARY:
-               getIntl().keyMapSec();
-               break;
-
-       case LFUN_KEYMAP_TOGGLE:
-               getIntl().toggleKeyMap();
+       case LFUN_KEYMAP_SELECT: {
+               string const name = cmd.getArg(0);
+               if (name.empty())
+                       
getIntl().selectDefault(d->cursor_.real_current_font.language()->lang());
+               else if (!getIntl().selectMap(name))
+                       message(bformat(_("Keyboard map not found: %1$s"), 
from_utf8(name)));
                break;
+       }
 
        case LFUN_DIALOG_SHOW_NEW_INSET: {
                string const name = cmd.getArg(0);
diff --git a/src/FuncCode.h b/src/FuncCode.h
index 5c3259dd68..4f78596b9c 100644
--- a/src/FuncCode.h
+++ b/src/FuncCode.h
@@ -147,10 +147,8 @@ enum FuncCode
        LFUN_NOTE_INSERT,
        LFUN_UI_TOGGLE,
        LFUN_KEYMAP_OFF,
-       LFUN_KEYMAP_PRIMARY,
-       LFUN_KEYMAP_SECONDARY,
+       LFUN_KEYMAP_SELECT,
        // 100
-       LFUN_KEYMAP_TOGGLE,
        LFUN_MATH_INSERT,
        LFUN_MATH_MATRIX,
        LFUN_MATH_LIMITS,
diff --git a/src/Intl.cpp b/src/Intl.cpp
index fdae0b1aba..85f13f879c 100644
--- a/src/Intl.cpp
+++ b/src/Intl.cpp
@@ -22,76 +22,99 @@ namespace lyx {
 
 
 Intl::Intl()
-       : keymap(Intl::PRIMARY), keymapon(lyxrc.use_kbmap),
-       prim_lang(lyxrc.primary_kbmap), sec_lang(lyxrc.secondary_kbmap)
+       : use_kbmap_(lyxrc.use_kbmap),
+         default_lang_(lyxrc.default_kbmap),
+         follow_language_(lyxrc.keymap_follow_language),
+         lang_keymaps_(lyxrc.keymap_by_language)
 {
 }
 
 
-void Intl::keyMapOn(bool on)
+bool Intl::selectMap(std::string const & name)
 {
-       keymapon = on;
-
-       if (on) {
-               if (keymap == PRIMARY)
-                       keyMapPrim();
-               else
-                       keyMapSec();
-       } else {
-               trans.disableKeymap();
+       if (name.empty()) {
+               deselectMap();
+               return true;
        }
+
+       if (trans.setActive(name) != 0)
+               return false;
+
+       active_map_ = name;
+       return true;
 }
 
 
-void Intl::toggleKeyMap()
+void Intl::deselectMap()
 {
-       if (keymapon && (keymap == PRIMARY))
-               keyMapSec();
-       else if (keymapon)
-               keyMapOn(false);
-       else
-               keyMapPrim();
+       trans.disableKeymap();
+       active_map_.erase();
 }
 
 
-void Intl::keyMapPrim()
+std::string Intl::mapForLanguage(std::string const & langcode) const
 {
-       if (!trans.setPrimary(prim_lang))
-               trans.enablePrimary();
-
-       keymapon = true;
-       keymap = PRIMARY;
+       std::map<std::string, std::string>::const_iterator it =
+               lang_keymaps_.find(langcode);
+       return it == lang_keymaps_.end() ? default_lang_ : it->second;
 }
 
 
-void Intl::keyMapSec()
+void Intl::syncActiveMap(std::string const & langcode)
 {
-       if (!trans.setSecondary(sec_lang))
-               trans.enableSecondary();
+       if (!use_kbmap_) {
+               deselectMap();
+               last_synced_.erase();
+               last_langcode_.erase();
+               return;
+       }
 
-       keymapon = true;
-       keymap = SECONDARY;
+       // a language changemust focre a resync even if it resolves to the
+       // same map name as before (e.g. two languages sharing the default)
+       bool const lang_changed = follow_language_ && langcode != 
last_langcode_;
+       last_langcode_ = langcode;
+
+       std::string const wanted =
+               follow_language_ ? mapForLanguage(langcode) : default_lang_;
+       if (!lang_changed && wanted == last_synced_)
+               return;
+
+       last_synced_ = wanted;
+       if (wanted.empty())
+               deselectMap();
+       else
+               selectMap(wanted);
 }
 
 
-void Intl::initKeyMapper(bool on)
+void Intl::selectDefault(std::string const & langcode)
 {
-       LYXERR(Debug::INIT, "Initializing key mappings...");
-
-       if (trans.setPrimary(prim_lang) == -1)
-               prim_lang.erase();
-       if (trans.setSecondary(sec_lang) == -1)
-               sec_lang.erase();
+       if (!use_kbmap_) {
+               deselectMap();
+               last_synced_.erase();
+               last_langcode_.erase();
+               return;
+       }
 
-       if (prim_lang.empty() && sec_lang.empty())
-               keymapon = false;
+       std::string const wanted =
+               follow_language_ ? mapForLanguage(langcode) : default_lang_;
+       last_synced_ = wanted;
+       last_langcode_ = langcode;
+       if (wanted.empty())
+               deselectMap();
        else
-               keymapon = on;
+               selectMap(wanted);
+}
 
-       keyMapOn(keymapon);
 
-       if (keymapon)
-               keyMapPrim();
+void Intl::initKeyMapper(bool on)
+{
+       LYXERR(Debug::INIT, "Initializing key mappings...");
+
+       if (!on || default_lang_.empty() || !selectMap(default_lang_))
+               deselectMap();
+       last_synced_ = active_map_;
+       last_langcode_.erase();
 }
 
 
diff --git a/src/Intl.h b/src/Intl.h
index 228ea0d48f..2d5487a120 100644
--- a/src/Intl.h
+++ b/src/Intl.h
@@ -17,6 +17,9 @@
 
 #include "Trans.h"
 
+#include <map>
+#include <string>
+
 
 namespace lyx {
 
@@ -26,42 +29,52 @@ namespace lyx {
  */
 class Intl {
 public:
-       /// which keymap is currently used ?
-       enum Keymap {
-               PRIMARY,
-               SECONDARY
-       };
-
        Intl();
 
-       /// {en/dis}able the keymap
-       void keyMapOn(bool on);
-
-       /// set the primary language keymap
-       void keyMapPrim();
+       /// select a keymap by name (base name of a .kmap file); false if not 
found
+       bool selectMap(std::string const & name);
 
-       /// set the secondary language keymap
-       void keyMapSec();
+       /// Turn off key mapping.
+       void deselectMap();
 
-       /// turn on/off key mappings, status in keymapon
-       void toggleKeyMap();
+       /// force-apply like syncActiveMap(); used by keymap-select with no 
argument
+       void selectDefault(std::string const & langcode);
 
        /// initialize key mapper
        void initKeyMapper(bool on);
 
+       /// is keyboard mapping enabled at all (the "Use keyboard map" 
preference)?
+       bool enabled() const { return use_kbmap_; }
+
+       /// choose the active map automatically from the language at the cursor?
+       bool followLanguage() const { return use_kbmap_ && follow_language_; }
+
+       /// configured keymap for the language, or the default; empty if 
neither is set
+       std::string mapForLanguage(std::string const & langcode) const;
+
+       /// reapply the target map only if it changed, so manual overrides stick
+       void syncActiveMap(std::string const & langcode);
+
+       /// name of the currently selected map, empty if none
+       std::string const & activeMap() const { return active_map_; }
+
        // Get the Translation Manager
        inline TransManager & getTransManager() { return trans; }
 
-       /// using primary or secondary keymap ?
-       Keymap keymap;
-
 private:
-       /// is key mapping enabled ?
-       bool keymapon;
-       /// the primary language keymap
-       std::string & prim_lang;
-       /// the secondary language keymap
-       std::string & sec_lang;
+       /// currently selected map, empty if none
+       std::string active_map_;
+       /// last synced (map, langcode); catches real changes even if the map 
repeats
+       std::string last_synced_;
+       std::string last_langcode_;
+       /// the "Use keyboard map" preference: master on/off switch
+       bool & use_kbmap_;
+       /// the default keymap, loaded at start-up if enabled
+       std::string & default_lang_;
+       /// select the active map automatically from the language at the cursor?
+       bool & follow_language_;
+       /// per-language map assignments, used when follow_language_ is set
+       std::map<std::string, std::string> & lang_keymaps_;
        /// the translation manager
        TransManager trans;
 };
diff --git a/src/LyXAction.cpp b/src/LyXAction.cpp
index 5cea911475..bd9c9df054 100644
--- a/src/LyXAction.cpp
+++ b/src/LyXAction.cpp
@@ -2422,33 +2422,26 @@ void LyXAction::init()
                { LFUN_KEYMAP_OFF, "keymap-off", ReadOnly, Edit },
 
 /*!
- * \var lyx::FuncCode lyx::LFUN_KEYMAP_PRIMARY
- * \li Action: Turn on the primary keyboard map.
+ * \var lyx::FuncCode lyx::LFUN_KEYMAP_SELECT
+ * \li Action: Turn on and select a keyboard map by name.
  * \li Notion: Maps were widely used in past, when X-windows didn't have 
nowadays
                keyboard support. They can be still used to maintain uniform 
keyboard
                layout across the various platforms.\n
-               The language is to be set in the Preferences dialog.
- * \li Syntax: keymap-primary
- * \endvar
- */
-               { LFUN_KEYMAP_PRIMARY, "keymap-primary", ReadOnly, Edit },
-
-/*!
- * \var lyx::FuncCode lyx::LFUN_KEYMAP_SECONDARY
- * \li Action: Turn on the secondary keyboard map.
- * \li Syntax: keymap-secondary
- * \endvar
- */
-               { LFUN_KEYMAP_SECONDARY, "keymap-secondary", ReadOnly, Edit },
-
-/*!
- * \var lyx::FuncCode lyx::LFUN_KEYMAP_TOGGLE
- * \li Action: Toggles keyboard maps (first/second/off).
- * \li Syntax: keymap-toggle
- * \li Origin: leeming, 30 Mar 2004
- * \endvar
- */
-               { LFUN_KEYMAP_TOGGLE, "keymap-toggle", ReadOnly, Edit },
+               The name is the base name of a .kmap file, as configured in the
+               Preferences dialog (e.g. "hebrew" for hebrew.kmap). Keyboard 
maps
+               can also be selected automatically according to the language at
+               the cursor; see the Preferences dialog. If no name is given,
+               any manual selection is dropped and the map configured in the
+               Preferences dialog is (re-)applied: the default map, or, if
+               automatic selection by language is enabled, the map configured
+               for the language at the cursor.
+ * \li Syntax: keymap-select <NAME>
+ * \li Params: <NAME>: the name of the keyboard map to select; if omitted,
+               return to the configured default.
+ * \li Origin: ufogiel, 27 July 2026
+ * \endvar
+ */
+               { LFUN_KEYMAP_SELECT, "keymap-select", ReadOnly, Edit },
 
 
 /*!
diff --git a/src/LyXRC.cpp b/src/LyXRC.cpp
index 98ec1a40ea..eafac0a34f 100644
--- a/src/LyXRC.cpp
+++ b/src/LyXRC.cpp
@@ -60,7 +60,7 @@ namespace {
 
 // The format should also be updated in configure.py, and conversion code
 // should be added to prefs2prefs_prefs.py.
-static unsigned int const LYXRC_FILEFORMAT = 42; // Change default of 
\visual_cursor to true
+static unsigned int const LYXRC_FILEFORMAT = 43; // Migrate \kbmap_secondary 
to \kbmap_follow_language + \kbmap_lang
 // when adding something to this array keep it sorted!
 LexerKeyword lyxrcTags[] = {
        { "\\accept_compound", LyXRC::RC_ACCEPT_COMPOUND },
@@ -132,8 +132,9 @@ LexerKeyword lyxrcTags[] = {
        { "\\jbibtex_command", LyXRC::RC_JBIBTEX_COMMAND },
        { "\\jindex_command", LyXRC::RC_JINDEX_COMMAND },
        { "\\kbmap", LyXRC::RC_KBMAP },
+       { "\\kbmap_follow_language", LyXRC::RC_KBMAP_FOLLOW_LANGUAGE },
+       { "\\kbmap_lang", LyXRC::RC_KBMAP_LANG },
        { "\\kbmap_primary", LyXRC::RC_KBMAP_PRIMARY },
-       { "\\kbmap_secondary", LyXRC::RC_KBMAP_SECONDARY },
        { "\\language_auto_begin", LyXRC::RC_LANGUAGE_AUTO_BEGIN },
        { "\\language_auto_end", LyXRC::RC_LANGUAGE_AUTO_END },
        { "\\language_command_begin", LyXRC::RC_LANGUAGE_COMMAND_BEGIN },
@@ -369,24 +370,33 @@ LyXRC::ReturnValues LyXRC::read(Lexer & lexrc, bool 
check_format)
                                string const 
kmap(os::internal_path(lexrc.getString()));
                                if (!libFileSearch("kbd", kmap, "kmap").empty()
                                    || kmap.empty()) {
-                                       primary_kbmap = kmap;
+                                       default_kbmap = kmap;
                                } else {
                                        lexrc.printError("LyX: Keymap `$$Token' 
not found");
                                }
                        }
                        break;
 
-               case RC_KBMAP_SECONDARY:
-                       if (lexrc.next()) {
-                               string const 
kmap(os::internal_path(lexrc.getString()));
-                               if (!libFileSearch("kbd", kmap, "kmap").empty()
-                                         || kmap.empty()) {
-                                       secondary_kbmap = kmap;
-                               } else {
-                                       lexrc.printError("LyX: Keymap `$$Token' 
not found");
-                               }
+               case RC_KBMAP_FOLLOW_LANGUAGE:
+                       lexrc >> keymap_follow_language;
+                       break;
+
+               case RC_KBMAP_LANG: {
+                       string lang;
+                       if (lexrc.next())
+                               lang = lexrc.getString();
+                       string kmap;
+                       if (lexrc.next())
+                               kmap = os::internal_path(lexrc.getString());
+                       if (kmap.empty()) {
+                               keymap_by_language.erase(lang);
+                       } else if (!libFileSearch("kbd", kmap, "kmap").empty()) 
{
+                               keymap_by_language[lang] = kmap;
+                       } else {
+                               lexrc.printError("LyX: Keymap `$$Token' not 
found");
                        }
                        break;
+               }
 
                case RC_PRINTLANDSCAPEFLAG:
                        lexrc >> print_landscape_flag;
@@ -1492,18 +1502,30 @@ void LyXRC::write(ostream & os, bool 
ignore_system_lyxrc, string const & name) c
                // fall through
        case RC_KBMAP_PRIMARY:
                if (ignore_system_lyxrc ||
-                   primary_kbmap != system_lyxrc.primary_kbmap) {
-                       string const path = os::external_path(primary_kbmap);
+                   default_kbmap != system_lyxrc.default_kbmap) {
+                       string const path = os::external_path(default_kbmap);
                        os << "\\kbmap_primary \"" << path << "\"\n";
                }
                if (tag != RC_LAST)
                        break;
                // fall through
-       case RC_KBMAP_SECONDARY:
+       case RC_KBMAP_FOLLOW_LANGUAGE:
                if (ignore_system_lyxrc ||
-                   secondary_kbmap != system_lyxrc.secondary_kbmap) {
-                       string const path = os::external_path(secondary_kbmap);
-                       os << "\\kbmap_secondary \"" << path << "\"\n";
+                   keymap_follow_language != 
system_lyxrc.keymap_follow_language) {
+                       os << "\\kbmap_follow_language "
+                          << convert<string>(keymap_follow_language) << '\n';
+               }
+               if (tag != RC_LAST)
+                       break;
+               // fall through
+       case RC_KBMAP_LANG:
+               if (ignore_system_lyxrc ||
+                   keymap_by_language != system_lyxrc.keymap_by_language) {
+                       for (auto const & lang_map : keymap_by_language) {
+                               string const path = 
os::external_path(lang_map.second);
+                               os << "\\kbmap_lang \"" << lang_map.first
+                                  << "\" \"" << path << "\"\n";
+                       }
                }
                if (tag != RC_LAST)
                        break;
@@ -2984,7 +3006,8 @@ void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC 
const & lyxrc_new)
        case LyXRC::RC_INPUT:
        case LyXRC::RC_KBMAP:
        case LyXRC::RC_KBMAP_PRIMARY:
-       case LyXRC::RC_KBMAP_SECONDARY:
+       case LyXRC::RC_KBMAP_FOLLOW_LANGUAGE:
+       case LyXRC::RC_KBMAP_LANG:
        case LyXRC::RC_LANGUAGE_AUTO_BEGIN:
        case LyXRC::RC_LANGUAGE_AUTO_END:
        case LyXRC::RC_LANGUAGE_COMMAND_BEGIN:
@@ -3278,10 +3301,17 @@ string const LyXRC::getDescription(LyXRCTags tag)
 
        case RC_KBMAP:
        case RC_KBMAP_PRIMARY:
-       case RC_KBMAP_SECONDARY:
                str = _("Use this to set the correct mapping file for your 
keyboard. You'll need this if you for instance want to type German documents on 
an American keyboard.");
                break;
 
+       case RC_KBMAP_FOLLOW_LANGUAGE:
+               str = _("Select the keyboard map automatically according to the 
language at the cursor, falling back to the default keyboard map for languages 
with no assignment of their own.");
+               break;
+
+       case RC_KBMAP_LANG:
+               str = _("Keyboard map to use for a given language when the 
keyboard map is selected automatically according to language.");
+               break;
+
        case RC_LANGUAGE_AUTO_BEGIN:
                str = _("Select if a language switching command is needed at 
the beginning of the document.");
                break;
diff --git a/src/LyXRC.h b/src/LyXRC.h
index 82df958e44..4172303531 100644
--- a/src/LyXRC.h
+++ b/src/LyXRC.h
@@ -111,7 +111,8 @@ public:
                RC_JINDEX_COMMAND,
                RC_KBMAP,
                RC_KBMAP_PRIMARY,
-               RC_KBMAP_SECONDARY,
+               RC_KBMAP_FOLLOW_LANGUAGE,
+               RC_KBMAP_LANG,
                RC_LANGUAGE_AUTO_BEGIN,
                RC_LANGUAGE_AUTO_END,
                RC_LANGUAGE_COMMAND_BEGIN,
@@ -384,10 +385,12 @@ public:
        bool spellcheck_notes = true;
        ///
        bool use_kbmap = false;
-       ///
-       std::string primary_kbmap;
-       ///
-       std::string secondary_kbmap;
+       /// the keyboard map to load at start-up, if use_kbmap is set
+       std::string default_kbmap;
+       /// select the keyboard map by language instead of default_kbmap
+       bool keymap_follow_language = false;
+       /// keyboard map per language code, used when keymap_follow_language is 
set
+       std::map<std::string, std::string> keymap_by_language;
        ///
        std::string lyxpipes;
        ///
diff --git a/src/Trans.cpp b/src/Trans.cpp
index 12086658b1..470186b10d 100644
--- a/src/Trans.cpp
+++ b/src/Trans.cpp
@@ -23,6 +23,8 @@
 #include "support/Lexer.h"
 #include "support/lstrings.h"
 
+#include <utility>
+
 using namespace std;
 using namespace lyx::support;
 
@@ -579,38 +581,25 @@ TransManager::TransManager()
 {}
 
 
-int TransManager::setPrimary(string const & language)
-{
-       if (t1_.getName() == language)
-               return 0;
-
-       return t1_.load(language);
-}
-
-
-int TransManager::setSecondary(string const & language)
+int TransManager::setActive(string const & name)
 {
-       if (t2_.getName() == language)
+       if (name.empty()) {
+               disableKeymap();
                return 0;
+       }
 
-       return t2_.load(language);
-}
-
-
-void TransManager::enablePrimary()
-{
-       if (t1_.isDefined())
-               active_ = &t1_;
-
-       LYXERR(Debug::KBMAP, "Enabling primary keymap");
-}
-
+       map<string, Trans>::iterator it = maps_.find(name);
+       if (it == maps_.end()) {
+               Trans t;
+               int const res = t.load(name);
+               if (res != 0)
+                       return res;
+               it = maps_.emplace(name, std::move(t)).first;
+       }
 
-void TransManager::enableSecondary()
-{
-       if (t2_.isDefined())
-               active_ = &t2_;
-       LYXERR(Debug::KBMAP, "Enabling secondary keymap");
+       active_ = &it->second;
+       LYXERR(Debug::KBMAP, "Enabling keymap `" << name << '\'');
+       return 0;
 }
 
 
diff --git a/src/Trans.h b/src/Trans.h
index c8d828e785..7f6bda43fe 100644
--- a/src/Trans.h
+++ b/src/Trans.h
@@ -135,6 +135,11 @@ public:
        Trans() {}
        ///
        ~Trans() { freeKeymap(); }
+       /// defaulted explicitly: the destructor above suppresses these
+       /// implicitly, which would silently turn moves into copies
+       Trans(Trans &&) = default;
+       ///
+       Trans & operator=(Trans &&) = default;
 
        ///
        int load(std::string const & language);
@@ -313,9 +318,7 @@ private:
        ///
        Trans * active_;
        ///
-       Trans t1_;
-       ///
-       Trans t2_;
+       std::map<std::string, Trans> maps_;
        ///
        static Trans default_;
        ///
@@ -323,14 +326,8 @@ private:
 public:
        ///
        TransManager();
-       ///
-       int setPrimary(std::string const &);
-       ///
-       int setSecondary(std::string const &);
-       ///
-       void enablePrimary();
-       ///
-       void enableSecondary();
+       /// load (if needed) and activate the named keymap; 0 on success, -1 if 
not found
+       int setActive(std::string const &);
        ///
        void disableKeymap();
        ///
diff --git a/src/frontends/qt/GuiPrefs.cpp b/src/frontends/qt/GuiPrefs.cpp
index 6998430780..df50b086c0 100644
--- a/src/frontends/qt/GuiPrefs.cpp
+++ b/src/frontends/qt/GuiPrefs.cpp
@@ -318,8 +318,6 @@ PrefInput::PrefInput(GuiPreferences * form)
                this, SIGNAL(changed()));
        connect(firstKeymapED, SIGNAL(textChanged(QString)),
                this, SIGNAL(changed()));
-       connect(secondKeymapED, SIGNAL(textChanged(QString)),
-               this, SIGNAL(changed()));
        connect(mouseWheelSpeedSB, SIGNAL(valueChanged(double)),
                this, SIGNAL(changed()));
        connect(scrollzoomEnableCB, SIGNAL(clicked()),
@@ -330,6 +328,21 @@ PrefInput::PrefInput(GuiPreferences * form)
                this, SIGNAL(changed()));
        connect(mmPasteCB, SIGNAL(toggled(bool)),
                this, SIGNAL(changed()));
+       connect(keymapFollowLangCB, SIGNAL(clicked()),
+               this, SIGNAL(changed()));
+       connect(keymapLangAddPB, SIGNAL(clicked()),
+               this, SLOT(addKeymapLang()));
+       connect(keymapLangAddPB, SIGNAL(clicked()),
+               this, SIGNAL(changed()));
+       connect(keymapLangRemovePB, SIGNAL(clicked()),
+               this, SLOT(removeKeymapLang()));
+       connect(keymapLangRemovePB, SIGNAL(clicked()),
+               this, SIGNAL(changed()));
+
+       keymapLangED->setValidator(new NoNewLineValidator(keymapLangED));
+
+       keymapLangCO->setModel(guiApp->languageModel());
+       keymapLangCO->setModelColumn(0);
 
        // reveal checkbox for switching Ctrl and Meta on Mac:
 #ifdef Q_OS_MAC
@@ -342,10 +355,9 @@ PrefInput::PrefInput(GuiPreferences * form)
 
 void PrefInput::applyRC(LyXRC & rc) const
 {
-       // FIXME: can derive CB from the two EDs
+       // FIXME: can derive CB from the ED
        rc.use_kbmap = keymapCB->isChecked();
-       rc.primary_kbmap = internal_path(fromqstr(firstKeymapED->text()));
-       rc.secondary_kbmap = internal_path(fromqstr(secondKeymapED->text()));
+       rc.default_kbmap = internal_path(fromqstr(firstKeymapED->text()));
        rc.mouse_wheel_speed = mouseWheelSpeedSB->value();
        if (scrollzoomEnableCB->isChecked()) {
                switch (scrollzoomValueCO->currentIndex()) {
@@ -364,15 +376,23 @@ void PrefInput::applyRC(LyXRC & rc) const
        }
        rc.mac_dontswap_ctrl_meta  = dontswapCB->isChecked();
        rc.mouse_middlebutton_paste = mmPasteCB->isChecked();
+
+       rc.keymap_follow_language = keymapFollowLangCB->isChecked();
+       rc.keymap_by_language.clear();
+       for (int i = 0; i < keymapLangLW->count(); ++i) {
+               QListWidgetItem const * item = keymapLangLW->item(i);
+               string const langcode = 
fromqstr(item->data(Qt::UserRole).toString());
+               string const kmap = 
internal_path(fromqstr(item->data(Qt::UserRole + 1).toString()));
+               rc.keymap_by_language[langcode] = kmap;
+       }
 }
 
 
 void PrefInput::updateRC(LyXRC const & rc)
 {
-       // FIXME: can derive CB from the two EDs
+       // FIXME: can derive CB from the ED
        keymapCB->setChecked(rc.use_kbmap);
-       firstKeymapED->setText(toqstr(external_path(rc.primary_kbmap)));
-       secondKeymapED->setText(toqstr(external_path(rc.secondary_kbmap)));
+       firstKeymapED->setText(toqstr(external_path(rc.default_kbmap)));
        mouseWheelSpeedSB->setValue(rc.mouse_wheel_speed);
        switch (rc.scroll_wheel_zoom) {
        case LyXRC::SCROLL_WHEEL_ZOOM_OFF:
@@ -393,6 +413,20 @@ void PrefInput::updateRC(LyXRC const & rc)
        }
        dontswapCB->setChecked(rc.mac_dontswap_ctrl_meta);
        mmPasteCB->setChecked(rc.mouse_middlebutton_paste);
+
+       keymapFollowLangCB->setChecked(rc.keymap_follow_language);
+       keymapLangLW->clear();
+       for (auto const & lang_map : rc.keymap_by_language) {
+               Language const * lang = languages.getLanguage(lang_map.first);
+               QString const langname = lang ? qt_(lang->display())
+                       : toqstr(lang_map.first);
+               QString const kmap = toqstr(external_path(lang_map.second));
+               QListWidgetItem * item =
+                       new QListWidgetItem(langname + ": " + kmap, 
keymapLangLW);
+               item->setData(Qt::UserRole, toqstr(lang_map.first));
+               item->setData(Qt::UserRole + 1, kmap);
+       }
+       keymapLangLW->sortItems();
 }
 
 
@@ -410,22 +444,13 @@ void PrefInput::on_firstKeymapPB_clicked(bool)
 }
 
 
-void PrefInput::on_secondKeymapPB_clicked(bool)
-{
-       QString const file = testKeymap(secondKeymapED->text());
-       if (!file.isEmpty())
-               secondKeymapED->setText(file);
-}
-
-
 void PrefInput::on_keymapCB_toggled(bool keymap)
 {
        firstKeymapLA->setEnabled(keymap);
-       secondKeymapLA->setEnabled(keymap);
        firstKeymapED->setEnabled(keymap);
-       secondKeymapED->setEnabled(keymap);
        firstKeymapPB->setEnabled(keymap);
-       secondKeymapPB->setEnabled(keymap);
+       keymapFollowLangCB->setEnabled(keymap);
+       updateKeymapLangEnabled();
 }
 
 
@@ -435,6 +460,80 @@ void PrefInput::on_scrollzoomEnableCB_toggled(bool enabled)
 }
 
 
+void PrefInput::on_keymapFollowLangCB_toggled(bool)
+{
+       updateKeymapLangEnabled();
+}
+
+
+void PrefInput::updateKeymapLangEnabled()
+{
+       bool const enabled = keymapCB->isChecked() && 
keymapFollowLangCB->isChecked();
+       keymapLangLW->setEnabled(enabled);
+       keymapLangCO->setEnabled(enabled);
+       keymapLangED->setEnabled(enabled);
+       keymapLangPB->setEnabled(enabled);
+       keymapLangAddPB->setEnabled(enabled);
+       keymapLangRemovePB->setEnabled(enabled && keymapLangLW->currentRow() >= 
0);
+}
+
+
+void PrefInput::on_keymapLangLW_currentRowChanged(int row)
+{
+       keymapLangRemovePB->setEnabled(row >= 0
+               && keymapCB->isChecked() && keymapFollowLangCB->isChecked());
+       if (row < 0)
+               return;
+       QListWidgetItem const * item = keymapLangLW->item(row);
+       int const pos = keymapLangCO->findData(item->data(Qt::UserRole));
+       if (pos >= 0)
+               keymapLangCO->setCurrentIndex(pos);
+       keymapLangED->setText(item->data(Qt::UserRole + 1).toString());
+}
+
+
+void PrefInput::on_keymapLangPB_clicked(bool)
+{
+       QString const file = testKeymap(keymapLangED->text());
+       if (!file.isEmpty())
+               keymapLangED->setText(file);
+}
+
+
+void PrefInput::addKeymapLang()
+{
+       int const idx = keymapLangCO->currentIndex();
+       QString const kmap = keymapLangED->text();
+       if (idx < 0 || kmap.isEmpty())
+               return;
+
+       QString const langcode = keymapLangCO->itemData(idx).toString();
+       QString const text = keymapLangCO->currentText() + ": " + kmap;
+
+       // replace any existing entry for this language
+       for (int i = 0; i < keymapLangLW->count(); ++i) {
+               if (keymapLangLW->item(i)->data(Qt::UserRole).toString() == 
langcode) {
+                       delete keymapLangLW->takeItem(i);
+                       break;
+               }
+       }
+
+       QListWidgetItem * item = new QListWidgetItem(text, keymapLangLW);
+       item->setData(Qt::UserRole, langcode);
+       item->setData(Qt::UserRole + 1, kmap);
+       keymapLangLW->sortItems();
+       keymapLangLW->setCurrentItem(item);
+}
+
+
+void PrefInput::removeKeymapLang()
+{
+       int const row = keymapLangLW->currentRow();
+       if (row >= 0)
+               delete keymapLangLW->takeItem(row);
+}
+
+
 /////////////////////////////////////////////////////////////////////
 //
 // PrefCompletion
@@ -4574,6 +4673,8 @@ void GuiPreferences::dispatchParams()
 
        theMovers() = movers_;
 
+       lyxrc.keymap_by_language = rc_.keymap_by_language;
+
        for (string const & color : colors_)
                dispatch(FuncRequest(LFUN_SET_COLOR, color));
        colors_.clear();
diff --git a/src/frontends/qt/GuiPrefs.h b/src/frontends/qt/GuiPrefs.h
index cae84feae4..ba74b14fc3 100644
--- a/src/frontends/qt/GuiPrefs.h
+++ b/src/frontends/qt/GuiPrefs.h
@@ -183,12 +183,17 @@ public:
 
 private Q_SLOTS:
        void on_firstKeymapPB_clicked(bool);
-       void on_secondKeymapPB_clicked(bool);
        void on_keymapCB_toggled(bool);
        void on_scrollzoomEnableCB_toggled(bool);
+       void on_keymapFollowLangCB_toggled(bool);
+       void on_keymapLangLW_currentRowChanged(int);
+       void on_keymapLangPB_clicked(bool);
+       void addKeymapLang();
+       void removeKeymapLang();
 
 private:
        QString testKeymap(QString const & keymap);
+       void updateKeymapLangEnabled();
 };
 
 
diff --git a/src/frontends/qt/ui/PrefInputUi.ui 
b/src/frontends/qt/ui/PrefInputUi.ui
index a9960b2a2a..cc78677f26 100644
--- a/src/frontends/qt/ui/PrefInputUi.ui
+++ b/src/frontends/qt/ui/PrefInputUi.ui
@@ -43,59 +43,142 @@
         </property>
        </widget>
       </item>
-      <item row="2" column="2">
-       <widget class="QPushButton" name="secondKeymapPB">
+      <item row="1" column="2">
+       <widget class="QPushButton" name="firstKeymapPB">
         <property name="enabled">
          <bool>false</bool>
         </property>
         <property name="text">
-         <string>&amp;Browse...</string>
+         <string>Br&amp;owse...</string>
         </property>
         <property name="autoDefault">
          <bool>false</bool>
         </property>
        </widget>
       </item>
-      <item row="1" column="2">
-       <widget class="QPushButton" name="firstKeymapPB">
+      <item row="1" column="0">
+       <widget class="QLabel" name="firstKeymapLA">
         <property name="enabled">
          <bool>false</bool>
         </property>
         <property name="text">
-         <string>Br&amp;owse...</string>
+         <string>&amp;Default:</string>
         </property>
-        <property name="autoDefault">
-         <bool>false</bool>
+        <property name="buddy">
+         <cstring>firstKeymapED</cstring>
         </property>
        </widget>
       </item>
-      <item row="2" column="0">
-       <widget class="QLabel" name="secondKeymapLA">
+      <item row="2" column="0" colspan="3">
+       <widget class="QCheckBox" name="keymapFollowLangCB">
         <property name="enabled">
          <bool>false</bool>
         </property>
-        <property name="text">
-         <string>S&amp;econdary:</string>
+        <property name="toolTip">
+         <string>If checked, the keyboard map is selected automatically 
according to the language at the cursor, using the assignments below, falling 
back to the Default map above for languages without an assignment</string>
         </property>
-        <property name="buddy">
-         <cstring>secondKeymapED</cstring>
+        <property name="text">
+         <string>&amp;Select keyboard map automatically by language</string>
         </property>
        </widget>
       </item>
-      <item row="1" column="0">
-       <widget class="QLabel" name="firstKeymapLA">
+      <item row="3" column="0" colspan="2">
+       <widget class="QListWidget" name="keymapLangLW">
         <property name="enabled">
          <bool>false</bool>
         </property>
-        <property name="text">
-         <string>&amp;Primary:</string>
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
         </property>
-        <property name="buddy">
-         <cstring>firstKeymapED</cstring>
+        <property name="toolTip">
+         <string>Keyboard map assigned to each language</string>
         </property>
        </widget>
       </item>
-      <item row="3" column="0" colspan="3">
+      <item row="3" column="2">
+       <layout class="QVBoxLayout" name="verticalLayout_kbmaplang">
+        <item>
+         <widget class="QComboBox" name="keymapLangCO">
+          <property name="enabled">
+           <bool>false</bool>
+          </property>
+          <property name="toolTip">
+           <string>Language to assign a keyboard map to</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <layout class="QHBoxLayout" name="horizontalLayout_kbmaplang">
+          <item>
+           <widget class="QLineEdit" name="keymapLangED">
+            <property name="enabled">
+             <bool>false</bool>
+            </property>
+            <property name="toolTip">
+             <string>Keyboard map to use for the selected language</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="keymapLangPB">
+            <property name="enabled">
+             <bool>false</bool>
+            </property>
+            <property name="text">
+             <string>&amp;Browse...</string>
+            </property>
+            <property name="autoDefault">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <widget class="QPushButton" name="keymapLangAddPB">
+          <property name="enabled">
+           <bool>false</bool>
+          </property>
+          <property name="text">
+           <string>A&amp;dd</string>
+          </property>
+          <property name="autoDefault">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="keymapLangRemovePB">
+          <property name="enabled">
+           <bool>false</bool>
+          </property>
+          <property name="text">
+           <string>Remo&amp;ve</string>
+          </property>
+          <property name="autoDefault">
+           <bool>false</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="verticalSpacer_kbmaplang">
+          <property name="orientation">
+           <enum>Qt::Vertical</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>20</width>
+            <height>40</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </item>
+      <item row="4" column="0" colspan="3">
        <widget class="QCheckBox" name="dontswapCB">
         <property name="toolTip">
          <string>macOS specific setting for use with emacs bindings. Takes 
effect next time LyX is launched.</string>
@@ -108,13 +191,6 @@
         </property>
        </widget>
       </item>
-      <item row="2" column="1">
-       <widget class="QLineEdit" name="secondKeymapED">
-        <property name="enabled">
-         <bool>false</bool>
-        </property>
-       </widget>
-      </item>
      </layout>
     </widget>
    </item>
@@ -299,8 +375,13 @@
   <tabstop>keymapCB</tabstop>
   <tabstop>firstKeymapED</tabstop>
   <tabstop>firstKeymapPB</tabstop>
-  <tabstop>secondKeymapED</tabstop>
-  <tabstop>secondKeymapPB</tabstop>
+  <tabstop>keymapFollowLangCB</tabstop>
+  <tabstop>keymapLangLW</tabstop>
+  <tabstop>keymapLangCO</tabstop>
+  <tabstop>keymapLangED</tabstop>
+  <tabstop>keymapLangPB</tabstop>
+  <tabstop>keymapLangAddPB</tabstop>
+  <tabstop>keymapLangRemovePB</tabstop>
   <tabstop>mouseWheelSpeedSB</tabstop>
  </tabstops>
  <includes>
-- 
lyx-cvs mailing list
[email protected]
https://lists.lyx.org/mailman/listinfo/lyx-cvs

Reply via email to