diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index ff78b78d45a..714150d240c 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -1526,6 +1526,16 @@
   #endif
 #endif // HAS_DGUS_LCD
 
+//
+// Specify additional languages for the UI. Default specified by LCD_LANGUAGE.
+//
+#if EITHER(DOGLCD, TOUCH_UI_FTDI_EVE)
+  //#define LCD_LANGUAGE_2 fr
+  //#define LCD_LANGUAGE_3 de
+  //#define LCD_LANGUAGE_4 es
+  //#define LCD_LANGUAGE_5 it
+#endif
+
 //
 // Touch UI for the FTDI Embedded Video Engine (EVE)
 //
@@ -1601,13 +1611,6 @@
   // Use a smaller font when labels don't fit buttons
   #define TOUCH_UI_FIT_TEXT
 
-  // Allow language selection from menu at run-time (otherwise use LCD_LANGUAGE)
-  //#define LCD_LANGUAGE_1 en
-  //#define LCD_LANGUAGE_2 fr
-  //#define LCD_LANGUAGE_3 de
-  //#define LCD_LANGUAGE_4 es
-  //#define LCD_LANGUAGE_5 it
-
   // Use a numeric passcode for "Screen lock" keypad.
   // (recommended for smaller displays)
   //#define TOUCH_UI_PASSCODE
diff --git a/Marlin/src/core/multi_language.h b/Marlin/src/core/multi_language.h
index 6af4af2f8df..5a26edf8d45 100644
--- a/Marlin/src/core/multi_language.h
+++ b/Marlin/src/core/multi_language.h
@@ -20,6 +20,8 @@
  ****************************************************************************/
 #pragma once
 
+#include "../inc/MarlinConfigPre.h"
+
 typedef const char Language_Str[];
 
 #ifdef LCD_LANGUAGE_5
@@ -57,26 +59,27 @@ typedef const char Language_Str[];
 #define GET_LANG(LANG) _GET_LANG(LANG)
 
 #if NUM_LANGUAGES > 1
-  extern uint8_t lang;
+  #define HAS_MULTI_LANGUAGE 1
   #define GET_TEXT(MSG) ( \
-    lang == 0 ? GET_LANG(LCD_LANGUAGE)::MSG : \
-    lang == 1 ? GET_LANG(LCD_LANGUAGE_2)::MSG : \
-    lang == 2 ? GET_LANG(LCD_LANGUAGE_3)::MSG : \
-    lang == 3 ? GET_LANG(LCD_LANGUAGE_4)::MSG : \
-                GET_LANG(LCD_LANGUAGE_5)::MSG \
-    )
-  #define MAX_LANG_CHARSIZE _MAX(GET_LANG(LCD_LANGUAGE)::CHARSIZE, \
-                                GET_LANG(LCD_LANGUAGE_2)::CHARSIZE, \
-                                GET_LANG(LCD_LANGUAGE_3)::CHARSIZE, \
-                                GET_LANG(LCD_LANGUAGE_4)::CHARSIZE, \
-                                GET_LANG(LCD_LANGUAGE_5)::CHARSIZE)
+    ui.language == 0 ? GET_LANG(LCD_LANGUAGE  )::MSG : \
+    ui.language == 1 ? GET_LANG(LCD_LANGUAGE_2)::MSG : \
+    ui.language == 2 ? GET_LANG(LCD_LANGUAGE_3)::MSG : \
+    ui.language == 3 ? GET_LANG(LCD_LANGUAGE_4)::MSG : \
+                       GET_LANG(LCD_LANGUAGE_5)::MSG   )
+  #define MAX_LANG_CHARSIZE _MAX(GET_LANG(LCD_LANGUAGE  )::CHARSIZE, \
+                                 GET_LANG(LCD_LANGUAGE_2)::CHARSIZE, \
+                                 GET_LANG(LCD_LANGUAGE_3)::CHARSIZE, \
+                                 GET_LANG(LCD_LANGUAGE_4)::CHARSIZE, \
+                                 GET_LANG(LCD_LANGUAGE_5)::CHARSIZE  )
 #else
   #define GET_TEXT(MSG) GET_LANG(LCD_LANGUAGE)::MSG
