From 4f90a5e4261cd6388a8aee5d8d2e603ed150b3e6 Mon Sep 17 00:00:00 2001 From: philmoz Date: Thu, 8 Jan 2026 13:34:22 +1100 Subject: [PATCH] feat: add a separate setting for selecting 'text language' when ALL_LANGS is set (#6960) --- .../firmwares/edgetx/yaml_generalsettings.cpp | 2 + companion/src/firmwares/generalsettings.cpp | 6 +- companion/src/firmwares/generalsettings.h | 1 + companion/src/generaledit/generalsetup.cpp | 166 ++++++++++++++---- companion/src/generaledit/generalsetup.h | 4 +- companion/src/generaledit/generalsetup.ui | 40 +++-- radio/src/datastructs.h | 10 +- radio/src/datastructs_private.h | 1 + radio/src/edgetx.cpp | 8 + radio/src/edgetx.h | 1 + radio/src/gui/128x64/radio_setup.cpp | 32 +++- radio/src/gui/212x64/radio_setup.cpp | 32 +++- radio/src/gui/colorlcd/radio/radio_setup.cpp | 51 ++++-- radio/src/lua/api_general.cpp | 4 +- radio/src/lua/lua_widget_factory.cpp | 4 +- radio/src/storage/sdcard_common.cpp | 18 +- .../storage/yaml/yaml_datastructs_128x64.cpp | 1 + .../src/storage/yaml/yaml_datastructs_f16.cpp | 1 + .../storage/yaml/yaml_datastructs_gx12.cpp | 1 + .../storage/yaml/yaml_datastructs_nb4p.cpp | 1 + .../storage/yaml/yaml_datastructs_nv14.cpp | 1 + .../storage/yaml/yaml_datastructs_pa01.cpp | 1 + .../storage/yaml/yaml_datastructs_pl18.cpp | 1 + .../storage/yaml/yaml_datastructs_pl18u.cpp | 1 + .../storage/yaml/yaml_datastructs_st16.cpp | 1 + .../src/storage/yaml/yaml_datastructs_t15.cpp | 1 + .../storage/yaml/yaml_datastructs_t15pro.cpp | 1 + .../src/storage/yaml/yaml_datastructs_t20.cpp | 1 + .../storage/yaml/yaml_datastructs_tpro.cpp | 1 + .../storage/yaml/yaml_datastructs_tx15.cpp | 1 + .../src/storage/yaml/yaml_datastructs_x10.cpp | 1 + .../src/storage/yaml/yaml_datastructs_x9d.cpp | 1 + .../yaml/yaml_datastructs_x9dp2019.cpp | 1 + .../src/storage/yaml/yaml_datastructs_x9e.cpp | 1 + .../storage/yaml/yaml_datastructs_xlite.cpp | 1 + .../storage/yaml/yaml_datastructs_xlites.cpp | 1 + radio/src/translations/i18n/cn.h | 1 + radio/src/translations/i18n/cz.h | 1 + radio/src/translations/i18n/da.h | 1 + radio/src/translations/i18n/de.h | 1 + radio/src/translations/i18n/en.h | 1 + radio/src/translations/i18n/es.h | 1 + radio/src/translations/i18n/fi.h | 1 + radio/src/translations/i18n/fr.h | 1 + radio/src/translations/i18n/he.h | 1 + radio/src/translations/i18n/it.h | 1 + radio/src/translations/i18n/jp.h | 1 + radio/src/translations/i18n/ko.h | 1 + radio/src/translations/i18n/nl.h | 1 + radio/src/translations/i18n/pl.h | 1 + radio/src/translations/i18n/pt.h | 1 + radio/src/translations/i18n/ru.h | 1 + radio/src/translations/i18n/se.h | 1 + radio/src/translations/i18n/tw.h | 1 + radio/src/translations/i18n/ua.h | 1 + radio/src/translations/sim_string_list.h | 1 + radio/src/translations/string_list.h | 1 + radio/src/translations/translations.cpp | 23 +++ radio/src/translations/translations.h | 2 + radio/src/translations/tts/tts.h | 1 + 60 files changed, 352 insertions(+), 95 deletions(-) diff --git a/companion/src/firmwares/edgetx/yaml_generalsettings.cpp b/companion/src/firmwares/edgetx/yaml_generalsettings.cpp index 790c59203..103ac42cd 100644 --- a/companion/src/firmwares/edgetx/yaml_generalsettings.cpp +++ b/companion/src/firmwares/edgetx/yaml_generalsettings.cpp @@ -292,6 +292,7 @@ Node convert::encode(const GeneralSettings& rhs) node["imperial"] = rhs.imperial; node["ppmunit"] = rhs.ppmunit; node["ttsLanguage"] = rhs.ttsLanguage; + node["uiLanguage"] = rhs.uiLanguage; node["beepVolume"] = rhs.beepVolume + 2; node["wavVolume"] = rhs.wavVolume + 2; node["varioVolume"] = rhs.varioVolume + 2; @@ -573,6 +574,7 @@ bool convert::decode(const Node& node, GeneralSettings& rhs) node["imperial"] >> rhs.imperial; node["ppmunit"] >> rhs.ppmunit; node["ttsLanguage"] >> rhs.ttsLanguage; + node["uiLanguage"] >> rhs.uiLanguage; node["beepVolume"] >> ioffset_int(rhs.beepVolume, 2); node["wavVolume"] >> ioffset_int(rhs.wavVolume, 2); node["varioVolume"] >> ioffset_int(rhs.varioVolume, 2); diff --git a/companion/src/firmwares/generalsettings.cpp b/companion/src/firmwares/generalsettings.cpp index 5ca06b708..287a2d8ec 100644 --- a/companion/src/firmwares/generalsettings.cpp +++ b/companion/src/firmwares/generalsettings.cpp @@ -233,12 +233,14 @@ void GeneralSettings::init() internalModule = g.profile[g.sessionId()].defaultInternalModule(); QString lang = getCurrentFirmware()->getLanguage(); - if (lang.size() > 1) + if (lang.size() > 1) { memcpy(ttsLanguage, lang.toLatin1().data(), 2); - else { + } else { ttsLanguage[0] = 'e'; ttsLanguage[1] = 'n'; } + ttsLanguage[2] = 0; + memcpy(uiLanguage, ttsLanguage, 3); stickDeadZone = (IS_FLYSKY_NV14(board) || IS_FAMILY_PL18(board)) ? 2 : 0; setDefaultFavorites(); diff --git a/companion/src/firmwares/generalsettings.h b/companion/src/firmwares/generalsettings.h index 5cf884e56..f29b68333 100644 --- a/companion/src/firmwares/generalsettings.h +++ b/companion/src/firmwares/generalsettings.h @@ -367,6 +367,7 @@ class GeneralSettings { unsigned int imperial; unsigned int ppmunit; char ttsLanguage[TTS_LANGUAGE_LEN + 1]; + char uiLanguage[TTS_LANGUAGE_LEN + 1]; int beepVolume; int wavVolume; int varioVolume; diff --git a/companion/src/generaledit/generalsetup.cpp b/companion/src/generaledit/generalsetup.cpp index a564effcf..5869b9779 100644 --- a/companion/src/generaledit/generalsetup.cpp +++ b/companion/src/generaledit/generalsetup.cpp @@ -115,8 +115,9 @@ ui(new Ui::GeneralSetup) ui->voiceLang_CB->hide(); } else { - populateVoiceLangCB(); + populateVoiceLangCB(ui->voiceLang_CB, generalSettings.ttsLanguage); } + populateTextLangCB(ui->textLang_CB, generalSettings.uiLanguage, Boards::getCapability(board, Board::HasColorLcd)); if (!firmware->getCapability(MavlinkTelemetry)) { ui->mavbaud_CB->hide(); @@ -124,7 +125,6 @@ ui(new Ui::GeneralSetup) } else { ui->mavbaud_CB->setCurrentIndex(generalSettings.mavbaud); - // TODO why ??? populateVoiceLangCB(ui->voiceLang_CB, generalSettings.ttsLanguage); } if (!firmware->getCapability(HasSoundMixer)) { @@ -396,38 +396,130 @@ void GeneralSetupPanel::on_timezoneLE_textEdited(const QString &text) } } -void GeneralSetupPanel::populateVoiceLangCB() +// Copied from tts.h +enum RadioLanguage { + LANG_CN, + LANG_CZ, + LANG_DA, + LANG_DE, + LANG_EN, + LANG_ES, + LANG_FI, + LANG_FR, + LANG_HE, + LANG_HU, + LANG_IT, + LANG_JP, + LANG_KO, + LANG_NL, + LANG_PL, + LANG_PT, + LANG_RU, + LANG_SE, + LANG_SK, + LANG_TW, + LANG_UA, + LANG_COUNT +}; + +// Order must match RadioLanguage +// Note: these align with the radio NOT computer locales - TODO harmonise with ISO and one list!!! +static const char* langStrings[][2] = { + { "Chinese", "cn" }, + { "Czech", "cz" }, + { "Danish", "da" }, + { "German", "de" }, + { "English", "en" }, + { "Spanish", "es" }, + { "Finnish", "fi" }, + { "French", "fr" }, + { "Hebrew", "he" }, + { "Hungarian", "hu" }, + { "Italian", "it" }, + { "Japanese", "jp" }, + { "Korean", "ko" }, + { "Dutch", "nl" }, + { "Polish", "pl" }, + { "Portuguese", "pt" }, + { "Russian", "ru" }, + { "Swedish", "se" }, + { "Slovak", "sk" }, + { "Taiwanese", "tw" }, + { "Ukrainian", "ua" }, +}; + +void GeneralSetupPanel::populateVoiceLangCB(QComboBox* b, const char* currLang) { - QComboBox * b = ui->voiceLang_CB; - // Note: these align with the radio NOT computer locales - TODO harmonise with ISO and one list!!! - static QString strings[][2] = { - { tr("Chinese"), "cn" }, - { tr("Czech"), "cz" }, - { tr("Danish"), "da" }, - { tr("Dutch"), "nl" }, - { tr("English"), "en" }, - { tr("Finnish"), "fi" }, - { tr("French"), "fr" }, - { tr("German"), "de" }, - { tr("Hebrew"), "he" }, - { tr("Hungarian"), "hu" }, - { tr("Italian"), "it" }, - { tr("Japanese"), "jp" }, - { tr("Korean"), "ko" }, - { tr("Polish"), "pl" }, - { tr("Portuguese"), "pt" }, - { tr("Russian"), "ru" }, - { tr("Slovak"), "sk" }, - { tr("Spanish"), "es" }, - { tr("Swedish"), "se" }, - { tr("Taiwanese"), "tw" }, - { tr("Ukrainian"), "ua" }, - { NULL, NULL }}; + b->clear(); + for (int i = 0; i < LANG_COUNT; i++) { + b->addItem(tr(langStrings[i][0]), langStrings[i][1]); + if (strncmp(currLang, langStrings[i][1], 2) == 0) { + b->setCurrentIndex(b->count() - 1); + } + } +} + +void GeneralSetupPanel::populateTextLangCB(QComboBox* b, const char* currLang, bool isColor) +{ + // Available text languages + // B&W + static RadioLanguage bwLangs[] = { + // LANG_CN, // no fonts + LANG_CZ, + LANG_DA, + LANG_DE, + LANG_EN, + LANG_ES, + LANG_FI, + LANG_FR, + // LANG_HE, // no fonts + // LANG_HU, // no translation file + LANG_IT, + // LANG_JP, // no fonts + // LANG_KO, // no fonts + LANG_NL, + LANG_PL, + LANG_PT, + LANG_RU, + LANG_SE, + // LANG_SK, // no translation file + // LANG_TW, // no fonts + LANG_UA, + LANG_COUNT + }; + // Color + static RadioLanguage colorLangs[] = { + LANG_CN, + LANG_CZ, + LANG_DA, + LANG_DE, + LANG_EN, + LANG_ES, + LANG_FI, + LANG_FR, + LANG_HE, + // LANG_HU, // no translation file + LANG_IT, + LANG_JP, + LANG_KO, + LANG_NL, + LANG_PL, + LANG_PT, + LANG_RU, + LANG_SE, + // LANG_SK, // no translation file + LANG_TW, + LANG_UA, + LANG_COUNT + }; + + RadioLanguage* langs = isColor ? colorLangs : bwLangs; b->clear(); - for (int i = 0; !strings[i][0].isNull(); i++) { - b->addItem(strings[i][0],strings[i][1]); - if (generalSettings.ttsLanguage == strings[i][1]) { + for (int i = 0; langs[i] < LANG_COUNT; i++) { + int n = langs[i]; + b->addItem(tr(langStrings[n][0]),langStrings[n][1]); + if (strncmp(currLang, langStrings[n][1], 2) == 0) { b->setCurrentIndex(b->count() - 1); } } @@ -485,6 +577,18 @@ void GeneralSetupPanel::on_voiceLang_CB_currentIndexChanged(int index) } } +void GeneralSetupPanel::on_textLang_CB_currentIndexChanged(int index) +{ + if (!lock) { + QString code = ui->textLang_CB->itemData(index).toString(); + for (int i = 0; i < 2; i++) { + generalSettings.uiLanguage[i] = code.at(i).toLatin1(); + } + generalSettings.uiLanguage[2] = '\0'; + emit modified(); + } +} + void GeneralSetupPanel::updateVarioPitchRange() { ui->varioPMax_SB->setMaximum(700 + (generalSettings.varioPitch * 10) + 1000 + 800); diff --git a/companion/src/generaledit/generalsetup.h b/companion/src/generaledit/generalsetup.h index 389d30238..2e996e45d 100644 --- a/companion/src/generaledit/generalsetup.h +++ b/companion/src/generaledit/generalsetup.h @@ -68,6 +68,7 @@ class GeneralSetupPanel : public GeneralPanel void on_backlightColor_SL_valueChanged(); void on_mavbaud_CB_currentIndexChanged(int index); void on_voiceLang_CB_currentIndexChanged(int index); + void on_textLang_CB_currentIndexChanged(int index); void stickReverseEdited(); void on_switchesDelay_valueChanged(int); void on_blAlarm_ChkB_stateChanged(); @@ -113,6 +114,7 @@ class GeneralSetupPanel : public GeneralPanel void showLabelSelectOptions(); void setValues(); - void populateVoiceLangCB(); + void populateVoiceLangCB(QComboBox* b, const char* currLang); + void populateTextLangCB(QComboBox* b, const char* currLang, bool isColor); void updateVarioPitchRange(); }; diff --git a/companion/src/generaledit/generalsetup.ui b/companion/src/generaledit/generalsetup.ui index eaaee94b2..8bb5eb434 100644 --- a/companion/src/generaledit/generalsetup.ui +++ b/companion/src/generaledit/generalsetup.ui @@ -576,7 +576,7 @@ - + @@ -590,7 +590,7 @@ - + Enable this to quickly change model on the model select page (a long press can then be used to open the model edit menu). @@ -621,14 +621,14 @@ - + Owner Registration ID - + Label selection mode @@ -662,7 +662,7 @@ - + Label matching @@ -692,7 +692,7 @@ - + @@ -706,7 +706,7 @@ - + Qt::Orientation::Vertical @@ -822,7 +822,7 @@ - + @@ -874,7 +874,7 @@ - + @@ -908,7 +908,7 @@ - + 8 @@ -929,6 +929,13 @@ + + + + Text Language + + + @@ -999,7 +1006,10 @@ - + + + + @@ -1102,7 +1112,7 @@ - + Manage Models layout @@ -1125,7 +1135,7 @@ - + Rotary Encoder Mode @@ -1148,7 +1158,7 @@ - + Model quick select @@ -1203,7 +1213,7 @@ p, li { white-space: pre-wrap; } - + Favorites matching diff --git a/radio/src/datastructs.h b/radio/src/datastructs.h index 32a9b58e0..891fad317 100644 --- a/radio/src/datastructs.h +++ b/radio/src/datastructs.h @@ -77,15 +77,15 @@ static inline void check_struct() #endif #if defined(PCBXLITES) - CHKSIZE(RadioData, 948); + CHKSIZE(RadioData, 950); #elif defined(RADIO_ST16) || defined(PCBPA01) || defined(RADIO_TX15) || defined(RADIO_T15PRO) - CHKSIZE(RadioData, 1179); + CHKSIZE(RadioData, 1181); #elif defined(COLORLCD) - CHKSIZE(RadioData, 1059); + CHKSIZE(RadioData, 1061); #elif defined(RADIO_GX12) - CHKSIZE(RadioData, 1066); + CHKSIZE(RadioData, 1068); #else - CHKSIZE(RadioData, 946); + CHKSIZE(RadioData, 948); #endif #if defined(RADIO_TPRO) || defined(RADIO_TPROV2) || defined(RADIO_BUMBLEBEE) diff --git a/radio/src/datastructs_private.h b/radio/src/datastructs_private.h index b1e8d1335..a24ca37c4 100644 --- a/radio/src/datastructs_private.h +++ b/radio/src/datastructs_private.h @@ -1079,6 +1079,7 @@ PACK(struct RadioData { NOBACKUP(uint8_t sportUpdatePower:1 SKIP); NOBACKUP(char ttsLanguage[2]); + NOBACKUP(char uiLanguage[2]); NOBACKUP(int8_t beepVolume:4 CUST(r_5pos,w_5pos)); NOBACKUP(int8_t wavVolume:4 CUST(r_5pos,w_5pos)); NOBACKUP(int8_t varioVolume:4 CUST(r_5pos,w_5pos)); diff --git a/radio/src/edgetx.cpp b/radio/src/edgetx.cpp index 7a104d307..c80c60fc9 100644 --- a/radio/src/edgetx.cpp +++ b/radio/src/edgetx.cpp @@ -310,6 +310,13 @@ void generalDefaultSwitches() } } +void generalDefaultUILanguage() +{ + memcpy(g_eeGeneral.uiLanguage, TRANSLATIONS, 2); + g_eeGeneral.uiLanguage[0] = tolower(g_eeGeneral.uiLanguage[0]); + g_eeGeneral.uiLanguage[1] = tolower(g_eeGeneral.uiLanguage[1]); +} + void generalDefault() { memclear(&g_eeGeneral, sizeof(g_eeGeneral)); @@ -365,6 +372,7 @@ void generalDefault() g_eeGeneral.lightAutoOff = 2; g_eeGeneral.inactivityTimer = 10; + generalDefaultUILanguage(); g_eeGeneral.ttsLanguage[0] = 'e'; g_eeGeneral.ttsLanguage[1] = 'n'; g_eeGeneral.wavVolume = 2; diff --git a/radio/src/edgetx.h b/radio/src/edgetx.h index 4f27b2e40..f5044fb35 100644 --- a/radio/src/edgetx.h +++ b/radio/src/edgetx.h @@ -348,6 +348,7 @@ uint16_t isqrt32(uint32_t n); void setDefaultOwnerId(); void generalDefault(); void generalDefaultSwitches(); +void generalDefaultUILanguage(); uint32_t hash(const void * ptr, uint32_t size); diff --git a/radio/src/gui/128x64/radio_setup.cpp b/radio/src/gui/128x64/radio_setup.cpp index 31694956b..7e0aa5997 100644 --- a/radio/src/gui/128x64/radio_setup.cpp +++ b/radio/src/gui/128x64/radio_setup.cpp @@ -99,7 +99,10 @@ enum { CASE_GPS(ITEM_RADIO_SETUP_ADJUST_RTC) CASE_GPS(ITEM_RADIO_SETUP_GPSFORMAT) CASE_PXX1(ITEM_RADIO_SETUP_COUNTRYCODE) - ITEM_RADIO_SETUP_LANGUAGE, + ITEM_RADIO_SETUP_VOICE_LANGUAGE, +#if defined(ALL_LANGS) + ITEM_RADIO_SETUP_TEXT_LANGUAGE, +#endif ITEM_RADIO_SETUP_IMPERIAL, ITEM_RADIO_SETUP_PPM, IF_FAI_CHOICE(ITEM_RADIO_SETUP_FAI) @@ -238,6 +241,9 @@ void menuRadioSetup(event_t event) CASE_GPS(0) CASE_PXX1(0) 0, 0, 0, +#if defined(ALL_LANGS) + 0, // text language +#endif IF_FAI_CHOICE(0) 0, 0, // USB mode @@ -708,7 +714,7 @@ void menuRadioSetup(event_t event) break; #endif - case ITEM_RADIO_SETUP_LANGUAGE: + case ITEM_RADIO_SETUP_VOICE_LANGUAGE: lcdDrawTextAlignedLeft(y, STR_VOICE_LANGUAGE); #if !defined(ALL_LANGS) lcdDrawText(LCD_W-2, y, currentLanguagePack->name, attr|RIGHT); @@ -720,15 +726,27 @@ void menuRadioSetup(event_t event) if (checkIncDec_Ret) { currentLanguagePack = languagePacks[currentLanguagePackIdx]; strncpy(g_eeGeneral.ttsLanguage, currentLanguagePack->id, 2); -#if defined(ALL_LANGS) - currentLangStrings = langStrings[currentLanguagePackIdx]; - extern void setLanguageFont(int n); - setLanguageFont(currentLanguagePackIdx); -#endif } } break; +#if defined(ALL_LANGS) + case ITEM_RADIO_SETUP_TEXT_LANGUAGE: + lcdDrawTextAlignedLeft(y, STR_TEXT_LANGUAGE); + lcdDrawText(LCD_W-2, y, languagePacks[getLanguageId(g_eeGeneral.uiLanguage)]->name(), attr|RIGHT); + if (attr) { + int textLangId = checkIncDec(event, getLanguageId(g_eeGeneral.uiLanguage), 0, DIM(languagePacks)-2, EE_GENERAL, isTextLangAvail); + if (checkIncDec_Ret) { + currentLanguagePack = languagePacks[currentLanguagePackIdx]; + strncpy(g_eeGeneral.uiLanguage, languagePacks[textLangId]->id, 2); + currentLangStrings = langStrings[textLangId]; + extern void setLanguageFont(int n); + setLanguageFont(textLangId); + } + } + break; +#endif + case ITEM_RADIO_SETUP_IMPERIAL: g_eeGeneral.imperial = editChoice(LCD_W-2, y, STR_UNITS_SYSTEM, STR_VUNITSSYSTEM, g_eeGeneral.imperial, 0, 1, attr|RIGHT, event); break; diff --git a/radio/src/gui/212x64/radio_setup.cpp b/radio/src/gui/212x64/radio_setup.cpp index f428074bb..0f71deac4 100644 --- a/radio/src/gui/212x64/radio_setup.cpp +++ b/radio/src/gui/212x64/radio_setup.cpp @@ -98,7 +98,10 @@ enum MenuRadioSetupItems { CASE_GPS(ITEM_RADIO_SETUP_ADJUST_RTC) CASE_GPS(ITEM_RADIO_SETUP_GPSFORMAT) CASE_PXX1(ITEM_RADIO_SETUP_COUNTRYCODE) - ITEM_RADIO_SETUP_LANGUAGE, + ITEM_RADIO_SETUP_VOICE_LANGUAGE, +#if defined(ALL_LANGS) + ITEM_RADIO_SETUP_TEXT_LANGUAGE, +#endif ITEM_RADIO_SETUP_IMPERIAL, ITEM_RADIO_SETUP_PPM, IF_FAI_CHOICE(ITEM_RADIO_SETUP_FAI) @@ -238,6 +241,9 @@ void menuRadioSetup(event_t event) CASE_GPS(0) CASE_PXX1(0) // country code 0, // voice language +#if defined(ALL_LANGS) + 0, // text language +#endif 0, // imperial 0, // PPM unit IF_FAI_CHOICE(0) @@ -679,7 +685,7 @@ void menuRadioSetup(event_t event) break; #endif - case ITEM_RADIO_SETUP_LANGUAGE: + case ITEM_RADIO_SETUP_VOICE_LANGUAGE: lcdDrawTextAlignedLeft(y, STR_VOICE_LANGUAGE); #if !defined(ALL_LANGS) lcdDrawText(RADIO_SETUP_2ND_COLUMN, y, currentLanguagePack->name, attr); @@ -691,15 +697,27 @@ void menuRadioSetup(event_t event) if (checkIncDec_Ret) { currentLanguagePack = languagePacks[currentLanguagePackIdx]; strncpy(g_eeGeneral.ttsLanguage, currentLanguagePack->id, 2); -#if defined(ALL_LANGS) - currentLangStrings = langStrings[currentLanguagePackIdx]; - extern void setLanguageFont(int n); - setLanguageFont(currentLanguagePackIdx); -#endif } } break; +#if defined(ALL_LANGS) + case ITEM_RADIO_SETUP_TEXT_LANGUAGE: + lcdDrawTextAlignedLeft(y, STR_TEXT_LANGUAGE); + lcdDrawText(RADIO_SETUP_2ND_COLUMN, y, languagePacks[getLanguageId(g_eeGeneral.uiLanguage)]->name(), attr); + if (attr) { + int textLangId = checkIncDec(event, getLanguageId(g_eeGeneral.uiLanguage), 0, DIM(languagePacks)-2, EE_GENERAL, isTextLangAvail); + if (checkIncDec_Ret) { + currentLanguagePack = languagePacks[currentLanguagePackIdx]; + strncpy(g_eeGeneral.uiLanguage, languagePacks[textLangId]->id, 2); + currentLangStrings = langStrings[textLangId]; + extern void setLanguageFont(int n); + setLanguageFont(textLangId); + } + } + break; +#endif + case ITEM_RADIO_SETUP_IMPERIAL: g_eeGeneral.imperial = editChoice(RADIO_SETUP_2ND_COLUMN, y, STR_UNITS_SYSTEM, STR_VUNITSSYSTEM, g_eeGeneral.imperial, 0, 1, attr, event); break; diff --git a/radio/src/gui/colorlcd/radio/radio_setup.cpp b/radio/src/gui/colorlcd/radio/radio_setup.cpp index 79688dc54..cb16f6cce 100644 --- a/radio/src/gui/colorlcd/radio/radio_setup.cpp +++ b/radio/src/gui/colorlcd/radio/radio_setup.cpp @@ -852,19 +852,6 @@ static SetupLineDef setupLines[] = { currentLanguagePack = languagePacks[currentLanguagePackIdx]; strncpy(g_eeGeneral.ttsLanguage, currentLanguagePack->id, 2); SET_DIRTY(); -#if defined(ALL_LANGS) - currentLangStrings = langStrings[currentLanguagePackIdx]; - extern void setLanguageFont(int idx); - setLanguageFont(currentLanguagePackIdx); - PageGroup* pg = (PageGroup*)Layer::getPageGroup(); - coord_t y = pg->getScrollY(); - pg->onCancel(); - QuickMenu::openPage(QM_RADIO_SETUP); - pg = (PageGroup*)Layer::getPageGroup(); - pg->setScrollY(y); - // Force QM rebuild for language change - QuickMenu::shutdownQuickMenu(); -#endif }); #if !defined(ALL_LANGS) choice->setTextHandler( @@ -884,6 +871,44 @@ static SetupLineDef setupLines[] = { #endif } }, +#if defined(ALL_LANGS) + { + // UI language + STR_DEF(STR_TEXT_LANGUAGE), + [](Window* parent, coord_t x, coord_t y) { + auto choice = + new Choice(parent, {x, y, 0, 0}, 0, DIM(languagePacks) - 2, + GET_VALUE(getLanguageId(g_eeGeneral.uiLanguage)), + [](uint8_t newValue) { + strncpy(g_eeGeneral.uiLanguage, languagePacks[newValue]->id, 2); + currentLangStrings = langStrings[newValue]; + extern void setLanguageFont(int idx); + setLanguageFont(newValue); + PageGroup* pg = (PageGroup*)Layer::getPageGroup(); + coord_t y = pg->getScrollY(); + pg->onCancel(); + QuickMenu::openPage(QM_RADIO_SETUP); + pg = (PageGroup*)Layer::getPageGroup(); + pg->setScrollY(y); + // Force QM rebuild for language change + QuickMenu::shutdownQuickMenu(); + SET_DIRTY(); + }); + choice->setAvailableHandler([=](int n) { return isTextLangAvail(n); }); + choice->setTextHandler( + [](uint8_t value) { + // TODO: language name should always be in the language of the name, not + // the current UI language. Needs translation characters to be + // always available for all language names in the base font. + // temp solution - prepend language id to name. + std::string s(languagePacks[value]->id); + s += " - "; + s += languagePacks[value]->name(); + return s; + }); + } + }, +#endif { // Imperial units STR_DEF(STR_UNITS_SYSTEM), diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index 7eb3f5f99..461015496 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -1760,8 +1760,8 @@ static int luaGetGeneralSettings(lua_State * L) lua_pushtableinteger(L, "imperial", g_eeGeneral.imperial); #if defined(ALL_LANGS) char l[3]; - l[0] = toupper(g_eeGeneral.ttsLanguage[0]); - l[1] = toupper(g_eeGeneral.ttsLanguage[1]); + l[0] = toupper(g_eeGeneral.uiLanguage[0]); + l[1] = toupper(g_eeGeneral.uiLanguage[1]); l[2] = 0; lua_pushtablestring(L, "language", l); #else diff --git a/radio/src/lua/lua_widget_factory.cpp b/radio/src/lua/lua_widget_factory.cpp index 497d31b01..c3d9059d7 100644 --- a/radio/src/lua/lua_widget_factory.cpp +++ b/radio/src/lua/lua_widget_factory.cpp @@ -112,8 +112,8 @@ void LuaWidgetFactory::translateOptions(WidgetOption * options) #if defined(ALL_LANGS) char lang[3]; - lang[0] = toupper(g_eeGeneral.ttsLanguage[0]); - lang[1] = toupper(g_eeGeneral.ttsLanguage[1]); + lang[0] = toupper(g_eeGeneral.uiLanguage[0]); + lang[1] = toupper(g_eeGeneral.uiLanguage[1]); lang[2] = 0; #else const char* lang = TRANSLATIONS; diff --git a/radio/src/storage/sdcard_common.cpp b/radio/src/storage/sdcard_common.cpp index a14e06a90..33c53a1c4 100644 --- a/radio/src/storage/sdcard_common.cpp +++ b/radio/src/storage/sdcard_common.cpp @@ -243,18 +243,16 @@ void storageReadAll() } #endif - for (uint8_t i = 0; languagePacks[i] != nullptr; i++) { - if (!strncmp(g_eeGeneral.ttsLanguage, languagePacks[i]->id, 2)) { - currentLanguagePackIdx = i; - currentLanguagePack = languagePacks[i]; + if (g_eeGeneral.uiLanguage[0] == 0) + generalDefaultUILanguage(); + currentLanguagePackIdx = getLanguageId(g_eeGeneral.ttsLanguage); + currentLanguagePack = languagePacks[currentLanguagePackIdx]; #if defined(ALL_LANGS) - currentLangStrings = langStrings[currentLanguagePackIdx]; - extern void setLanguageFont(int n); - setLanguageFont(currentLanguagePackIdx); + uint8_t uiLangIdx = getLanguageId(g_eeGeneral.uiLanguage); + currentLangStrings = langStrings[uiLangIdx]; + extern void setLanguageFont(int n); + setLanguageFont(uiLangIdx); #endif - break; - } - } #if defined(STORAGE_MODELSLIST) // and reload the list diff --git a/radio/src/storage/yaml/yaml_datastructs_128x64.cpp b/radio/src/storage/yaml/yaml_datastructs_128x64.cpp index 83ad2c1bd..990ea5c37 100644 --- a/radio/src/storage/yaml/yaml_datastructs_128x64.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_128x64.cpp @@ -343,6 +343,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "jackMode", 2 ), YAML_PADDING( 1 ), YAML_STRING("ttsLanguage", 2), + YAML_STRING("uiLanguage", 2), YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), diff --git a/radio/src/storage/yaml/yaml_datastructs_f16.cpp b/radio/src/storage/yaml/yaml_datastructs_f16.cpp index 836264dd9..14a79e7ca 100644 --- a/radio/src/storage/yaml/yaml_datastructs_f16.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_f16.cpp @@ -399,6 +399,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "jackMode", 2 ), YAML_PADDING( 1 ), YAML_STRING("ttsLanguage", 2), + YAML_STRING("uiLanguage", 2), YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), diff --git a/radio/src/storage/yaml/yaml_datastructs_gx12.cpp b/radio/src/storage/yaml/yaml_datastructs_gx12.cpp index f7c629142..b803abb19 100644 --- a/radio/src/storage/yaml/yaml_datastructs_gx12.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_gx12.cpp @@ -367,6 +367,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "jackMode", 2 ), YAML_PADDING( 1 ), YAML_STRING("ttsLanguage", 2), + YAML_STRING("uiLanguage", 2), YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), diff --git a/radio/src/storage/yaml/yaml_datastructs_nb4p.cpp b/radio/src/storage/yaml/yaml_datastructs_nb4p.cpp index 18c504e0d..41d0db0e1 100644 --- a/radio/src/storage/yaml/yaml_datastructs_nb4p.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_nb4p.cpp @@ -392,6 +392,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "jackMode", 2 ), YAML_PADDING( 1 ), YAML_STRING("ttsLanguage", 2), + YAML_STRING("uiLanguage", 2), YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), diff --git a/radio/src/storage/yaml/yaml_datastructs_nv14.cpp b/radio/src/storage/yaml/yaml_datastructs_nv14.cpp index f439071be..9281afc51 100644 --- a/radio/src/storage/yaml/yaml_datastructs_nv14.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_nv14.cpp @@ -399,6 +399,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "jackMode", 2 ), YAML_PADDING( 1 ), YAML_STRING("ttsLanguage", 2), + YAML_STRING("uiLanguage", 2), YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), diff --git a/radio/src/storage/yaml/yaml_datastructs_pa01.cpp b/radio/src/storage/yaml/yaml_datastructs_pa01.cpp index 5901a1974..4e66e24b4 100644 --- a/radio/src/storage/yaml/yaml_datastructs_pa01.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_pa01.cpp @@ -422,6 +422,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "jackMode", 2 ), YAML_PADDING( 1 ), YAML_STRING("ttsLanguage", 2), + YAML_STRING("uiLanguage", 2), YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), diff --git a/radio/src/storage/yaml/yaml_datastructs_pl18.cpp b/radio/src/storage/yaml/yaml_datastructs_pl18.cpp index da5ea20cb..07e60f939 100644 --- a/radio/src/storage/yaml/yaml_datastructs_pl18.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_pl18.cpp @@ -399,6 +399,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "jackMode", 2 ), YAML_PADDING( 1 ), YAML_STRING("ttsLanguage", 2), + YAML_STRING("uiLanguage", 2), YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), diff --git a/radio/src/storage/yaml/yaml_datastructs_pl18u.cpp b/radio/src/storage/yaml/yaml_datastructs_pl18u.cpp index 6523e4d6e..c4fff4aab 100644 --- a/radio/src/storage/yaml/yaml_datastructs_pl18u.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_pl18u.cpp @@ -392,6 +392,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "jackMode", 2 ), YAML_PADDING( 1 ), YAML_STRING("ttsLanguage", 2), + YAML_STRING("uiLanguage", 2), YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), diff --git a/radio/src/storage/yaml/yaml_datastructs_st16.cpp b/radio/src/storage/yaml/yaml_datastructs_st16.cpp index fefe37832..721cbd8ad 100644 --- a/radio/src/storage/yaml/yaml_datastructs_st16.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_st16.cpp @@ -422,6 +422,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "jackMode", 2 ), YAML_PADDING( 1 ), YAML_STRING("ttsLanguage", 2), + YAML_STRING("uiLanguage", 2), YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), diff --git a/radio/src/storage/yaml/yaml_datastructs_t15.cpp b/radio/src/storage/yaml/yaml_datastructs_t15.cpp index a6f3ecb94..1468c6117 100644 --- a/radio/src/storage/yaml/yaml_datastructs_t15.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_t15.cpp @@ -407,6 +407,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "jackMode", 2 ), YAML_PADDING( 1 ), YAML_STRING("ttsLanguage", 2), + YAML_STRING("uiLanguage", 2), YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), diff --git a/radio/src/storage/yaml/yaml_datastructs_t15pro.cpp b/radio/src/storage/yaml/yaml_datastructs_t15pro.cpp index fefe37832..721cbd8ad 100644 --- a/radio/src/storage/yaml/yaml_datastructs_t15pro.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_t15pro.cpp @@ -422,6 +422,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "jackMode", 2 ), YAML_PADDING( 1 ), YAML_STRING("ttsLanguage", 2), + YAML_STRING("uiLanguage", 2), YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), diff --git a/radio/src/storage/yaml/yaml_datastructs_t20.cpp b/radio/src/storage/yaml/yaml_datastructs_t20.cpp index 87fe9c934..8338142e9 100644 --- a/radio/src/storage/yaml/yaml_datastructs_t20.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_t20.cpp @@ -352,6 +352,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "jackMode", 2 ), YAML_PADDING( 1 ), YAML_STRING("ttsLanguage", 2), + YAML_STRING("uiLanguage", 2), YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), diff --git a/radio/src/storage/yaml/yaml_datastructs_tpro.cpp b/radio/src/storage/yaml/yaml_datastructs_tpro.cpp index 81b54a990..4178251a4 100644 --- a/radio/src/storage/yaml/yaml_datastructs_tpro.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_tpro.cpp @@ -352,6 +352,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "jackMode", 2 ), YAML_PADDING( 1 ), YAML_STRING("ttsLanguage", 2), + YAML_STRING("uiLanguage", 2), YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), diff --git a/radio/src/storage/yaml/yaml_datastructs_tx15.cpp b/radio/src/storage/yaml/yaml_datastructs_tx15.cpp index fefe37832..721cbd8ad 100644 --- a/radio/src/storage/yaml/yaml_datastructs_tx15.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_tx15.cpp @@ -422,6 +422,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "jackMode", 2 ), YAML_PADDING( 1 ), YAML_STRING("ttsLanguage", 2), + YAML_STRING("uiLanguage", 2), YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), diff --git a/radio/src/storage/yaml/yaml_datastructs_x10.cpp b/radio/src/storage/yaml/yaml_datastructs_x10.cpp index 2c523eba8..071a51f3c 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x10.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x10.cpp @@ -398,6 +398,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "jackMode", 2 ), YAML_PADDING( 1 ), YAML_STRING("ttsLanguage", 2), + YAML_STRING("uiLanguage", 2), YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), diff --git a/radio/src/storage/yaml/yaml_datastructs_x9d.cpp b/radio/src/storage/yaml/yaml_datastructs_x9d.cpp index 02b3afb5f..4802d38d8 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x9d.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x9d.cpp @@ -343,6 +343,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "jackMode", 2 ), YAML_PADDING( 1 ), YAML_STRING("ttsLanguage", 2), + YAML_STRING("uiLanguage", 2), YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), diff --git a/radio/src/storage/yaml/yaml_datastructs_x9dp2019.cpp b/radio/src/storage/yaml/yaml_datastructs_x9dp2019.cpp index 02b3afb5f..4802d38d8 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x9dp2019.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x9dp2019.cpp @@ -343,6 +343,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "jackMode", 2 ), YAML_PADDING( 1 ), YAML_STRING("ttsLanguage", 2), + YAML_STRING("uiLanguage", 2), YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), diff --git a/radio/src/storage/yaml/yaml_datastructs_x9e.cpp b/radio/src/storage/yaml/yaml_datastructs_x9e.cpp index 03f9451c4..3820b34c6 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x9e.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x9e.cpp @@ -343,6 +343,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "jackMode", 2 ), YAML_PADDING( 1 ), YAML_STRING("ttsLanguage", 2), + YAML_STRING("uiLanguage", 2), YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), diff --git a/radio/src/storage/yaml/yaml_datastructs_xlite.cpp b/radio/src/storage/yaml/yaml_datastructs_xlite.cpp index 83ad2c1bd..990ea5c37 100644 --- a/radio/src/storage/yaml/yaml_datastructs_xlite.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_xlite.cpp @@ -343,6 +343,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "jackMode", 2 ), YAML_PADDING( 1 ), YAML_STRING("ttsLanguage", 2), + YAML_STRING("uiLanguage", 2), YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), diff --git a/radio/src/storage/yaml/yaml_datastructs_xlites.cpp b/radio/src/storage/yaml/yaml_datastructs_xlites.cpp index 9ce5f298f..78a079b76 100644 --- a/radio/src/storage/yaml/yaml_datastructs_xlites.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_xlites.cpp @@ -345,6 +345,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "jackMode", 2 ), YAML_PADDING( 1 ), YAML_STRING("ttsLanguage", 2), + YAML_STRING("uiLanguage", 2), YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ), YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ), diff --git a/radio/src/translations/i18n/cn.h b/radio/src/translations/i18n/cn.h index a41ecd694..5c008cef0 100644 --- a/radio/src/translations/i18n/cn.h +++ b/radio/src/translations/i18n/cn.h @@ -970,6 +970,7 @@ #define TR_USBMODE "USB模式" #define TR_JACK_MODE "教练插口模式" #define TR_VOICE_LANGUAGE "播报语言" +#define TR_TEXT_LANGUAGE "Text language" #define TR_UNITS_SYSTEM "单位" #define TR_UNITS_PPM "PPM 单位" #define TR_EDIT "编辑" diff --git a/radio/src/translations/i18n/cz.h b/radio/src/translations/i18n/cz.h index aa7e9b6f3..8b3cced15 100644 --- a/radio/src/translations/i18n/cz.h +++ b/radio/src/translations/i18n/cz.h @@ -968,6 +968,7 @@ #define TR_USBMODE "Režim USB" #define TR_JACK_MODE "Režim Jack" #define TR_VOICE_LANGUAGE "Jazyk hlasu" +#define TR_TEXT_LANGUAGE "Text language" #define TR_UNITS_SYSTEM "Jednotky" #define TR_UNITS_PPM "PPM jednotky" #define TR_EDIT "Upravit" diff --git a/radio/src/translations/i18n/da.h b/radio/src/translations/i18n/da.h index ec99a2460..93c1f8963 100644 --- a/radio/src/translations/i18n/da.h +++ b/radio/src/translations/i18n/da.h @@ -975,6 +975,7 @@ #define TR_USBMODE "USB tilstand" #define TR_JACK_MODE "Jack tilstand" #define TR_VOICE_LANGUAGE "Stemme sprog" +#define TR_TEXT_LANGUAGE "Text language" #define TR_UNITS_SYSTEM "Enheder" #define TR_UNITS_PPM "PPM enheder" #define TR_EDIT "Rediger" diff --git a/radio/src/translations/i18n/de.h b/radio/src/translations/i18n/de.h index f28fcc4df..83eaeca2c 100644 --- a/radio/src/translations/i18n/de.h +++ b/radio/src/translations/i18n/de.h @@ -964,6 +964,7 @@ #define TR_USBMODE "USB Modus" #define TR_JACK_MODE "Jack Mode" #define TR_VOICE_LANGUAGE "Sprachansagen" +#define TR_TEXT_LANGUAGE "Text language" #define TR_UNITS_SYSTEM "Einheiten" #define TR_UNITS_PPM "PPM Einheiten" #define TR_EDIT "Zeile Editieren" diff --git a/radio/src/translations/i18n/en.h b/radio/src/translations/i18n/en.h index 9be7c8161..a3bbaa33d 100644 --- a/radio/src/translations/i18n/en.h +++ b/radio/src/translations/i18n/en.h @@ -971,6 +971,7 @@ #define TR_USBMODE "USB mode" #define TR_JACK_MODE "Jack mode" #define TR_VOICE_LANGUAGE "Voice language" +#define TR_TEXT_LANGUAGE "Text language" #define TR_UNITS_SYSTEM "Units" #define TR_UNITS_PPM "PPM Units" #define TR_EDIT "Edit" diff --git a/radio/src/translations/i18n/es.h b/radio/src/translations/i18n/es.h index c1a18c4ed..3fbabbd08 100644 --- a/radio/src/translations/i18n/es.h +++ b/radio/src/translations/i18n/es.h @@ -964,6 +964,7 @@ #define TR_USBMODE "Modo USB" #define TR_JACK_MODE "Modo Jack" #define TR_VOICE_LANGUAGE "Idioma voces" +#define TR_TEXT_LANGUAGE "Text language" #define TR_UNITS_SYSTEM "Unidades" #define TR_UNITS_PPM "PPM Units" #define TR_EDIT "Editar" diff --git a/radio/src/translations/i18n/fi.h b/radio/src/translations/i18n/fi.h index 65e0d40fd..f20d6ce85 100644 --- a/radio/src/translations/i18n/fi.h +++ b/radio/src/translations/i18n/fi.h @@ -964,6 +964,7 @@ #define TR_USBMODE "USB-tila" #define TR_JACK_MODE "Jack Mode" #define TR_VOICE_LANGUAGE "Äänen kieli" +#define TR_TEXT_LANGUAGE "Text language" #define TR_UNITS_SYSTEM "Units" #define TR_UNITS_PPM "PPM Units" #define TR_EDIT "Edit" diff --git a/radio/src/translations/i18n/fr.h b/radio/src/translations/i18n/fr.h index f65f3275b..d2a04ee38 100644 --- a/radio/src/translations/i18n/fr.h +++ b/radio/src/translations/i18n/fr.h @@ -968,6 +968,7 @@ #define TR_USBMODE "Mode USB" #define TR_JACK_MODE "Mode Jack" #define TR_VOICE_LANGUAGE TR("Langue voix", "Langue annonces vocales") +#define TR_TEXT_LANGUAGE "Text language" #define TR_UNITS_SYSTEM "Unités" #define TR_UNITS_PPM "PPM Units" #define TR_EDIT "Éditer" diff --git a/radio/src/translations/i18n/he.h b/radio/src/translations/i18n/he.h index bb308368a..707876b52 100644 --- a/radio/src/translations/i18n/he.h +++ b/radio/src/translations/i18n/he.h @@ -973,6 +973,7 @@ #define TR_USBMODE "USB מצב" #define TR_JACK_MODE "Jack mode" #define TR_VOICE_LANGUAGE "שפת שמע" +#define TR_TEXT_LANGUAGE "Text language" #define TR_UNITS_SYSTEM "יחידות" #define TR_UNITS_PPM "PPM Units" #define TR_EDIT "ערוך" diff --git a/radio/src/translations/i18n/it.h b/radio/src/translations/i18n/it.h index 4489c56b9..35a784dc5 100644 --- a/radio/src/translations/i18n/it.h +++ b/radio/src/translations/i18n/it.h @@ -970,6 +970,7 @@ #define TR_USBMODE "Modo USB" #define TR_JACK_MODE "Modo JACK" #define TR_VOICE_LANGUAGE "Lingua vocale" +#define TR_TEXT_LANGUAGE "Text language" #define TR_UNITS_SYSTEM "Unità" #define TR_UNITS_PPM "Unità PPM" #define TR_EDIT "Modifica" diff --git a/radio/src/translations/i18n/jp.h b/radio/src/translations/i18n/jp.h index c59d0745b..714cc47c7 100644 --- a/radio/src/translations/i18n/jp.h +++ b/radio/src/translations/i18n/jp.h @@ -969,6 +969,7 @@ #define TR_USBMODE "USBモード" #define TR_JACK_MODE "Jackモード" #define TR_VOICE_LANGUAGE "音声言語" +#define TR_TEXT_LANGUAGE "Text language" #define TR_UNITS_SYSTEM "ユニット" #define TR_UNITS_PPM "PPMユニット" #define TR_EDIT "編集" diff --git a/radio/src/translations/i18n/ko.h b/radio/src/translations/i18n/ko.h index 7f61ab2da..5c345c9d4 100644 --- a/radio/src/translations/i18n/ko.h +++ b/radio/src/translations/i18n/ko.h @@ -1014,6 +1014,7 @@ #define TR_USBMODE "USB 모드" #define TR_JACK_MODE "잭 모드" #define TR_VOICE_LANGUAGE "음성 언어" +#define TR_TEXT_LANGUAGE "Text language" #define TR_UNITS_SYSTEM "단위 체계" #define TR_UNITS_PPM "PPM 단위" #define TR_EDIT "편집" diff --git a/radio/src/translations/i18n/nl.h b/radio/src/translations/i18n/nl.h index ac4a70dfa..6fa580566 100644 --- a/radio/src/translations/i18n/nl.h +++ b/radio/src/translations/i18n/nl.h @@ -966,6 +966,7 @@ #define TR_USBMODE "USB Mode" #define TR_JACK_MODE "Jack Mode" #define TR_VOICE_LANGUAGE "Taal" +#define TR_TEXT_LANGUAGE "Text language" #define TR_UNITS_SYSTEM "Eenheden" #define TR_UNITS_PPM "PPM Units" #define TR_EDIT "Wijzigen" diff --git a/radio/src/translations/i18n/pl.h b/radio/src/translations/i18n/pl.h index cc43c4bf5..cc75b2225 100644 --- a/radio/src/translations/i18n/pl.h +++ b/radio/src/translations/i18n/pl.h @@ -963,6 +963,7 @@ #define TR_USBMODE "Tryb USB" #define TR_JACK_MODE "Tryb Jack" #define TR_VOICE_LANGUAGE "Język głosu" +#define TR_TEXT_LANGUAGE "Text language" #define TR_UNITS_SYSTEM "Jednostki" #define TR_UNITS_PPM "Jednostki PPM" #define TR_EDIT "Edytuj" diff --git a/radio/src/translations/i18n/pt.h b/radio/src/translations/i18n/pt.h index 07d99fc13..e64c29cf5 100644 --- a/radio/src/translations/i18n/pt.h +++ b/radio/src/translations/i18n/pt.h @@ -971,6 +971,7 @@ #define TR_USBMODE "Modo USB" #define TR_JACK_MODE "Jack mode" #define TR_VOICE_LANGUAGE "Idoma da Voz" +#define TR_TEXT_LANGUAGE "Text language" #define TR_UNITS_SYSTEM "Unidades" #define TR_UNITS_PPM "Unidade PPM" #define TR_EDIT "Editar" diff --git a/radio/src/translations/i18n/ru.h b/radio/src/translations/i18n/ru.h index 922a6332d..8ed256ac9 100644 --- a/radio/src/translations/i18n/ru.h +++ b/radio/src/translations/i18n/ru.h @@ -972,6 +972,7 @@ #define TR_USBMODE "Режим USB" #define TR_JACK_MODE "Режим разъема" #define TR_VOICE_LANGUAGE "Язык озвучки" +#define TR_TEXT_LANGUAGE "Text language" #define TR_UNITS_SYSTEM "Единицы" #define TR_UNITS_PPM "PPM Един" #define TR_EDIT "Редактировать" diff --git a/radio/src/translations/i18n/se.h b/radio/src/translations/i18n/se.h index 0ec28b90c..ca50bd013 100644 --- a/radio/src/translations/i18n/se.h +++ b/radio/src/translations/i18n/se.h @@ -971,6 +971,7 @@ #define TR_USBMODE "USB-läge" #define TR_JACK_MODE "Uttagsläge" #define TR_VOICE_LANGUAGE "Röstspråk" +#define TR_TEXT_LANGUAGE "Text language" #define TR_UNITS_SYSTEM "Enheter" #define TR_UNITS_PPM "PPM-enheter" #define TR_EDIT "Redigera" diff --git a/radio/src/translations/i18n/tw.h b/radio/src/translations/i18n/tw.h index 61fc3513c..555328c2e 100644 --- a/radio/src/translations/i18n/tw.h +++ b/radio/src/translations/i18n/tw.h @@ -967,6 +967,7 @@ #define TR_USBMODE "USB模式" #define TR_JACK_MODE "教練插口模式" #define TR_VOICE_LANGUAGE "播報語言" +#define TR_TEXT_LANGUAGE "Text language" #define TR_UNITS_SYSTEM "單位" #define TR_UNITS_PPM "PPM 單位" #define TR_EDIT "編輯" diff --git a/radio/src/translations/i18n/ua.h b/radio/src/translations/i18n/ua.h index c938d72a1..d0028c5ab 100644 --- a/radio/src/translations/i18n/ua.h +++ b/radio/src/translations/i18n/ua.h @@ -971,6 +971,7 @@ #define TR_USBMODE "Режим USB" #define TR_JACK_MODE "Режим коннектора" #define TR_VOICE_LANGUAGE "Мова голосу" +#define TR_TEXT_LANGUAGE "Text language" #define TR_UNITS_SYSTEM "Одиниці" #define TR_UNITS_PPM "PPM одиниці" #define TR_EDIT "Редагувати" diff --git a/radio/src/translations/sim_string_list.h b/radio/src/translations/sim_string_list.h index b3faa1110..3960767a0 100644 --- a/radio/src/translations/sim_string_list.h +++ b/radio/src/translations/sim_string_list.h @@ -978,6 +978,7 @@ #define STR_TEST_NOTSAFE currentLangStrings->STR_TEST_NOTSAFE #define STR_TEST_WARNING currentLangStrings->STR_TEST_WARNING #define STR_TEXT_COLOR currentLangStrings->STR_TEXT_COLOR +#define STR_TEXT_LANGUAGE currentLangStrings->STR_TEXT_LANGUAGE #define STR_THEME currentLangStrings->STR_THEME #define STR_THROTTLE_LABEL currentLangStrings->STR_THROTTLE_LABEL #define STR_THROTTLE_NOT_IDLE currentLangStrings->STR_THROTTLE_NOT_IDLE diff --git a/radio/src/translations/string_list.h b/radio/src/translations/string_list.h index 5d05077af..57dd7395f 100644 --- a/radio/src/translations/string_list.h +++ b/radio/src/translations/string_list.h @@ -977,6 +977,7 @@ STR(TEMP_CALIB) STR(TEST_NOTSAFE) STR(TEST_WARNING) STR(TEXT_COLOR) +STR(TEXT_LANGUAGE) STR(THEME) STR(THROTTLE_LABEL) STR(THROTTLE_NOT_IDLE) diff --git a/radio/src/translations/translations.cpp b/radio/src/translations/translations.cpp index 612ddf47b..8d153fa00 100644 --- a/radio/src/translations/translations.cpp +++ b/radio/src/translations/translations.cpp @@ -62,6 +62,16 @@ #include "translations/i18n/en.h" #endif +uint8_t getLanguageId(const char* lang) +{ + for (uint8_t i = 0; languagePacks[i] != nullptr; i++) { + if (!strncmp(lang, languagePacks[i]->id, 2)) { + return i; + } + } + return LANG_EN; +} + const char CHR_HOUR = TR_CHR_HOUR; const char CHR_INPUT = TR_CHR_INPUT; @@ -80,6 +90,19 @@ const char CHR_INPUT = TR_CHR_INPUT; #else +bool isTextLangAvail(int lang) +{ +#if defined(COLORLCD) + // Skip languages with no translation files + return lang != LANG_HU && lang != LANG_SK; +#else + // Skip languages with no translation files or no unicode fonts + return lang != LANG_CN && lang != LANG_HE && lang != LANG_HU && + lang != LANG_JP && lang != LANG_KO && lang != LANG_SK && + lang != LANG_TW; +#endif +} + // Order must match languagePack[] #if defined(COLORLCD) const LangStrings* const langStrings[] = { diff --git a/radio/src/translations/translations.h b/radio/src/translations/translations.h index 572cacbd6..2531ca9a6 100644 --- a/radio/src/translations/translations.h +++ b/radio/src/translations/translations.h @@ -41,6 +41,8 @@ #else +bool isTextLangAvail(int lang); + // Static string #define STR(x) extern const char STR_##x[]; // Static string array diff --git a/radio/src/translations/tts/tts.h b/radio/src/translations/tts/tts.h index 57660acc4..45bc35631 100644 --- a/radio/src/translations/tts/tts.h +++ b/radio/src/translations/tts/tts.h @@ -45,6 +45,7 @@ struct LanguagePack { extern const LanguagePack * currentLanguagePack; extern uint8_t currentLanguagePackIdx; +extern uint8_t getLanguageId(const char* lang); enum RadioLanguage { LANG_CN,