MarlinUI multi-language support (#20725)

This commit is contained in:
Scott Lahteine 2021-01-20 18:52:06 -06:00
parent befcdeb74d
commit 3dde2722bd
16 changed files with 202 additions and 26 deletions

View File

@ -1526,6 +1526,16 @@
#endif #endif
#endif // HAS_DGUS_LCD #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) // Touch UI for the FTDI Embedded Video Engine (EVE)
// //
@ -1601,13 +1611,6 @@
// Use a smaller font when labels don't fit buttons // Use a smaller font when labels don't fit buttons
#define TOUCH_UI_FIT_TEXT #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. // Use a numeric passcode for "Screen lock" keypad.
// (recommended for smaller displays) // (recommended for smaller displays)
//#define TOUCH_UI_PASSCODE //#define TOUCH_UI_PASSCODE

View File

@ -20,6 +20,8 @@
****************************************************************************/ ****************************************************************************/
#pragma once #pragma once
#include "../inc/MarlinConfigPre.h"
typedef const char Language_Str[]; typedef const char Language_Str[];
#ifdef LCD_LANGUAGE_5 #ifdef LCD_LANGUAGE_5
@ -57,14 +59,13 @@ typedef const char Language_Str[];
#define GET_LANG(LANG) _GET_LANG(LANG) #define GET_LANG(LANG) _GET_LANG(LANG)
#if NUM_LANGUAGES > 1 #if NUM_LANGUAGES > 1
extern uint8_t lang; #define HAS_MULTI_LANGUAGE 1
#define GET_TEXT(MSG) ( \ #define GET_TEXT(MSG) ( \
lang == 0 ? GET_LANG(LCD_LANGUAGE)::MSG : \ ui.language == 0 ? GET_LANG(LCD_LANGUAGE )::MSG : \
lang == 1 ? GET_LANG(LCD_LANGUAGE_2)::MSG : \ ui.language == 1 ? GET_LANG(LCD_LANGUAGE_2)::MSG : \
lang == 2 ? GET_LANG(LCD_LANGUAGE_3)::MSG : \ ui.language == 2 ? GET_LANG(LCD_LANGUAGE_3)::MSG : \
lang == 3 ? GET_LANG(LCD_LANGUAGE_4)::MSG : \ ui.language == 3 ? GET_LANG(LCD_LANGUAGE_4)::MSG : \
GET_LANG(LCD_LANGUAGE_5)::MSG \ GET_LANG(LCD_LANGUAGE_5)::MSG )
)
#define MAX_LANG_CHARSIZE _MAX(GET_LANG(LCD_LANGUAGE )::CHARSIZE, \ #define MAX_LANG_CHARSIZE _MAX(GET_LANG(LCD_LANGUAGE )::CHARSIZE, \
GET_LANG(LCD_LANGUAGE_2)::CHARSIZE, \ GET_LANG(LCD_LANGUAGE_2)::CHARSIZE, \
GET_LANG(LCD_LANGUAGE_3)::CHARSIZE, \ GET_LANG(LCD_LANGUAGE_3)::CHARSIZE, \
@ -72,11 +73,13 @@ typedef const char Language_Str[];
GET_LANG(LCD_LANGUAGE_5)::CHARSIZE ) GET_LANG(LCD_LANGUAGE_5)::CHARSIZE )
#else #else
#define GET_TEXT(MSG) GET_LANG(LCD_LANGUAGE)::MSG #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 #endif
#define GET_TEXT_F(MSG) (const __FlashStringHelper*)GET_TEXT(MSG) #define GET_TEXT_F(MSG) (const __FlashStringHelper*)GET_TEXT(MSG)
#define GET_LANGUAGE_NAME(INDEX) GET_LANG(LCD_LANGUAGE_##INDEX)::LANGUAGE #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_1_LINE(A) A "\0" "\0"
#define MSG_2_LINE(A,B) A "\0" B "\0" #define MSG_2_LINE(A,B) A "\0" B "\0"

View File

@ -718,6 +718,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 412: M412(); break; // M412: Enable/Disable filament runout detection case 412: M412(); break; // M412: Enable/Disable filament runout detection
#endif #endif
#if HAS_MULTI_LANGUAGE
case 414: M414(); break; // M414: Select multi language menu
#endif
#if HAS_LEVELING #if HAS_LEVELING
case 420: M420(); break; // M420: Enable/Disable Bed Leveling case 420: M420(); break; // M420: Enable/Disable Bed Leveling
#endif #endif

