Feature: Implement language pack support for display texts

This commit is contained in:
Thomas Basler 2024-10-25 22:38:55 +02:00
parent d259042542
commit 70f301941b
4 changed files with 114 additions and 16 deletions

View File

@ -16,7 +16,14 @@ public:
I18nClass(); I18nClass();
void init(Scheduler& scheduler); void init(Scheduler& scheduler);
std::list<LanguageInfo_t> getAvailableLanguages(); std::list<LanguageInfo_t> getAvailableLanguages();
String getFilenameByLocale(String& locale) const; String getFilenameByLocale(const String& locale) const;
void readDisplayStrings(
const String& locale,
String& date_format,
String& offline,
String& power_w, String& power_kw,
String& yield_today_wh, String& yield_today_kwh,
String& yield_total_kwh, String& yield_total_mwh);
private: private:
void readLangPacks(); void readLangPacks();

View File

@ -4,6 +4,7 @@
*/ */
#include "Display_Graphic.h" #include "Display_Graphic.h"
#include "Datastore.h" #include "Datastore.h"
#include "I18n.h"
#include <NetworkSettings.h> #include <NetworkSettings.h>
#include <map> #include <map>
#include <time.h> #include <time.h>
@ -169,14 +170,24 @@ void DisplayGraphicClass::setLocale(const String& locale)
idx = I18N_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_date_format = i18n_date_format[idx];
_i18n_current_power_kw = i18n_current_power_kw[idx]; _i18n_offline = i18n_offline[idx];
_i18n_current_power_w = i18n_current_power_w[idx]; _i18n_current_power_w = i18n_current_power_w[idx];
_i18n_yield_total_mwh = i18n_yield_total_mwh[idx]; _i18n_current_power_kw = i18n_current_power_kw[idx];
_i18n_yield_today_wh = i18n_yield_today_wh[idx];
_i18n_yield_today_kwh = i18n_yield_today_kwh[idx];
_i18n_yield_total_kwh = i18n_yield_total_kwh[idx]; _i18n_yield_total_kwh = i18n_yield_total_kwh[idx];
_i18n_yield_total_mwh = i18n_yield_total_mwh[idx];
I18n.readDisplayStrings(locale,
_i18n_date_format,
_i18n_offline,
_i18n_current_power_w,
_i18n_current_power_kw,
_i18n_yield_today_wh,
_i18n_yield_today_kwh,
_i18n_yield_total_kwh,
_i18n_yield_total_mwh);
} }
void DisplayGraphicClass::setDiagramMode(DiagramMode_t mode) void DisplayGraphicClass::setDiagramMode(DiagramMode_t mode)

View File