-  #define MAX_LANG_CHARSIZE GET_LANG(LCD_LANGUAGE)::CHARSIZE
+  #define MAX_LANG_CHARSIZE LANG_CHARSIZE
 #endif
 #define GET_TEXT_F(MSG) (const __FlashStringHelper*)GET_TEXT(MSG)
 
 #define GET_LANGUAGE_NAME(INDEX) GET_LANG(LCD_LANGUAGE_##INDEX)::LANGUAGE
+#define LANG_CHARSIZE GET_TEXT(CHARSIZE)
+#define USE_WIDE_GLYPH (LANG_CHARSIZE > 2)
 
 #define MSG_1_LINE(A)     A "\0"   "\0"
 #define MSG_2_LINE(A,B)   A "\0" B "\0"
diff --git a/Marlin/src/gcode/gcode.cpp b/Marlin/src/gcode/gcode.cpp
index 89bc0dc7af6..90a0b0ded00 100644
--- a/Marlin/src/gcode/gcode.cpp
+++ b/Marlin/src/gcode/gcode.cpp
@@ -718,6 +718,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
         case 412: M412(); break;                                  // M412: Enable/Disable filament runout detection
       #endif
 
+      #if HAS_MULTI_LANGUAGE
+        case 414: M414(); break;                                  // M414: Select multi language menu
+      #endif
+
       #if HAS_LEVELING
         case 420: M420(); break;                                  // M420: Enable/Disable Bed Leveling
       #endif
diff --git a/Marlin/src/gcode/gcode.h b/Marlin/src/gcode/gcode.h
index 765cd8e5914..9453eecd946 100644
--- a/Marlin/src/gcode/gcode.h
+++ b/Marlin/src/gcode/gcode.h
@@ -213,6 +213,7 @@
  * M410 - Quickstop. Abort all planned moves.
  * M412 - Enable / Disable Filament Runout Detection. (Requires FILAMENT_RUNOUT_SENSOR)
  * M413 - Enable / Disable Power-Loss Recovery. (Requires POWER_LOSS_RECOVERY)
+ * M414 - Set language by index. (Requires LCD_LANGUAGE_2...)
  * M420 - Enable/Disable Leveling (with current values) S1=enable S0=disable (Requires MESH_BED_LEVELING or ABL)
  * M421 - Set a single Z coordinate in the Mesh Leveling grid. X<units> Y<units> Z<units> (Requires MESH_BED_LEVELING, AUTO_BED_LEVELING_BILINEAR, or AUTO_BED_LEVELING_UBL)
  * M422 - Set Z Stepper automatic alignment position using probe. X<units> Y<units> A<axis> (Requires Z_STEPPER_AUTO_ALIGN)
@@ -747,6 +748,8 @@ private:
 
   TERN_(HAS_FILAMENT_SENSOR, static void M412());
 
+  TERN_(HAS_MULTI_LANGUAGE, static void M414());
+
   #if HAS_LEVELING
     static void M420();
     static void M421();
diff --git a/Marlin/src/gcode/lcd/M414.cpp b/Marlin/src/gcode/lcd/M414.cpp
new file mode 100644
index 00000000000..760028a899f
--- /dev/null
+++ b/Marlin/src/gcode/lcd/M414.cpp
@@ -0,0 +1,44 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../../inc/MarlinConfig.h"
+
+#if HAS_MULTI_LANGUAGE
+
+#include "../gcode.h"
+#include "../../MarlinCore.h"
+#include "../../lcd/marlinui.h"
+
+/**
+ * M414: Set the language for the UI
+ *
+ * Parameters
+ *  S<index> : The language to select
+ */
+void GcodeSuite::M414() {
+
+  if (parser.seenval('S'))
+    ui.set_language(parser.value_byte());
+
+}
+
+#endif // HAS_MULTI_LANGUAGE
diff --git a/Marlin/src/inc/MarlinConfig.h b/Marlin/src/inc/MarlinConfig.h
index 2eafa2b4171..8fdb4b9baea 100644
--- a/Marlin/src/inc/MarlinConfig.h
+++ b/Marlin/src/inc/MarlinConfig.h
@@ -55,3 +55,5 @@
   #include "../core/serial.h"
 
 #endif
