diff --git a/include/Configuration.h b/include/Configuration.h index 4a802e4..013f401 100644 --- a/include/Configuration.h +++ b/include/Configuration.h @@ -5,7 +5,7 @@ #include #define CONFIG_FILENAME "/config.json" -#define CONFIG_VERSION 0x00011c00 // 0.1.28 // make sure to clean all after change +#define CONFIG_VERSION 0x00011d00 // 0.1.29 // make sure to clean all after change #define WIFI_MAX_SSID_STRLEN 32 #define WIFI_MAX_PASSWORD_STRLEN 64 @@ -30,6 +30,7 @@ #define CHAN_MAX_NAME_STRLEN 31 #define DEV_MAX_MAPPING_NAME_STRLEN 63 +#define LOCALE_STRLEN 2 struct CHANNEL_CONFIG_T { uint16_t MaxChannelPower; @@ -144,7 +145,7 @@ struct CONFIG_T { bool ScreenSaver; uint8_t Rotation; uint8_t Contrast; - uint8_t Language; + char Locale[LOCALE_STRLEN + 1]; struct { uint32_t Duration; uint8_t Mode; diff --git a/include/Display_Graphic.h b/include/Display_Graphic.h index e49bf9f..2f3287c 100644 --- a/include/Display_Graphic.h +++ b/include/Display_Graphic.h @@ -40,7 +40,7 @@ public: void setContrast(const uint8_t contrast); void setStatus(const bool turnOn); void setOrientation(const uint8_t rotation = DISPLAY_ROTATION); - void setLanguage(const uint8_t language); + void setLocale(const String& locale); void setDiagramMode(DiagramMode_t mode); void setStartupDisplay(); @@ -65,7 +65,7 @@ private: DisplayType_t _display_type = DisplayType_t::None; DiagramMode_t _diagram_mode = DiagramMode_t::Off; - uint8_t _display_language = DISPLAY_LANGUAGE; + String _display_language = DISPLAY_LOCALE; uint8_t _mExtra; const uint16_t _period = 1000; const uint16_t _interval = 60000; // interval at which to power save (milliseconds) @@ -73,6 +73,15 @@ private: char _fmtText[32]; bool _isLarge = false; uint8_t _lineOffsets[5]; + + String _i18n_offline; + String _i18n_yield_today_kwh; + String _i18n_yield_today_wh; + String _i18n_date_format; + String _i18n_current_power_kw; + String _i18n_current_power_w; + String _i18n_yield_total_mwh; + String _i18n_yield_total_kwh; }; extern DisplayGraphicClass Display; diff --git a/include/defaults.h b/include/defaults.h index 5655d72..bd16169 100644 --- a/include/defaults.h +++ b/include/defaults.h @@ -99,7 +99,7 @@ #define DISPLAY_SCREENSAVER true #define DISPLAY_ROTATION 2U #define DISPLAY_CONTRAST 60U -#define DISPLAY_LANGUAGE 0U +#define DISPLAY_LOCALE "en" #define DISPLAY_DIAGRAM_DURATION (10UL * 60UL * 60UL) #define DISPLAY_DIAGRAM_MODE 1U diff --git a/src/Configuration.cpp b/src/Configuration.cpp index db47d9c..04bcfa6 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -107,7 +107,7 @@ bool ConfigurationClass::write() display["screensaver"] = config.Display.ScreenSaver; display["rotation"] = config.Display.Rotation; display["contrast"] = config.Display.Contrast; - display["language"] = config.Display.Language; + display["locale"] = config.Display.Locale; display["diagram_duration"] = config.Display.Diagram.Duration; display["diagram_mode"] = config.Display.Diagram.Mode; @@ -282,7 +282,7 @@ bool ConfigurationClass::read() config.Display.ScreenSaver = display["screensaver"] | DISPLAY_SCREENSAVER; config.Display.Rotation = display["rotation"] | DISPLAY_ROTATION; config.Display.Contrast = display["contrast"] | DISPLAY_CONTRAST; - config.Display.Language = display["language"] | DISPLAY_LANGUAGE; + strlcpy(config.Display.Locale, display["locale"] | DISPLAY_LOCALE, sizeof(config.Display.Locale)); config.Display.Diagram.Duration = display["diagram_duration"] | DISPLAY_DIAGRAM_DURATION; config.Display.Diagram.Mode = display["diagram_mode"] | DISPLAY_DIAGRAM_MODE; @@ -383,6 +383,22 @@ void ConfigurationClass::migrate() } } + if (config.Cfg.Version < 0x00011d00) { + JsonObject device = doc["device"]; + JsonObject display = device["display"]; + switch (display["language"] | 0U) { + case 0U: + strlcpy(config.Display.Locale, "en", sizeof(config.Display.Locale)); + break; + case 1U: + strlcpy(config.Display.Locale, "de", sizeof(config.Display.Locale)); + break; + case 2U: + strlcpy(config.Display.Locale, "fr", sizeof(config.Display.Locale)); + break; + } + } + f.close(); config.Cfg.Version = CONFIG_VERSION; diff --git a/src/Display_Graphic.cpp b/src/Display_Graphic.cpp index 4433c43..69b298e 100644 --- a/src/Display_Graphic.cpp +++ b/src/Display_Graphic.cpp @@ -16,18 +16,11 @@ std::map { DisplayType_t::ST7567_GM12864I_59N, [](uint8_t reset, uint8_t clock, uint8_t data, uint8_t cs) { return new U8G2_ST7567_ENH_DG128064I_F_HW_I2C(U8G2_R0, reset, clock, data); } }, }; -// Language defintion, respect order in languages[] and translation lists +// Language defintion, respect order in translation lists #define I18N_LOCALE_EN 0 #define I18N_LOCALE_DE 1 #define I18N_LOCALE_FR 2 -// Languages supported. Note: the order is important and must match locale_translations.h -const uint8_t languages[] = { - I18N_LOCALE_EN, - I18N_LOCALE_DE, - I18N_LOCALE_FR -}; - static const char* const i18n_offline[] = { "Offline", "Offline", "Offline" }; static const char* const i18n_current_power_w[] = { "%.0f W", "%.0f W", "%.0f W" }; @@ -166,9 +159,24 @@ void DisplayGraphicClass::setOrientation(const uint8_t rotation) calcLineHeights(); } -void DisplayGraphicClass::setLanguage(const uint8_t language) +void DisplayGraphicClass::setLocale(const String& locale) { - _display_language = language < sizeof(languages) / sizeof(languages[0]) ? language : DISPLAY_LANGUAGE; + _display_language = locale; + uint8_t idx = I18N_LOCALE_EN; + if (locale == "de") { + idx = I18N_LOCALE_DE; + } else if (locale == "fr") { + idx = I18N_LOCALE_FR; + } + + _i18n_offline = i18n_offline[idx]; + _i18n_yield_today_kwh = i18n_yield_today_kwh[idx]; + _i18n_yield_today_wh = i18n_yield_today_wh[idx]; + _i18n_date_format = i18n_date_format[idx]; + _i18n_current_power_kw = i18n_current_power_kw[idx]; + _i18n_current_power_w = i18n_current_power_w[idx]; + _i18n_yield_total_mwh = i18n_yield_total_mwh[idx]; + _i18n_yield_total_kwh = i18n_yield_total_kwh[idx]; } void DisplayGraphicClass::setDiagramMode(DiagramMode_t mode) @@ -225,9 +233,9 @@ void DisplayGraphicClass::loop() if (showText) { const float watts = Datastore.getTotalAcPowerEnabled(); if (watts > 999) { - snprintf(_fmtText, sizeof(_fmtText), i18n_current_power_kw[_display_language], watts / 1000); + snprintf(_fmtText, sizeof(_fmtText), _i18n_current_power_kw.c_str(), watts / 1000); } else { - snprintf(_fmtText, sizeof(_fmtText), i18n_current_power_w[_display_language], watts); + snprintf(_fmtText, sizeof(_fmtText), _i18n_current_power_w.c_str(), watts); } printText(_fmtText, 0); } @@ -237,7 +245,7 @@ void DisplayGraphicClass::loop() //=====> Offline =========== else { - printText(i18n_offline[_display_language], 0); + printText(_i18n_offline.c_str(), 0); // check if it's time to enter power saving mode if (millis() - _previousMillis >= (_interval * 2)) { displayPowerSave = enablePowerSafe; @@ -249,16 +257,16 @@ void DisplayGraphicClass::loop() // Daily production float wattsToday = Datastore.getTotalAcYieldDayEnabled(); if (wattsToday >= 10000) { - snprintf(_fmtText, sizeof(_fmtText), i18n_yield_today_kwh[_display_language], wattsToday / 1000); + snprintf(_fmtText, sizeof(_fmtText), _i18n_yield_today_kwh.c_str(), wattsToday / 1000); } else { - snprintf(_fmtText, sizeof(_fmtText), i18n_yield_today_wh[_display_language], wattsToday); + snprintf(_fmtText, sizeof(_fmtText), _i18n_yield_today_wh.c_str(), wattsToday); } printText(_fmtText, 1); // Total production const float wattsTotal = Datastore.getTotalAcYieldTotalEnabled(); - auto const format = (wattsTotal >= 1000) ? i18n_yield_total_mwh : i18n_yield_total_kwh; - snprintf(_fmtText, sizeof(_fmtText), format[_display_language], wattsTotal); + auto const format = (wattsTotal >= 1000) ? _i18n_yield_total_mwh : _i18n_yield_total_kwh; + snprintf(_fmtText, sizeof(_fmtText), format.c_str(), wattsTotal); printText(_fmtText, 2); //=====> IP or Date-Time ======== @@ -268,7 +276,7 @@ void DisplayGraphicClass::loop() } else { // Get current time time_t now = time(nullptr); - strftime(_fmtText, sizeof(_fmtText), i18n_date_format[_display_language], localtime(&now)); + strftime(_fmtText, sizeof(_fmtText), _i18n_date_format.c_str(), localtime(&now)); printText(_fmtText, 3); } } diff --git a/src/WebApi_device.cpp b/src/WebApi_device.cpp index 29686fe..cfe8803 100644 --- a/src/WebApi_device.cpp +++ b/src/WebApi_device.cpp @@ -86,7 +86,7 @@ void WebApiDeviceClass::onDeviceAdminGet(AsyncWebServerRequest* request) display["power_safe"] = config.Display.PowerSafe; display["screensaver"] = config.Display.ScreenSaver; display["contrast"] = config.Display.Contrast; - display["language"] = config.Display.Language; + display["locale"] = config.Display.Locale; display["diagramduration"] = config.Display.Diagram.Duration; display["diagrammode"] = config.Display.Diagram.Mode; @@ -137,7 +137,7 @@ void WebApiDeviceClass::onDeviceAdminPost(AsyncWebServerRequest* request) config.Display.PowerSafe = root["display"]["power_safe"].as(); config.Display.ScreenSaver = root["display"]["screensaver"].as(); config.Display.Contrast = root["display"]["contrast"].as(); - config.Display.Language = root["display"]["language"].as(); + strlcpy(config.Display.Locale, root["display"]["locale"].as().c_str(), sizeof(config.Display.Locale)); config.Display.Diagram.Duration = root["display"]["diagramduration"].as(); config.Display.Diagram.Mode = root["display"]["diagrammode"].as(); @@ -151,7 +151,7 @@ void WebApiDeviceClass::onDeviceAdminPost(AsyncWebServerRequest* request) Display.enablePowerSafe = config.Display.PowerSafe; Display.enableScreensaver = config.Display.ScreenSaver; Display.setContrast(config.Display.Contrast); - Display.setLanguage(config.Display.Language); + Display.setLocale(config.Display.Locale); Display.Diagram().updatePeriod(); WebApi.writeConfig(retMsg); diff --git a/src/main.cpp b/src/main.cpp index 7f4ac56..9578b30 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -143,7 +143,7 @@ void setup() Display.enablePowerSafe = config.Display.PowerSafe; Display.enableScreensaver = config.Display.ScreenSaver; Display.setContrast(config.Display.Contrast); - Display.setLanguage(config.Display.Language); + Display.setLocale(config.Display.Locale); Display.setStartupDisplay(); MessageOutput.println("done"); diff --git a/webapp/src/types/DeviceConfig.ts b/webapp/src/types/DeviceConfig.ts index e47fca7..eec9e0b 100644 --- a/webapp/src/types/DeviceConfig.ts +++ b/webapp/src/types/DeviceConfig.ts @@ -5,7 +5,7 @@ export interface Display { power_safe: boolean; screensaver: boolean; contrast: number; - language: number; + locale: string; diagramduration: number; diagrammode: number; } diff --git a/webapp/src/views/DeviceAdminView.vue b/webapp/src/views/DeviceAdminView.vue index df37415..8a554f7 100644 --- a/webapp/src/views/DeviceAdminView.vue +++ b/webapp/src/views/DeviceAdminView.vue @@ -160,13 +160,13 @@ {{ $t('deviceadmin.DisplayLanguage') }}
-
@@ -289,10 +289,10 @@ export default defineComponent({ { key: 2, value: 'rot180' }, { key: 3, value: 'rot270' }, ], - displayLanguageList: [ - { key: 0, value: 'en' }, - { key: 1, value: 'de' }, - { key: 2, value: 'fr' }, + displayLocaleList: [ + { key: 'en', value: 'en' }, + { key: 'de', value: 'de' }, + { key: 'fr', value: 'fr' }, ], diagramModeList: [ { key: 0, value: 'off' },