@ -25,7 +25,7 @@ std::list<LanguageInfo_t> I18nClass::getAvailableLanguages()
return _availLanguages; return _availLanguages;
} }
String I18nClass::getFilenameByLocale(String& locale) const String I18nClass::getFilenameByLocale(const String& locale) const
{ {
auto it = std::find_if(_availLanguages.begin(), _availLanguages.end(), [locale](const LanguageInfo_t& elem) { auto it = std::find_if(_availLanguages.begin(), _availLanguages.end(), [locale](const LanguageInfo_t& elem) {
return elem.code == locale; return elem.code == locale;
@ -38,6 +38,75 @@ String I18nClass::getFilenameByLocale(String& locale) const
} }
} }
void I18nClass::readDisplayStrings(
const String& locale,
String& date_format,
String& offline,
String& power_w, String& power_kw,
String& yield_today_wh, String& yield_today_kwh,
String& yield_total_kwh, String& yield_total_mwh)
{
auto filename = getFilenameByLocale(locale);
if (filename == "") {
return;
}
JsonDocument filter;
filter["display"] = true;
File f = LittleFS.open(filename, "r", false);
JsonDocument doc;
// Deserialize the JSON document
const DeserializationError error = deserializeJson(doc, f, DeserializationOption::Filter(filter));
if (error) {
MessageOutput.printf("Failed to read file %s\r\n", filename.c_str());
f.close();
return;
}
if (!Utils::checkJsonAlloc(doc, __FUNCTION__, __LINE__)) {
return;
}
auto displayData = doc["display"];
if (displayData["date_format"].as<String>() != "null") {
date_format = displayData["date_format"].as<String>();
}
if (displayData["offline"].as<String>() != "null") {
offline = displayData["offline"].as<String>();
}
if (displayData["power_w"].as<String>() != "null") {
power_w = displayData["power_w"].as<String>();
}
if (displayData["power_kw"].as<String>() != "null") {
power_kw = displayData["power_kw"].as<String>();
}
if (displayData["yield_today_wh"].as<String>() != "null") {
yield_today_wh = displayData["yield_today_wh"].as<String>();
}
if (displayData["yield_today_kwh"].as<String>() != "null") {
yield_today_kwh = displayData["yield_today_kwh"].as<String>();
}
if (displayData["yield_total_kwh"].as<String>() != "null") {
yield_total_kwh = displayData["yield_total_kwh"].as<String>();
}
if (displayData["yield_total_mwh"].as<String>() != "null") {
yield_total_mwh = displayData["yield_total_mwh"].as<String>();
}
f.close();
}
void I18nClass::readLangPacks() void I18nClass::readLangPacks()
{ {
auto root = LittleFS.open("/"); auto root = LittleFS.open("/");
@ -79,7 +148,7 @@ void I18nClass::readConfig(String file)
lang.name = String(doc["meta"]["name"] | ""); lang.name = String(doc["meta"]["name"] | "");
lang.filename = file; lang.filename = file;
if (lang.code != "" && lang.name != "") { if (lang.code != "" && lang.name != "") {
_availLanguages.push_back(lang); _availLanguages.push_back(lang);
} else { } else {
MessageOutput.printf("Invalid meta data\r\n"); MessageOutput.printf("Invalid meta data\r\n");

View File

@ -1,5 +1,5 @@
<template> <template>
<BasePage :title="$t('deviceadmin.DeviceManager')" :isLoading="dataLoading || pinMappingLoading"> <BasePage :title="$t('deviceadmin.DeviceManager')" :isLoading="dataLoading || pinMappingLoading || languageLoading">
<BootstrapAlert v-model="showAlert" dismissible :variant="alertType"> <BootstrapAlert v-model="showAlert" dismissible :variant="alertType">
{{ alertMessage }} {{ alertMessage }}
</BootstrapAlert> </BootstrapAlert>
@ -162,11 +162,11 @@
<div class="col-sm-10"> <div class="col-sm-10">
<select class="form-select" v-model="deviceConfigList.display.locale"> <select class="form-select" v-model="deviceConfigList.display.locale">
<option <option
v-for="locale in displayLocaleList" v-for="(locale, index) in displayLocaleList"
:key="locale.key" :key="locale.code"
:value="locale.key" :value="locale.code"
> >
{{ $t(`deviceadmin.` + locale.value) }} {{ $t((index < 3 ? `deviceadmin.` : ``) + locale.name) }}
</option> </option>
</select> </select>
</div> </div>
@ -277,6 +277,7 @@ export default defineComponent({
return { return {
dataLoading: true, dataLoading: true,
pinMappingLoading: true, pinMappingLoading: true,
languageLoading: true,
deviceConfigList: {} as DeviceConfig, deviceConfigList: {} as DeviceConfig,
pinMappingList: {} as PinMapping, pinMappingList: {} as PinMapping,
alertMessage: '', alertMessage: '',
@ -290,9 +291,9 @@ export default defineComponent({
{ key: 3, value: 'rot270' }, { key: 3, value: 'rot270' },
], ],
displayLocaleList: [ displayLocaleList: [
{ key: 'en', value: 'en' }, { code: 'en', name: 'en' },
{ key: 'de', value: 'de' }, { code: 'de', name: 'de' },
{ key: 'fr', value: 'fr' }, { code: 'fr', name: 'fr' },
], ],
diagramModeList: [ diagramModeList: [
{ key: 0, value: 'off' }, { key: 0, value: 'off' },
@ -304,6 +305,7 @@ export default defineComponent({
created() { created() {
this.getDeviceConfig(); this.getDeviceConfig();
this.getPinMappingList(); this.getPinMappingList();
this.getLanguageList();
}, },
watch: { watch: {
equalBrightnessCheckVal: function (val) { equalBrightnessCheckVal: function (val) {
@ -314,6 +316,15 @@ export default defineComponent({
}, },
}, },
methods: { methods: {
getLanguageList() {
this.languageLoading = true;
fetch('/api/i18n/languages')
.then((response) => handleResponse(response, this.$emitter, this.$router))
.then((data) => {
this.displayLocaleList.push(...data);
this.languageLoading = false;
});
},
getPinMappingList() { getPinMappingList() {
this.pinMappingLoading = true; this.pinMappingLoading = true;
fetch('/api/file/get?file=pin_mapping.json', { headers: authHeader() }) fetch('/api/file/get?file=pin_mapping.json', { headers: authHeader() })