From d1281edda4c32fd3be5243897cc886ebcbd29adb Mon Sep 17 00:00:00 2001 From: Manuel <71137295+mverch67@users.noreply.github.com> Date: Mon, 8 Sep 2025 21:46:42 +0200 Subject: [PATCH] feat: add Bulgarian translation (#148) * feat: add Bulgarian translation * update language translations * fix chat panel crash --------- Co-authored-by: b.bogoev Co-authored-by: blagovest-bogoev <29256251+blagovest-bogoev@users.noreply.github.com> --- locale/bg.yml | 146 +++++++++++++++++++++++ locale/lv_i18n.c | 150 +++++++++++++++++++++++- source/graphics/TFT/TFTView_320x240.cpp | 12 +- 3 files changed, 298 insertions(+), 10 deletions(-) create mode 100644 locale/bg.yml diff --git a/locale/bg.yml b/locale/bg.yml new file mode 100644 index 0000000..b56ee12 --- /dev/null +++ b/locale/bg.yml @@ -0,0 +1,146 @@ +bg: + no new messages: няма нови съобщения + 1 of 1 nodes online: 1 от 1 нода са онлайн + DEL: ~ + 'User name: ': 'Потребителско име:' + 'Modem Preset: LONG FAST': ~ + 'Channel: LongFast': 'Канал: LongFast' + 'Role: Client': 'Роля: Клиент' + 'Screen Timeout: 60s': 'Таймаут на екрана: 60с' + 'Screen Brightness: 60%': 'Яркостн а екрана: 60%%' + 'Screen Calibration: default': 'Калибровка на екрана: по подразбиране' + 'Input Control: none/none': ~ + 'Message Alert Buzzer: on': 'Звън при съобщение: включено' + 'Language: English': 'Език: Български' + Configuration Reset: ресет на настройките + Reboot / Shutdown: Рестарт / изкл. + Group Channels: Групови канали + no messages: няма съобщения + Settings: Настройки + Settings (advanced): Разширени настройки + Locations Map: Карта на местоположението + no chats: няма чатове + Node Options: Опции на възела + Short Name: Кратко име + Long Name: Дълго име + : <неопределено> + 'FrequencySlot: 1 (902.0MHz)': ~ + 'Brightness: 60%': 'Яркост: 60%%' + 'Timeout: 60s': ~ + Mouse: Мишка + Keyboard: Клавиатура + Message Alert: Известие за съобщение + "NodeDB Reset\nFactory Reset": "Нулиране NodeDB\nНулиране на настройки" + Channel Name: Име на канала + Pre-shared Key: ~ + New Message from\n: Ново съобщение от\n + 'User name: %s': 'Име: %s' + 'Device Role: %s': 'Роля на устройство: %s' + 'Screen Calibration: %s': 'Калибровка на екрана: %s' + done: готово + default: по подразбиране + 'Region: %s': 'Регион: %s' + 'Modem Preset: %s': ~ + 'Channel: %s': 'Канал: %s' + 'Language: %s': 'Език: %s' + 'Screen Lock: off': 'Блокировка на екрана: off' + 'Theme: Dark': 'Тема: Тъмна' + Mesh Detector: Mesh Детектор + Signal Scanner: Сигнал скенер + Trace Route: Маршрут + Neighbors: Съседи + Statistics: Статистика + Packet Log: Лог на пакети + Settings & Tools: Настройки и инструменти + Node Search: Търсене на нод + Screen Lock: Блокировка на екрана + Lock PIN: PIN-код + Ringtone: Рингтон + Zone: Зона + City: Град + Unknown: Неизвестно + Offline: Не е в мрежата + Public Key: Публичен ключ + Hops away: Хопове + MQTT: ~ + Position: Позиция + Name: Име + Active Chat: Активен чат + Telemetry: Телеметрия + IAQ: ~ + Start: Старт + 'Theme: %s': 'Тема: %s' + 'uptime 00:00:00': ~ + 'Heap: 0\nLVGL: 0': ~ + Meshtastic: ~ + Packet Statistics: Статистика на пакети + "LONG FAST\nLONG SLOW\n-- deprecated --\nMEDIUM SLOW\nMEDIUM FAST\nSHORT SLOW\nSHORT FAST\nLONG MODERATE\nSHORT TURBO": "LONG FAST\nLONG SLOW\n-- старо --\nMEDIUM SLOW\nMEDIUM FAST\nSHORT SLOW\nSHORT FAST\nLONG MODERATE\nSHORT TURBO" + "Client\nClient Mute\nRouter\n-- deprecated --\nRepeater\nTracker\nSensor\nTAK\nClient Hidden\nLost & Found\nTAK Tracker": "Client\nClient Mute\nRouter\n-- старо --\nRepeater\nTracker\nSensor\nTAK\nClient Hidden\nLost & Found\nTAK Tracker" + "Dark\nLight": "Тъмна\nСветла" + none: ~ + Default: ~ + OK: ~ + Cancel: Отмени + 'FrequencySlot: %d (%.2f MHz)': ~ + 'Brightness: %d%%': 'Яркост: %d%%' + 'Timeout: off': 'Таймаут: изкл' + 'Timeout: %ds': 'Таймаут: %ds' + Stop: Стоп + "choose\nnode": "избери\nод" + choose target node: изберете целеви възел + 'heard: !%08x': 'чут: !%08x' + 'Packet Log: %d': 'Лог на пакети: %d' + 'Screen Timeout: off': 'Таймаут на екрана: вкл.' + 'Screen Timeout: %ds': 'Таймаут на екрана: %ds' + 'Screen Brightness: %d%%': 'Яркост на екрана: %d%%' + 'Screen Lock: %s': 'Блокировка на екрана: %s' + 'on': вкл. + 'off': изкл. + 'Message Alert: %s': 'Оповестяване: %s' + Util %0.1f%% Air %0.1f%%: ~ + 'hops: %d': 'хопове: %d' + unknown: неизвестно + : <без име> + '%d active chat(s)': + one: '%d активен чат' + other: '%d активни чатове' + "New message from \n%s": "Ново съобщение от:\n%s" + 'Input Control: %s/%s': ~ + '%d of %d nodes online': + one: '%d възел онлайн' + other: '%d от %d нода са онлайн' + Filtering ...: Филтрация ... + 'Filter: %d of %d nodes': 'Филтър: %d от %d нода' + now: сега + '%d new message': '%d ново съобщение' + '%d new messages': '%d нови съобщения' + 'uptime: %02d:%02d:%02d': "време в работа:\n%02d:%02d:%02d" + 'Heap: %d (%d%%)\nLVGL: %d (%d%%)': ~ + Tools: Инструменти + Filter: Филтер + Highlight: Подчертаване + Primary Channel: Основен канал + Secondary Channels: Вторични канали + Resync ...: Ресинхронизация ... + Rebooting ...: Рестартиране ... + Shutting down ...: Изключване ... + LoRa 0.0 MHz: ~ + silent: тих режим + 'WiFi: ': 'WiFi: <не е настроен>' + 'Lock: off/off': 'Блокировка: изкл./изкл.' + LoRa TX off!: LoRa TX изкл.! + WiFi SSID: Име на WiFi мрежата + WiFi pre-shared Key: ~ + Settings Lock: Блокировка на настройки + 'Lock: %s/%s': 'Блокировка: %s/%s' + Enter Text ...: Въведете сообщение ... + '!Enter Filter ...': '!Въведете фильтр ...' + Enter Filter ...: Въведете фильтр ... + 'WiFi: %s': 'WiFi: %s' + : <не е настроено> + region unset: регион не настроен + Banner & Sound: Банер и звук + Banner only: Само банер + Sound only: Само звук + no signal: ~ + Restoring messages ...: ~ diff --git a/locale/lv_i18n.c b/locale/lv_i18n.c index a51f1c6..82df316 100644 --- a/locale/lv_i18n.c +++ b/locale/lv_i18n.c @@ -66,6 +66,152 @@ static const lv_i18n_lang_t en_lang = {.locale_name = "en", .locale_plural_fn = en_plural_fn}; +static const lv_i18n_phrase_t bg_singulars[] = { + {"no new messages", "няма нови съобщения"}, + {"1 of 1 nodes online", "1 от 1 нода са онлайн"}, + {"User name: ", "Потребителско име:"}, + {"Channel: LongFast", "Канал: LongFast"}, + {"Role: Client", "Роля: Клиент"}, + {"Screen Timeout: 60s", "Таймаут на екрана: 60с"}, + {"Screen Brightness: 60%", "Яркостн а екрана: 60%%"}, + {"Screen Calibration: default", "Калибровка на екрана: по подразбиране"}, + {"Message Alert Buzzer: on", "Звън при съобщение: включено"}, + {"Language: English", "Език: Български"}, + {"Configuration Reset", "ресет на настройките"}, + {"Reboot / Shutdown", "Рестарт / изкл."}, + {"Group Channels", "Групови канали"}, + {"no messages", "няма съобщения"}, + {"Settings", "Настройки"}, + {"Settings (advanced)", "Разширени настройки"}, + {"Locations Map", "Карта на местоположението"}, + {"no chats", "няма чатове"}, + {"Node Options", "Опции на възела"}, + {"Short Name", "Кратко име"}, + {"Long Name", "Дълго име"}, + {"", "<неопределено>"}, + {"Brightness: 60%", "Яркост: 60%%"}, + {"Mouse", "Мишка"}, + {"Keyboard", "Клавиатура"}, + {"Message Alert", "Известие за съобщение"}, + {"NodeDB Reset\nFactory Reset", "Нулиране NodeDB\nНулиране на настройки"}, + {"Channel Name", "Име на канала"}, + {"New Message from\\n", "Ново съобщение от\\n"}, + {"User name: %s", "Име: %s"}, + {"Device Role: %s", "Роля на устройство: %s"}, + {"Screen Calibration: %s", "Калибровка на екрана: %s"}, + {"done", "готово"}, + {"default", "по подразбиране"}, + {"Region: %s", "Регион: %s"}, + {"Channel: %s", "Канал: %s"}, + {"Language: %s", "Език: %s"}, + {"Screen Lock: off", "Блокировка на екрана: off"}, + {"Theme: Dark", "Тема: Тъмна"}, + {"Mesh Detector", "Mesh Детектор"}, + {"Signal Scanner", "Сигнал скенер"}, + {"Trace Route", "Маршрут"}, + {"Neighbors", "Съседи"}, + {"Statistics", "Статистика"}, + {"Packet Log", "Лог на пакети"}, + {"Settings & Tools", "Настройки и инструменти"}, + {"Node Search", "Търсене на нод"}, + {"Screen Lock", "Блокировка на екрана"}, + {"Lock PIN", "PIN-код"}, + {"Ringtone", "Рингтон"}, + {"Zone", "Зона"}, + {"City", "Град"}, + {"Unknown", "Неизвестно"}, + {"Offline", "Не е в мрежата"}, + {"Public Key", "Публичен ключ"}, + {"Hops away", "Хопове"}, + {"Position", "Позиция"}, + {"Name", "Име"}, + {"Active Chat", "Активен чат"}, + {"Telemetry", "Телеметрия"}, + {"Start", "Старт"}, + {"Theme: %s", "Тема: %s"}, + {"Packet Statistics", "Статистика на пакети"}, + {"LONG FAST\nLONG SLOW\n-- deprecated --\nMEDIUM SLOW\nMEDIUM FAST\nSHORT SLOW\nSHORT FAST\nLONG MODERATE\nSHORT TURBO", + "LONG FAST\nLONG SLOW\n-- старо --\nMEDIUM SLOW\nMEDIUM FAST\nSHORT SLOW\nSHORT FAST\nLONG MODERATE\nSHORT TURBO"}, + {"Client\nClient Mute\nRouter\n-- deprecated --\nRepeater\nTracker\nSensor\nTAK\nClient Hidden\nLost & Found\nTAK Tracker", + "Client\nClient Mute\nRouter\n-- старо --\nRepeater\nTracker\nSensor\nTAK\nClient Hidden\nLost & Found\nTAK Tracker"}, + {"Dark\nLight", "Тъмна\nСветла"}, + {"Cancel", "Отмени"}, + {"Brightness: %d%%", "Яркост: %d%%"}, + {"Timeout: off", "Таймаут: изкл"}, + {"Timeout: %ds", "Таймаут: %ds"}, + {"Stop", "Стоп"}, + {"choose\nnode", "избери\nод"}, + {"choose target node", "изберете целеви възел"}, + {"heard: !%08x", "чут: !%08x"}, + {"Packet Log: %d", "Лог на пакети: %d"}, + {"Screen Timeout: off", "Таймаут на екрана: вкл."}, + {"Screen Timeout: %ds", "Таймаут на екрана: %ds"}, + {"Screen Brightness: %d%%", "Яркост на екрана: %d%%"}, + {"Screen Lock: %s", "Блокировка на екрана: %s"}, + {"on", "вкл."}, + {"off", "изкл."}, + {"Message Alert: %s", "Оповестяване: %s"}, + {"hops: %d", "хопове: %d"}, + {"unknown", "неизвестно"}, + {"", "<без име>"}, + {"New message from \n%s", "Ново съобщение от:\n%s"}, + {"Filtering ...", "Филтрация ..."}, + {"Filter: %d of %d nodes", "Филтър: %d от %d нода"}, + {"now", "сега"}, + {"%d new message", "%d ново съобщение"}, + {"%d new messages", "%d нови съобщения"}, + {"uptime: %02d:%02d:%02d", "време в работа:\n%02d:%02d:%02d"}, + {"Tools", "Инструменти"}, + {"Filter", "Филтер"}, + {"Highlight", "Подчертаване"}, + {"Primary Channel", "Основен канал"}, + {"Secondary Channels", "Вторични канали"}, + {"Resync ...", "Ресинхронизация ..."}, + {"Rebooting ...", "Рестартиране ..."}, + {"Shutting down ...", "Изключване ..."}, + {"silent", "тих режим"}, + {"WiFi: ", "WiFi: <не е настроен>"}, + {"Lock: off/off", "Блокировка: изкл./изкл."}, + {"LoRa TX off!", "LoRa TX изкл.!"}, + {"WiFi SSID", "Име на WiFi мрежата"}, + {"Settings Lock", "Блокировка на настройки"}, + {"Lock: %s/%s", "Блокировка: %s/%s"}, + {"Enter Text ...", "Въведете сообщение ..."}, + {"!Enter Filter ...", "!Въведете фильтр ..."}, + {"Enter Filter ...", "Въведете фильтр ..."}, + {"WiFi: %s", "WiFi: %s"}, + {"", "<не е настроено>"}, + {"region unset", "регион не настроен"}, + {"Banner & Sound", "Банер и звук"}, + {"Banner only", "Само банер"}, + {"Sound only", "Само звук"}, + {NULL, NULL} // End mark +}; + +static lv_i18n_phrase_t bg_plurals_one[] = { + {"%d active chat(s)", "%d активен чат"}, {"%d of %d nodes online", "%d възел онлайн"}, {NULL, NULL} // End mark +}; + +static lv_i18n_phrase_t bg_plurals_other[] = { + {"%d active chat(s)", "%d активни чатове"}, {"%d of %d nodes online", "%d от %d нода са онлайн"}, {NULL, NULL} // End mark +}; + +static uint8_t bg_plural_fn(int32_t num) +{ + uint32_t n = op_n(num); + UNUSED(n); + + if ((n == 1)) + return LV_I18N_PLURAL_TYPE_ONE; + return LV_I18N_PLURAL_TYPE_OTHER; +} + +static const lv_i18n_lang_t bg_lang = {.locale_name = "bg", + .singulars = bg_singulars, + .plurals[LV_I18N_PLURAL_TYPE_ONE] = bg_plurals_one, + .plurals[LV_I18N_PLURAL_TYPE_OTHER] = bg_plurals_other, + .locale_plural_fn = bg_plural_fn}; + static const lv_i18n_phrase_t de_singulars[] = { {"User name: %s", "Benutzer: %s"}, {"Device Role: %s", "Gerätemodus: %s"}, @@ -2835,8 +2981,8 @@ static const lv_i18n_lang_t zh_cn_lang = {.locale_name = "zh-CN", .locale_plural_fn = zh_cn_plural_fn}; const lv_i18n_language_pack_t lv_i18n_language_pack[] = { - &en_lang, &de_lang, &el_lang, &es_lang, &fi_lang, &fr_lang, &it_lang, &nl_lang, &no_lang, &pl_lang, - &pt_lang, &ro_lang, &ru_lang, &se_lang, &sl_lang, &sr_lang, &tr_lang, &uk_lang, &zh_cn_lang, + &en_lang, &bg_lang, &de_lang, &el_lang, &es_lang, &fi_lang, &fr_lang, &it_lang, &nl_lang, &no_lang, + &pl_lang, &pt_lang, &ro_lang, &ru_lang, &se_lang, &sl_lang, &sr_lang, &tr_lang, &uk_lang, &zh_cn_lang, NULL // End mark }; diff --git a/source/graphics/TFT/TFTView_320x240.cpp b/source/graphics/TFT/TFTView_320x240.cpp index 18c6656..f2d1225 100644 --- a/source/graphics/TFT/TFTView_320x240.cpp +++ b/source/graphics/TFT/TFTView_320x240.cpp @@ -1508,11 +1508,7 @@ void TFTView_320x240::ui_event_MemoryButton(lv_event_t *e) void TFTView_320x240::ui_event_QrButton(lv_event_t *e) { - meshtastic_SharedContact contact { .node_num = THIS->ownNode, - .has_user = true, - .user = THIS->db.user, - .should_ignore = false - }; + meshtastic_SharedContact contact{.node_num = THIS->ownNode, .has_user = true, .user = THIS->db.user, .should_ignore = false}; meshtastic_Data_payload_t payload; payload.size = pb_encode_to_bytes(payload.bytes, sizeof(payload.bytes), &meshtastic_SharedContact_msg, &contact); @@ -6104,10 +6100,10 @@ void TFTView_320x240::updateSecurityConfig(const meshtastic_Config_SecurityConfi { db.config.security = cfg; db.config.has_security = true; - + // display public key in qr code label char buf[64]; - lv_snprintf(buf, sizeof(buf), "%s", pskToBase64((uint8_t*)cfg.public_key.bytes, cfg.public_key.size).c_str()); + lv_snprintf(buf, sizeof(buf), "%s", pskToBase64((uint8_t *)cfg.public_key.bytes, cfg.public_key.size).c_str()); lv_label_set_text(objects.home_qr_label, buf); } @@ -6995,7 +6991,7 @@ void TFTView_320x240::updateAllLastHeard(void) void TFTView_320x240::updateUnreadMessages(void) { - char buf[32]; + char buf[64]; if (unreadMessages > 0) { sprintf(buf, unreadMessages == 1 ? _("%d new message") : _("%d new messages"), unreadMessages); lv_obj_set_style_bg_img_src(objects.home_mail_button, &img_home_mail_unread_button_image,