View File

@ -213,6 +213,7 @@
* M410 - Quickstop. Abort all planned moves. * M410 - Quickstop. Abort all planned moves.
* M412 - Enable / Disable Filament Runout Detection. (Requires FILAMENT_RUNOUT_SENSOR) * M412 - Enable / Disable Filament Runout Detection. (Requires FILAMENT_RUNOUT_SENSOR)
* M413 - Enable / Disable Power-Loss Recovery. (Requires POWER_LOSS_RECOVERY) * 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) * 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) * 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) * 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_FILAMENT_SENSOR, static void M412());
TERN_(HAS_MULTI_LANGUAGE, static void M414());
#if HAS_LEVELING #if HAS_LEVELING
static void M420(); static void M420();
static void M421(); static void M421();

View File

@ -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

View File

@ -55,3 +55,5 @@
#include "../core/serial.h" #include "../core/serial.h"
#endif #endif
#include "../core/multi_language.h"

View File

@ -54,6 +54,7 @@
#include "../../sd/cardreader.h" #include "../../sd/cardreader.h"
#include "../../module/temperature.h" #include "../../module/temperature.h"
#include "../../module/printcounter.h" #include "../../module/printcounter.h"
#include "../../MarlinCore.h"
#if ENABLED(SDSUPPORT) #if ENABLED(SDSUPPORT)
#include "../../libs/duration_t.h" #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) { 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), const u8g_uint_t len = utf8_strlen_P(pstr),
by = (y + 1) * (MENU_FONT_HEIGHT); 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) { if (inv) {
u8g.setColorIndex(1); 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); u8g.setColorIndex(0);
} }
lcd_put_u8str_P(bx, by, pstr); lcd_put_u8str_P(bx / prop, by, pstr);
if (inv) u8g.setColorIndex(1); 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*/) { 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); ui.draw_select_screen_prompt(pref, string, suff);
draw_boxed_string(1, LCD_HEIGHT - 1, no, !yesno); 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) #if ENABLED(SDSUPPORT)

View File