+
+#include "../core/multi_language.h"
diff --git a/Marlin/src/lcd/dogm/marlinui_DOGM.cpp b/Marlin/src/lcd/dogm/marlinui_DOGM.cpp
index c326b89aa82..c7c5908b36b 100644
--- a/Marlin/src/lcd/dogm/marlinui_DOGM.cpp
+++ b/Marlin/src/lcd/dogm/marlinui_DOGM.cpp
@@ -54,6 +54,7 @@
 #include "../../sd/cardreader.h"
 #include "../../module/temperature.h"
 #include "../../module/printcounter.h"
+#include "../../MarlinCore.h"
 
 #if ENABLED(SDSUPPORT)
   #include "../../libs/duration_t.h"
@@ -455,20 +456,22 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop
   inline void draw_boxed_string(const u8g_uint_t x, const u8g_uint_t y, PGM_P const pstr, const bool inv) {
     const u8g_uint_t len = utf8_strlen_P(pstr),
                       by = (y + 1) * (MENU_FONT_HEIGHT);
-    const pixel_len_t bw = len * (MENU_FONT_WIDTH), bx = x * (MENU_FONT_WIDTH);
+    const u8g_uint_t prop = USE_WIDE_GLYPH ? 2 : 1;
+    const pixel_len_t bw = len * prop * (MENU_FONT_WIDTH), bx = x * prop * (MENU_FONT_WIDTH);
     if (inv) {
       u8g.setColorIndex(1);
-      u8g.drawBox(bx - 1, by - (MENU_FONT_ASCENT) + 1, bw + 2, MENU_FONT_HEIGHT - 1);
+      u8g.drawBox(bx / prop - 1, by - (MENU_FONT_ASCENT) + 1, bw / prop + 2, MENU_FONT_HEIGHT - 1);
       u8g.setColorIndex(0);
     }
-    lcd_put_u8str_P(bx, by, pstr);
+    lcd_put_u8str_P(bx / prop, by, pstr);
     if (inv) u8g.setColorIndex(1);
   }
 
   void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const bool yesno, PGM_P const pref, const char * const string/*=nullptr*/, PGM_P const suff/*=nullptr*/) {
     ui.draw_select_screen_prompt(pref, string, suff);
     draw_boxed_string(1, LCD_HEIGHT - 1, no, !yesno);
-    draw_boxed_string(LCD_WIDTH - (utf8_strlen_P(yes) + 1), LCD_HEIGHT - 1, yes, yesno);
+    const u8g_uint_t xpos = (LCD_WIDTH) / (USE_WIDE_GLYPH ? 2 : 1);
+    draw_boxed_string(xpos - (utf8_strlen_P(yes) + 1), LCD_HEIGHT - 1, yes, yesno);
   }
 
   #if ENABLED(SDSUPPORT)
diff --git a/Marlin/src/lcd/extui/lib/mks_ui/pic_manager.cpp b/Marlin/src/lcd/extui/lib/mks_ui/pic_manager.cpp
index 1cb7ed185e0..8b96587fea1 100644
--- a/Marlin/src/lcd/extui/lib/mks_ui/pic_manager.cpp
+++ b/Marlin/src/lcd/extui/lib/mks_ui/pic_manager.cpp
@@ -64,7 +64,6 @@ static const char assets[][LONG_FILENAME_LENGTH] = {
   "bmp_speed255.bin",
   "bmp_speed127.bin",
   "bmp_speed0.bin",
-  "bmp_speed0.bin",
 
   "bmp_bed.bin",
   "bmp_step1_degree.bin",
diff --git a/Marlin/src/lcd/lcdprint.cpp b/Marlin/src/lcd/lcdprint.cpp
index 2c78b14834b..32f425168f8 100644
--- a/Marlin/src/lcd/lcdprint.cpp
+++ b/Marlin/src/lcd/lcdprint.cpp
@@ -28,6 +28,7 @@
 
 #if HAS_WIRED_LCD && !HAS_GRAPHICAL_TFT
 
+#include "marlinui.h"
 #include "lcdprint.h"
 
 /**
diff --git a/Marlin/src/lcd/marlinui.cpp b/Marlin/src/lcd/marlinui.cpp
index d4e1357e861..d13c8e409de 100644
--- a/Marlin/src/lcd/marlinui.cpp
+++ b/Marlin/src/lcd/marlinui.cpp
@@ -78,6 +78,10 @@ constexpr uint8_t epps = ENCODER_PULSES_PER_STEP;
   #endif
 #endif
 
+#if HAS_MULTI_LANGUAGE
+  uint8_t MarlinUI::language; // Initialized by settings.load()
+#endif
+
 #if ENABLED(SOUND_MENU_ITEM)
   bool MarlinUI::buzzer_enabled = true;
 #endif
diff --git a/Marlin/src/lcd/marlinui.h b/Marlin/src/lcd/marlinui.h
index a64483fcb00..95a521d5dd8 100644
--- a/Marlin/src/lcd/marlinui.h
+++ b/Marlin/src/lcd/marlinui.h
@@ -178,6 +178,17 @@ public:
     TERN_(HAS_LCD_MENU, currentScreen = status_screen);
   }
 
+  #if HAS_MULTI_LANGUAGE
+    static uint8_t language;
+    static inline void set_language(const uint8_t lang) {
+      if (lang < NUM_LANGUAGES) {
+        language = lang;
+        return_to_status();
+        refresh();
+      }
+    }
+  #endif
+
   #if ENABLED(SOUND_MENU_ITEM)
     static bool buzzer_enabled; // Initialized by settings.load()
   #else
diff --git a/Marlin/src/lcd/menu/menu_language.cpp b/Marlin/src/lcd/menu/menu_language.cpp
new file mode 100644
index 00000000000..26660f22f80
--- /dev/null
+++ b/Marlin/src/lcd/menu/menu_language.cpp
@@ -0,0 +1,59 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+//
+// Language Selection Menu
+//
+
+#include "../../inc/MarlinConfig.h"
+
+#if HAS_MULTI_LANGUAGE
+
+#include "menu_item.h"
+#include "../../MarlinCore.h"
+#include "../../module/settings.h"
+
+static void set_lcd_language(const uint8_t inlang) {
+  ui.set_language(inlang);
+  (void)settings.save();
+}
+
+void menu_language() {
+  START_MENU();
+  BACK_ITEM(MSG_MAIN);
+
+  MENU_ITEM_P(function, GET_LANG(LCD_LANGUAGE  )::LANGUAGE, []{ set_lcd_language(0); });
+  MENU_ITEM_P(function, GET_LANG(LCD_LANGUAGE_2)::LANGUAGE, []{ set_lcd_language(1); });
+  #if NUM_LANGUAGES > 2
+    MENU_ITEM_P(function, GET_LANG(LCD_LANGUAGE_3)::LANGUAGE, []{ set_lcd_language(2); });
+    #if NUM_LANGUAGES > 3
+      MENU_ITEM_P(function, GET_LANG(LCD_LANGUAGE_4)::LANGUAGE, []{ set_lcd_language(3); });
+      #if NUM_LANGUAGES > 4
+        MENU_ITEM_P(function, GET_LANG(LCD_LANGUAGE_5)::LANGUAGE, []{ set_lcd_language(4); });
+      #endif
+    #endif
+  #endif
+
+  END_MENU();
+}
+
+#endif // HAS_MULTI_LANGUAGE
diff --git a/Marlin/src/lcd/menu/menu_main.cpp b/Marlin/src/lcd/menu/menu_main.cpp
index b7cd549e6b0..24d048cafda 100644
--- a/Marlin/src/lcd/menu/menu_main.cpp
+++ b/Marlin/src/lcd/menu/menu_main.cpp
@@ -97,6 +97,10 @@ void menu_configuration();
   void menu_spindle_laser();
 #endif
 
+#if HAS_MULTI_LANGUAGE
+  void menu_language();
+#endif
+
 extern const char M21_STR[];
 
 void menu_main() {
@@ -325,6 +329,10 @@ void menu_main() {
     }
   #endif
 
+  #if HAS_MULTI_LANGUAGE
+    SUBMENU(LANGUAGE, menu_language);
+  #endif
+
   END_MENU();
 }
 
diff --git a/Marlin/src/module/settings.cpp b/Marlin/src/module/settings.cpp
index 58cdd5296f2..0a5439facde 100644
--- a/Marlin/src/module/settings.cpp
+++ b/Marlin/src/module/settings.cpp
@@ -36,7 +36,7 @@
  */
 
 // Change EEPROM version if the structure changes
-#define EEPROM_VERSION "V82"
+#define EEPROM_VERSION "V83"
 #define EEPROM_OFFSET 100
 
 // Check the integrity of data offsets.
@@ -457,6 +457,11 @@ typedef struct SettingsDataStruct {
   #if ENABLED(SOUND_MENU_ITEM)
     bool buzzer_enabled;
   #endif
+
+  #if HAS_MULTI_LANGUAGE
+    uint8_t ui_language;                                // M414 S
+  #endif
+
 } SettingsData;
 
 //static_assert(sizeof(SettingsData) <= MARLIN_EEPROM_SIZE, "EEPROM too small to contain SettingsData!");
@@ -1382,6 +1387,13 @@ void MarlinSettings::postprocess() {
       EEPROM_WRITE(ui.buzzer_enabled);
     #endif
 
+    //
+    // Selected LCD language
+    //
+    #if HAS_MULTI_LANGUAGE
+      EEPROM_WRITE(ui.language);
+    #endif
+
     //
     // Report final CRC and Data Size
     //
@@ -2261,6 +2273,18 @@ void MarlinSettings::postprocess() {
         EEPROM_READ(ui.buzzer_enabled);
       #endif
 
+      //
+      // Selected LCD language
+      //
+      #if HAS_MULTI_LANGUAGE
+      {
+        uint8_t ui_language;
+        EEPROM_READ(ui_language);
+        if (ui_language >= NUM_LANGUAGES) ui_language = 0;
+        ui.set_language(ui_language);
+      }
+      #endif
+
       //
       // Validate Final Size and CRC
       //
@@ -3846,6 +3870,11 @@ void MarlinSettings::reset() {
       CONFIG_ECHO_START(); SERIAL_ECHO_SP(2); M553_report();
       CONFIG_ECHO_START(); SERIAL_ECHO_SP(2); M554_report();
     #endif
+
+    #if HAS_MULTI_LANGUAGE
+      CONFIG_ECHO_HEADING("UI Language:");
+      SERIAL_ECHO_MSG("  M414 S", int(ui.language));
+    #endif
   }
 
 #endif // !DISABLE_M503
diff --git a/buildroot/tests/FYSETC_F6-tests b/buildroot/tests/FYSETC_F6-tests
index cc7f3340991..e1eb6684a53 100755
--- a/buildroot/tests/FYSETC_F6-tests
+++ b/buildroot/tests/FYSETC_F6-tests
@@ -39,6 +39,7 @@ exec_test $1 $2 "DELTA, RAMPS, L6470, UBL, Allen Key, EEPROM, OLED_PANEL_TINYBOY
 restore_configs
 opt_set MOTHERBOARD BOARD_FYSETC_F6_13
 opt_set LCD_LANGUAGE vi
+opt_set LCD_LANGUAGE_2 fr
 opt_set X_DRIVER_TYPE TMC2160
 opt_set Y_DRIVER_TYPE TMC5160
 opt_set Z_DRIVER_TYPE TMC2208_STANDALONE
diff --git a/platformio.ini b/platformio.ini
index a32bf53d676..a142fe891a5 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -39,6 +39,7 @@ default_src_filter = +<src/*> -<src/config> -<src/HAL> +<src/HAL/shared>
   -<src/lcd/menu/menu_filament.cpp>
   -<src/lcd/menu/menu_info.cpp>
   -<src/lcd/menu/menu_job_recovery.cpp>
+  -<src/lcd/menu/menu_language.cpp>
   -<src/lcd/menu/menu_led.cpp>
   -<src/lcd/menu/menu_media.cpp>
   -<src/lcd/menu/menu_mmu2.cpp>
@@ -264,6 +265,7 @@ HAS_MENU_DELTA_CALIBRATE = src_filter=+<src/lcd/menu/menu_delta_calibrate.cpp>
 HAS_MENU_FILAMENT       = src_filter=+<src/lcd/menu/menu_filament.cpp>
 LCD_INFO_MENU           = src_filter=+<src/lcd/menu/menu_info.cpp>
 HAS_MENU_JOB_RECOVERY   = src_filter=+<src/lcd/menu/menu_job_recovery.cpp>
+HAS_MULTI_LANGUAGE      = src_filter=+<src/lcd/menu/menu_language.cpp>
 HAS_MENU_LED            = src_filter=+<src/lcd/menu/menu_led.cpp>
 HAS_MENU_MEDIA          = src_filter=+<src/lcd/menu/menu_media.cpp>
 HAS_MENU_MIXER          = src_filter=+<src/lcd/menu/menu_mixer.cpp>