@ -64,7 +64,6 @@ static const char assets[][LONG_FILENAME_LENGTH] = {
"bmp_speed255.bin", "bmp_speed255.bin",
"bmp_speed127.bin", "bmp_speed127.bin",
"bmp_speed0.bin", "bmp_speed0.bin",
"bmp_speed0.bin",
"bmp_bed.bin", "bmp_bed.bin",
"bmp_step1_degree.bin", "bmp_step1_degree.bin",

View File

@ -28,6 +28,7 @@
#if HAS_WIRED_LCD && !HAS_GRAPHICAL_TFT #if HAS_WIRED_LCD && !HAS_GRAPHICAL_TFT
#include "marlinui.h"
#include "lcdprint.h" #include "lcdprint.h"
/** /**

View File

@ -78,6 +78,10 @@ constexpr uint8_t epps = ENCODER_PULSES_PER_STEP;
#endif #endif
#endif #endif
#if HAS_MULTI_LANGUAGE
uint8_t MarlinUI::language; // Initialized by settings.load()
#endif
#if ENABLED(SOUND_MENU_ITEM) #if ENABLED(SOUND_MENU_ITEM)
bool MarlinUI::buzzer_enabled = true; bool MarlinUI::buzzer_enabled = true;
#endif #endif

View File

@ -178,6 +178,17 @@ public:
TERN_(HAS_LCD_MENU, currentScreen = status_screen); 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) #if ENABLED(SOUND_MENU_ITEM)
static bool buzzer_enabled; // Initialized by settings.load() static bool buzzer_enabled; // Initialized by settings.load()
#else #else

View File

@ -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

View File

@ -97,6 +97,10 @@ void menu_configuration();
void menu_spindle_laser(); void menu_spindle_laser();
#endif #endif
#if HAS_MULTI_LANGUAGE
void menu_language();
#endif
extern const char M21_STR[]; extern const char M21_STR[];
void menu_main() { void menu_main() {
@ -325,6 +329,10 @@ void menu_main() {
} }
#endif #endif
#if HAS_MULTI_LANGUAGE
SUBMENU(LANGUAGE, menu_language);
#endif
END_MENU(); END_MENU();
} }

View File

@ -36,7 +36,7 @@
*/ */
// Change EEPROM version if the structure changes // Change EEPROM version if the structure changes
#define EEPROM_VERSION "V82" #define EEPROM_VERSION "V83"
#define EEPROM_OFFSET 100 #define EEPROM_OFFSET 100
// Check the integrity of data offsets. // Check the integrity of data offsets.
@ -457,6 +457,11 @@ typedef struct SettingsDataStruct {
#if ENABLED(SOUND_MENU_ITEM) #if ENABLED(SOUND_MENU_ITEM)
bool buzzer_enabled; bool buzzer_enabled;
#endif #endif
#if HAS_MULTI_LANGUAGE
uint8_t ui_language; // M414 S
#endif
} SettingsData; } SettingsData;
//static_assert(sizeof(SettingsData) <= MARLIN_EEPROM_SIZE, "EEPROM too small to contain 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); EEPROM_WRITE(ui.buzzer_enabled);
#endif #endif
//
// Selected LCD language
//
#if HAS_MULTI_LANGUAGE
EEPROM_WRITE(ui.language);
#endif
// //
// Report final CRC and Data Size // Report final CRC and Data Size
// //
@ -2261,6 +2273,18 @@ void MarlinSettings::postprocess() {
EEPROM_READ(ui.buzzer_enabled); EEPROM_READ(ui.buzzer_enabled);
#endif #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 // 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); M553_report();
CONFIG_ECHO_START(); SERIAL_ECHO_SP(2); M554_report(); CONFIG_ECHO_START(); SERIAL_ECHO_SP(2); M554_report();
#endif #endif
#if HAS_MULTI_LANGUAGE
CONFIG_ECHO_HEADING("UI Language:");
SERIAL_ECHO_MSG(" M414 S", int(ui.language));
#endif
} }
#endif // !DISABLE_M503 #endif // !DISABLE_M503

View File

@ -39,6 +39,7 @@ exec_test $1 $2 "DELTA, RAMPS, L6470, UBL, Allen Key, EEPROM, OLED_PANEL_TINYBOY
restore_configs restore_configs
opt_set MOTHERBOARD BOARD_FYSETC_F6_13 opt_set MOTHERBOARD BOARD_FYSETC_F6_13
opt_set LCD_LANGUAGE vi opt_set LCD_LANGUAGE vi
opt_set LCD_LANGUAGE_2 fr
opt_set X_DRIVER_TYPE TMC2160 opt_set X_DRIVER_TYPE TMC2160
opt_set Y_DRIVER_TYPE TMC5160 opt_set Y_DRIVER_TYPE TMC5160
opt_set Z_DRIVER_TYPE TMC2208_STANDALONE opt_set Z_DRIVER_TYPE TMC2208_STANDALONE

View File

@ -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_filament.cpp>
-<src/lcd/menu/menu_info.cpp> -<src/lcd/menu/menu_info.cpp>
-<src/lcd/menu/menu_job_recovery.cpp> -<src/lcd/menu/menu_job_recovery.cpp>
-<src/lcd/menu/menu_language.cpp>
-<src/lcd/menu/menu_led.cpp> -<src/lcd/menu/menu_led.cpp>
-<src/lcd/menu/menu_media.cpp> -<src/lcd/menu/menu_media.cpp>
-<src/lcd/menu/menu_mmu2.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> HAS_MENU_FILAMENT = src_filter=+<src/lcd/menu/menu_filament.cpp>
LCD_INFO_MENU = src_filter=+<src/lcd/menu/menu_info.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_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_LED = src_filter=+<src/lcd/menu/menu_led.cpp>
HAS_MENU_MEDIA = src_filter=+<src/lcd/menu/menu_media.cpp> HAS_MENU_MEDIA = src_filter=+<src/lcd/menu/menu_media.cpp>
HAS_MENU_MIXER = src_filter=+<src/lcd/menu/menu_mixer.cpp> HAS_MENU_MIXER = src_filter=+<src/lcd/menu/menu_mixer.cpp>