From 134a45dd70b74b8bce8b14e354873d0c7705e936 Mon Sep 17 00:00:00 2001 From: mverch67 Date: Sun, 16 Jun 2024 17:15:17 +0200 Subject: [PATCH] localisation preparations --- generated/ui_320x240/screens.c | 96 ++++---- library.json | 1 + locale/README.md | 18 ++ locale/de.yml | 48 ++++ locale/en.yml | 48 ++++ locale/es.yml | 48 ++++ locale/fr.yml | 48 ++++ locale/it.yml | 48 ++++ locale/lv_i18n.c | 393 +++++++++++++++++++++++++++++++++ locale/lv_i18n.h | 80 +++++++ locale/pl.yml | 48 ++++ locale/pt.yml | 48 ++++ locale/ro.yml | 48 ++++ source/TFTView_320x240.cpp | 35 ++- 14 files changed, 951 insertions(+), 56 deletions(-) create mode 100644 locale/README.md create mode 100644 locale/de.yml create mode 100644 locale/en.yml create mode 100644 locale/es.yml create mode 100644 locale/fr.yml create mode 100644 locale/it.yml create mode 100644 locale/lv_i18n.c create mode 100644 locale/lv_i18n.h create mode 100644 locale/pl.yml create mode 100644 locale/pt.yml create mode 100644 locale/ro.yml diff --git a/generated/ui_320x240/screens.c b/generated/ui_320x240/screens.c index 0a9521e..5daeefa 100644 --- a/generated/ui_320x240/screens.c +++ b/generated/ui_320x240/screens.c @@ -6,6 +6,8 @@ #include "styles.h" #include "ui.h" +#include "lv_i18n.h" + objects_t objects; lv_obj_t *tick_value_change_obj; @@ -348,7 +350,7 @@ void create_screen_main_screen() { objects.home_mail_label = obj; lv_obj_set_pos(obj, 105, 50); lv_obj_set_size(obj, LV_PCT(80), LV_SIZE_CONTENT); - lv_label_set_text(obj, "no new messages"); + lv_label_set_text(obj, _("no new messages")); } { // HomeNodesButton @@ -370,7 +372,7 @@ void create_screen_main_screen() { objects.home_nodes_label = obj; lv_obj_set_pos(obj, 105, 50); lv_obj_set_size(obj, LV_PCT(80), LV_SIZE_CONTENT); - lv_label_set_text(obj, "1 of 1 nodes online"); + lv_label_set_text(obj, _("1 of 1 nodes online")); } { // HomeLocationButton @@ -999,7 +1001,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_DOT); - lv_label_set_text(obj, "ABCD: Username"); + lv_label_set_text(obj, ""); lv_obj_set_style_align(obj, LV_ALIGN_TOP_MID, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_align(obj, LV_TEXT_ALIGN_LEFT, LV_PART_MAIN | LV_STATE_DEFAULT); } @@ -1021,7 +1023,7 @@ void create_screen_main_screen() { objects.del_label = obj; lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); - lv_label_set_text(obj, "DEL"); + lv_label_set_text(obj, _("DEL")); lv_obj_set_style_align(obj, LV_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); } } @@ -1084,7 +1086,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_DOT); - lv_label_set_text(obj, "User: "); + lv_label_set_text(obj, _("User name: ")); lv_obj_set_style_bg_color(obj, lv_color_hex(0xff000000), LV_PART_MAIN | LV_STATE_DISABLED); } } @@ -1139,7 +1141,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_DOT); - lv_label_set_text(obj, "Modem Preset: LONG FAST"); + lv_label_set_text(obj, _("Modem Preset: LONG FAST")); } } } @@ -1166,7 +1168,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_DOT); - lv_label_set_text(obj, "Channel: LongFast"); + lv_label_set_text(obj, _("Channel: LongFast")); } } } @@ -1193,7 +1195,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_DOT); - lv_label_set_text(obj, "Role: Client"); + lv_label_set_text(obj, _("Role: Client")); } } } @@ -1220,7 +1222,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_DOT); - lv_label_set_text(obj, "Screen Timeout: 60s"); + lv_label_set_text(obj, _("Screen Timeout: 60s")); } } } @@ -1247,7 +1249,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_DOT); - lv_label_set_text(obj, "Screen Brightness: 60%"); + lv_label_set_text(obj, _("Screen Brightness: 60%")); lv_obj_set_style_text_color(obj, lv_color_hex(0xff606060), LV_PART_MAIN | LV_STATE_DISABLED); } } @@ -1275,7 +1277,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_DOT); - lv_label_set_text(obj, "Screen Calibration: default"); + lv_label_set_text(obj, _("Screen Calibration: default")); lv_obj_set_style_text_color(obj, lv_color_hex(0xff606060), LV_PART_MAIN | LV_STATE_DISABLED); } } @@ -1303,7 +1305,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_DOT); - lv_label_set_text(obj, "Input Control: none/none"); + lv_label_set_text(obj, _("Input Control: none/none")); } } } @@ -1330,7 +1332,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_DOT); - lv_label_set_text(obj, "Message Alert Buzzer: on"); + lv_label_set_text(obj, _("Message Alert Buzzer: on")); } } } @@ -1357,7 +1359,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_DOT); - lv_label_set_text(obj, "Language: English"); + lv_label_set_text(obj, _("Language: English")); } } } @@ -1384,7 +1386,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_DOT); - lv_label_set_text(obj, "Configuration Reset"); + lv_label_set_text(obj, _("Configuration Reset")); } } } @@ -1411,7 +1413,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_DOT); - lv_label_set_text(obj, "Reboot / Shutdown"); + lv_label_set_text(obj, _("Reboot / Shutdown")); } } } @@ -1490,7 +1492,7 @@ void create_screen_main_screen() { objects.top_nodes_online_label = obj; lv_obj_set_pos(obj, 25, 0); lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); - lv_label_set_text(obj, "1 of 1 nodes online"); + lv_label_set_text(obj, _("1 of 1 nodes online")); lv_obj_set_style_text_font(obj, &ui_font_montserrat_16, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_color(obj, lv_color_hex(0xffe0e0e0), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_align(obj, LV_ALIGN_LEFT_MID, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -1529,7 +1531,7 @@ void create_screen_main_screen() { objects.top_user_group_label = obj; lv_obj_set_pos(obj, 25, 0); lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); - lv_label_set_text(obj, "Group Channels"); + lv_label_set_text(obj, _("Group Channels")); lv_obj_set_style_text_font(obj, &ui_font_montserrat_16, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_color(obj, lv_color_hex(0xffe0e0e0), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_align(obj, LV_ALIGN_LEFT_MID, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -1568,7 +1570,7 @@ void create_screen_main_screen() { objects.top_group_chat_label = obj; lv_obj_set_pos(obj, 25, 0); lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); - lv_label_set_text(obj, "no messages"); + lv_label_set_text(obj, _("no messages")); lv_obj_set_style_text_font(obj, &ui_font_montserrat_16, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_color(obj, lv_color_hex(0xffe0e0e0), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_align(obj, LV_ALIGN_LEFT_MID, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -1607,7 +1609,7 @@ void create_screen_main_screen() { objects.top_basic_settings_label = obj; lv_obj_set_pos(obj, 25, 0); lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); - lv_label_set_text(obj, "Settings"); + lv_label_set_text(obj, _("Settings")); lv_obj_set_style_text_font(obj, &ui_font_montserrat_16, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_color(obj, lv_color_hex(0xffe0e0e0), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_align(obj, LV_ALIGN_LEFT_MID, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -1646,7 +1648,7 @@ void create_screen_main_screen() { objects.top_advanced_settings_label = obj; lv_obj_set_pos(obj, 25, 0); lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); - lv_label_set_text(obj, "Settings (advanced)"); + lv_label_set_text(obj, _("Settings (advanced)")); lv_obj_set_style_text_font(obj, &ui_font_montserrat_16, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_color(obj, lv_color_hex(0xffe0e0e0), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_align(obj, LV_ALIGN_LEFT_MID, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -1685,7 +1687,7 @@ void create_screen_main_screen() { objects.top_map_label = obj; lv_obj_set_pos(obj, 25, 0); lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); - lv_label_set_text(obj, "Locations Map"); + lv_label_set_text(obj, _("Locations Map")); lv_obj_set_style_text_font(obj, &ui_font_montserrat_16, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_color(obj, lv_color_hex(0xffe0e0e0), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_align(obj, LV_ALIGN_LEFT_MID, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -1724,7 +1726,7 @@ void create_screen_main_screen() { objects.top_chats_label = obj; lv_obj_set_pos(obj, 25, 0); lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); - lv_label_set_text(obj, "no chats"); + lv_label_set_text(obj, _("no chats")); lv_obj_set_style_text_font(obj, &ui_font_montserrat_16, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_color(obj, lv_color_hex(0xffe0e0e0), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_align(obj, LV_ALIGN_LEFT_MID, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -1764,7 +1766,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 25, 0); lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_SCROLL); - lv_label_set_text(obj, "no messages"); + lv_label_set_text(obj, _("no messages")); lv_obj_set_style_text_font(obj, &ui_font_montserrat_16, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_color(obj, lv_color_hex(0xffe0e0e0), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_align(obj, LV_ALIGN_LEFT_MID, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -1803,7 +1805,7 @@ void create_screen_main_screen() { objects.top_node_options_label = obj; lv_obj_set_pos(obj, 25, 0); lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); - lv_label_set_text(obj, "Node Options"); + lv_label_set_text(obj, _("Node Options")); lv_obj_set_style_text_font(obj, &ui_font_montserrat_16, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_color(obj, lv_color_hex(0xffe0e0e0), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_align(obj, LV_ALIGN_LEFT_MID, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -1888,7 +1890,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, 200, LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_CLIP); - lv_label_set_text(obj, "Short Name"); + lv_label_set_text(obj, _("Short Name")); lv_obj_set_style_text_color(obj, lv_color_hex(0xffaafbff), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_align(obj, LV_ALIGN_TOP_MID, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_align(obj, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -1927,7 +1929,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 60); lv_obj_set_size(obj, 200, LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_CLIP); - lv_label_set_text(obj, "Long Name"); + lv_label_set_text(obj, _("Long Name")); lv_obj_set_style_text_color(obj, lv_color_hex(0xffaafbff), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_align(obj, LV_ALIGN_TOP_MID, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_align(obj, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -2046,7 +2048,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_SCROLL); - lv_label_set_text(obj, ""); + lv_label_set_text(obj, _("")); lv_obj_set_style_bg_color(obj, lv_color_hex(0xff000000), LV_PART_MAIN | LV_STATE_DISABLED); lv_obj_set_style_align(obj, LV_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_color(obj, lv_color_hex(0xfff0f0f0), LV_PART_MAIN | LV_STATE_DEFAULT); @@ -2091,7 +2093,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_SCROLL); - lv_label_set_text(obj, ""); + lv_label_set_text(obj, _("")); lv_obj_set_style_bg_color(obj, lv_color_hex(0xff000000), LV_PART_MAIN | LV_STATE_DISABLED); lv_obj_set_style_align(obj, LV_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_color(obj, lv_color_hex(0xfff0f0f0), LV_PART_MAIN | LV_STATE_DEFAULT); @@ -2126,7 +2128,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_SCROLL); - lv_label_set_text(obj, ""); + lv_label_set_text(obj, _("")); lv_obj_set_style_bg_color(obj, lv_color_hex(0xff000000), LV_PART_MAIN | LV_STATE_DISABLED); lv_obj_set_style_align(obj, LV_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_color(obj, lv_color_hex(0xfff0f0f0), LV_PART_MAIN | LV_STATE_DEFAULT); @@ -2161,7 +2163,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_SCROLL); - lv_label_set_text(obj, ""); + lv_label_set_text(obj, _("")); lv_obj_set_style_bg_color(obj, lv_color_hex(0xff000000), LV_PART_MAIN | LV_STATE_DISABLED); lv_obj_set_style_align(obj, LV_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_color(obj, lv_color_hex(0xfff0f0f0), LV_PART_MAIN | LV_STATE_DEFAULT); @@ -2196,7 +2198,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_SCROLL); - lv_label_set_text(obj, ""); + lv_label_set_text(obj, _("")); lv_obj_set_style_bg_color(obj, lv_color_hex(0xff000000), LV_PART_MAIN | LV_STATE_DISABLED); lv_obj_set_style_align(obj, LV_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_color(obj, lv_color_hex(0xfff0f0f0), LV_PART_MAIN | LV_STATE_DEFAULT); @@ -2266,7 +2268,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_SCROLL); - lv_label_set_text(obj, ""); + lv_label_set_text(obj, _("")); lv_obj_set_style_bg_color(obj, lv_color_hex(0xff000000), LV_PART_MAIN | LV_STATE_DISABLED); lv_obj_set_style_align(obj, LV_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_color(obj, lv_color_hex(0xfff0f0f0), LV_PART_MAIN | LV_STATE_DEFAULT); @@ -2301,7 +2303,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_SCROLL); - lv_label_set_text(obj, ""); + lv_label_set_text(obj, _("")); lv_obj_set_style_bg_color(obj, lv_color_hex(0xff000000), LV_PART_MAIN | LV_STATE_DISABLED); lv_obj_set_style_align(obj, LV_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_color(obj, lv_color_hex(0xfff0f0f0), LV_PART_MAIN | LV_STATE_DEFAULT); @@ -2404,7 +2406,7 @@ void create_screen_main_screen() { objects.settings_modem_preset_dropdown = obj; lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, 180, 30); - lv_dropdown_set_options(obj, "LONG FAST\nLONG SLOW\nVERY LONG SLOW\nMEDIUM SLOW\nMEDIUM FAST\nSHORT SLOW\nSHORT FAST\nLONG MODERATE"); + lv_dropdown_set_options(obj, _("LONG FAST\nLONG SLOW\nVERY LONG SLOW\nMEDIUM SLOW\nMEDIUM FAST\nSHORT SLOW\nSHORT FAST\nLONG MODERATE")); lv_obj_set_style_align(obj, LV_ALIGN_TOP_MID, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_bg_color(obj, lv_color_hex(0xff404040), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_border_color(obj, lv_color_hex(0xffe0e0e0), LV_PART_MAIN | LV_STATE_DEFAULT); @@ -2418,7 +2420,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, LV_PCT(0), 40); lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_CLIP); - lv_label_set_text(obj, "FrequencySlot: 1 (902.0MHz)"); + lv_label_set_text(obj, _("FrequencySlot: 1 (902.0MHz)")); lv_obj_set_style_align(obj, LV_ALIGN_TOP_MID, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_font(obj, &ui_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); } @@ -2487,7 +2489,7 @@ void create_screen_main_screen() { objects.settings_device_role_dropdown = obj; lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, 150, 30); - lv_dropdown_set_options(obj, "Client\nClient Mute\nRouter\nRouter Client\nRepeater\nTracker\nSensor\nTAK\nClient Hidden\nLost & Found\nTAK Tracker"); + lv_dropdown_set_options(obj, _("Client\nClient Mute\nRouter\nRouter Client\nRepeater\nTracker\nSensor\nTAK\nClient Hidden\nLost & Found\nTAK Tracker")); lv_obj_set_style_align(obj, LV_ALIGN_TOP_MID, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_bg_color(obj, lv_color_hex(0xff404040), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_border_color(obj, lv_color_hex(0xffe0e0e0), LV_PART_MAIN | LV_STATE_DEFAULT); @@ -2539,7 +2541,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, LV_PCT(0), 0); lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_SCROLL); - lv_label_set_text(obj, "Brightness: 60%"); + lv_label_set_text(obj, _("Brightness: 60%")); lv_obj_set_style_align(obj, LV_ALIGN_TOP_MID, LV_PART_MAIN | LV_STATE_DEFAULT); } { @@ -2608,7 +2610,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, LV_PCT(0), 0); lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_SCROLL); - lv_label_set_text(obj, "Timeout: 60s"); + lv_label_set_text(obj, _("Timeout: 60s")); lv_obj_set_style_align(obj, LV_ALIGN_TOP_MID, LV_PART_MAIN | LV_STATE_DEFAULT); } { @@ -2674,7 +2676,7 @@ void create_screen_main_screen() { lv_obj_t *obj = lv_label_create(parent_obj); lv_obj_set_pos(obj, 0, 5); lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); - lv_label_set_text(obj, "Mouse"); + lv_label_set_text(obj, _("Mouse")); lv_obj_set_style_text_color(obj, lv_color_hex(0xffffffff), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_align(obj, LV_ALIGN_TOP_LEFT, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_align(obj, LV_TEXT_ALIGN_LEFT, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -2696,7 +2698,7 @@ void create_screen_main_screen() { lv_obj_t *obj = lv_label_create(parent_obj); lv_obj_set_pos(obj, 0, 48); lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); - lv_label_set_text(obj, "Keyboard"); + lv_label_set_text(obj, _("Keyboard")); lv_obj_set_style_text_color(obj, lv_color_hex(0xffffffff), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_align(obj, LV_ALIGN_TOP_LEFT, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_align(obj, LV_TEXT_ALIGN_LEFT, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -2756,7 +2758,7 @@ void create_screen_main_screen() { lv_obj_t *obj = lv_label_create(parent_obj); lv_obj_set_pos(obj, 0, 10); lv_obj_set_size(obj, 125, LV_SIZE_CONTENT); - lv_label_set_text(obj, "Message Alert"); + lv_label_set_text(obj, _("Message Alert")); lv_obj_set_style_text_color(obj, lv_color_hex(0xffffffff), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_align(obj, LV_ALIGN_TOP_LEFT, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_align(obj, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -2870,7 +2872,7 @@ void create_screen_main_screen() { objects.settings_reset_dropdown = obj; lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, 150, 30); - lv_dropdown_set_options(obj, "NodeDB Reset\nFactory Reset"); + lv_dropdown_set_options(obj, _("NodeDB Reset\nFactory Reset")); lv_obj_set_style_align(obj, LV_ALIGN_TOP_MID, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_bg_color(obj, lv_color_hex(0xff404040), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_border_color(obj, lv_color_hex(0xffe0e0e0), LV_PART_MAIN | LV_STATE_DEFAULT); @@ -2924,7 +2926,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 0); lv_obj_set_size(obj, 200, LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_CLIP); - lv_label_set_text(obj, "Channel Name"); + lv_label_set_text(obj, _("Channel Name")); lv_obj_set_style_text_color(obj, lv_color_hex(0xffaafbff), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_align(obj, LV_ALIGN_TOP_LEFT, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_align(obj, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -2965,7 +2967,7 @@ void create_screen_main_screen() { lv_obj_set_pos(obj, 0, 60); lv_obj_set_size(obj, 200, LV_SIZE_CONTENT); lv_label_set_long_mode(obj, LV_LABEL_LONG_CLIP); - lv_label_set_text(obj, "Pre-shared Key"); + lv_label_set_text(obj, _("Pre-shared Key")); lv_obj_set_style_text_color(obj, lv_color_hex(0xffaafbff), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_align(obj, LV_ALIGN_TOP_LEFT, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_align(obj, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -3073,7 +3075,7 @@ void create_screen_main_screen() { objects.msg_popup_label = obj; lv_obj_set_pos(obj, 10, 0); lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); - lv_label_set_text(obj, "New Message from\n"); + lv_label_set_text(obj, _("New Message from\n")); lv_obj_set_style_align(obj, LV_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_color(obj, lv_color_hex(0xffffffff), LV_PART_MAIN | LV_STATE_DEFAULT); } @@ -3103,7 +3105,7 @@ void create_screen_main_screen() { objects.alert_label = obj; lv_obj_set_pos(obj, 10, 0); lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); - lv_label_set_text(obj, "Resynch..."); + lv_label_set_text(obj, _("Resynch...")); lv_obj_set_style_align(obj, LV_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_color(obj, lv_color_hex(0xffff0000), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_font(obj, &lv_font_montserrat_20, LV_PART_MAIN | LV_STATE_DEFAULT); diff --git a/library.json b/library.json index 4eb1192..5b197a9 100644 --- a/library.json +++ b/library.json @@ -27,6 +27,7 @@ "flags": [ "-Iinclude", "-Igenerated", + "-Ilocale", "-Iportduino", "-DLV_LVGL_H_INCLUDE_SIMPLE", "-DLV_CONF_INCLUDE_SIMPLE", diff --git a/locale/README.md b/locale/README.md new file mode 100644 index 0000000..fc87a1f --- /dev/null +++ b/locale/README.md @@ -0,0 +1,18 @@ +To install: + +``` + npm i lv_i18n -g +``` + +To extract: + +``` + lv_i18n extract -s 'generated/**/*.+(c|cpp|h|hpp)' -s 'source/**/*.+(c|cpp|h|hpp)' -t 'locale/*.yml' +``` + +To compile: + +``` + cd locale + npx lv_i18n compile -t './*.yml' -o '.' +``` diff --git a/locale/de.yml b/locale/de.yml new file mode 100644 index 0000000..2410bd3 --- /dev/null +++ b/locale/de.yml @@ -0,0 +1,48 @@ +de: + "User name: %s": "Benutzer: %s" + "Device Role: %s": "Gerätemodus: %s" + no new messages: "keine neue Nachricht" + 1 of 1 nodes online: ~ + DEL: ~ + "User name: ": "Benutzer: " + "Modem Preset: LONG FAST": "Modem: LONG FAST" + "Channel: LongFast": "Gruppen-Kanäle: LongFast" + "Role: Client": "Gerätemodus: Client" + "Screen Timeout: 60s": "Bild aus nach: 60s" + "Screen Brightness: 60%": "Bildschirmhelligkeit: 60%" + "Screen Calibration: default": "Kalibrierung: Standard" + "Input Control: none/none": "Eingabe: ohne/ohne" + "Message Alert Buzzer: on": "Akustischer Alarm: ein" + "Language: English": "Sprache: Deutsch" + Configuration Reset: Einstellungen zurücksetzen + Reboot / Shutdown: Neustart / Ausschalten + Group Channels: Gruppen Kanäle + no messages: Keine Nachrichten + Settings: Einstellungen + Settings (advanced): Erweiterte Einstellungen + Locations Map: Karte + no chats: Keine Gespräche + Node Options: Optionen + Short Name: Kurzname + Long Name: Langname + : + LONG FAST\nLONG SLOW\nVERY LONG SLOW\nMEDIUM SLOW\nMEDIUM FAST\nSHORT SLOW\nSHORT FAST\nLONG MODERATE: ~ + "FrequencySlot: 1 (902.0MHz)": "Frequenz: 1 (902.0MHz)" + Client\nClient Mute\nRouter\nRouter Client\nRepeater\nTracker\nSensor\nTAK\nClient Hidden\nLost & Found\nTAK Tracker: ~ + "Brightness: 60%": "Helligkeit: 60%" + "Timeout: 60s": "Bild aus nach: 60s" + Mouse: Maus + Keyboard: Tastatur + Message Alert: Alarm + NodeDB Reset\nFactory Reset: Einstellungen zurücksetzen + Channel Name: Kanalname + Pre-shared Key: Schlüssel + New Message from\n: Neue Nachricht von\n + Resynch...: Neu Synchronisieren... + "Screen Calibration: %s": "Kalibrierung: %s" + done: "erledigt" + default: "Standard" + "Region: %s": ~ + "Modem Preset: %s": "Voreinstellung: %s" + "Channel: %s": "Guppen-Kanäle: %s" + "Language: %s": "Sprache: %s" diff --git a/locale/en.yml b/locale/en.yml new file mode 100644 index 0000000..b9dee81 --- /dev/null +++ b/locale/en.yml @@ -0,0 +1,48 @@ +en: + "User name: %s": ~ + "Device Role: %s": ~ + no new messages: ~ + 1 of 1 nodes online: ~ + DEL: ~ + "User name: ": ~ + "Modem Preset: LONG FAST": ~ + "Channel: LongFast": ~ + "Role: Client": ~ + "Screen Timeout: 60s": ~ + "Screen Brightness: 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: ~ + : ~ + LONG FAST\nLONG SLOW\nVERY LONG SLOW\nMEDIUM SLOW\nMEDIUM FAST\nSHORT SLOW\nSHORT FAST\nLONG MODERATE: ~ + "FrequencySlot: 1 (902.0MHz)": ~ + Client\nClient Mute\nRouter\nRouter Client\nRepeater\nTracker\nSensor\nTAK\nClient Hidden\nLost & Found\nTAK Tracker: ~ + "Brightness: 60%": ~ + "Timeout: 60s": ~ + Mouse: ~ + Keyboard: ~ + Message Alert: ~ + NodeDB Reset\nFactory Reset: ~ + Channel Name: ~ + Pre-shared Key: ~ + New Message from\n: ~ + Resynch...: ~ + "Screen Calibration: %s": ~ + done: ~ + default: ~ + "Region: %s": ~ + "Modem Preset: %s": ~ + "Channel: %s": ~ + "Language: %s": ~ diff --git a/locale/es.yml b/locale/es.yml new file mode 100644 index 0000000..6f63ca5 --- /dev/null +++ b/locale/es.yml @@ -0,0 +1,48 @@ +es: + no new messages: ~ + 1 of 1 nodes online: ~ + DEL: ~ + "User name: ": ~ + "Modem Preset: LONG FAST": ~ + "Channel: LongFast": ~ + "Role: Client": ~ + "Screen Timeout: 60s": ~ + "Screen Brightness: 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: ~ + : ~ + LONG FAST\nLONG SLOW\nVERY LONG SLOW\nMEDIUM SLOW\nMEDIUM FAST\nSHORT SLOW\nSHORT FAST\nLONG MODERATE: ~ + "FrequencySlot: 1 (902.0MHz)": ~ + Client\nClient Mute\nRouter\nRouter Client\nRepeater\nTracker\nSensor\nTAK\nClient Hidden\nLost & Found\nTAK Tracker: ~ + "Brightness: 60%": ~ + "Timeout: 60s": ~ + Mouse: ~ + Keyboard: ~ + Message Alert: ~ + NodeDB Reset\nFactory Reset: ~ + Channel Name: ~ + Pre-shared Key: ~ + New Message from\n: ~ + Resynch...: ~ + "User name: %s": ~ + "Device Role: %s": ~ + "Screen Calibration: %s": ~ + done: ~ + default: ~ + "Region: %s": ~ + "Modem Preset: %s": ~ + "Channel: %s": ~ + "Language: %s": ~ diff --git a/locale/fr.yml b/locale/fr.yml new file mode 100644 index 0000000..9af376e --- /dev/null +++ b/locale/fr.yml @@ -0,0 +1,48 @@ +fr: + no new messages: ~ + 1 of 1 nodes online: ~ + DEL: ~ + "User name: ": ~ + "Modem Preset: LONG FAST": ~ + "Channel: LongFast": ~ + "Role: Client": ~ + "Screen Timeout: 60s": ~ + "Screen Brightness: 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: ~ + : ~ + LONG FAST\nLONG SLOW\nVERY LONG SLOW\nMEDIUM SLOW\nMEDIUM FAST\nSHORT SLOW\nSHORT FAST\nLONG MODERATE: ~ + "FrequencySlot: 1 (902.0MHz)": ~ + Client\nClient Mute\nRouter\nRouter Client\nRepeater\nTracker\nSensor\nTAK\nClient Hidden\nLost & Found\nTAK Tracker: ~ + "Brightness: 60%": ~ + "Timeout: 60s": ~ + Mouse: ~ + Keyboard: ~ + Message Alert: ~ + NodeDB Reset\nFactory Reset: ~ + Channel Name: ~ + Pre-shared Key: ~ + New Message from\n: ~ + Resynch...: ~ + "User name: %s": ~ + "Device Role: %s": ~ + "Screen Calibration: %s": ~ + done: ~ + default: ~ + "Region: %s": ~ + "Modem Preset: %s": ~ + "Channel: %s": ~ + "Language: %s": ~ diff --git a/locale/it.yml b/locale/it.yml new file mode 100644 index 0000000..03c5061 --- /dev/null +++ b/locale/it.yml @@ -0,0 +1,48 @@ +it: + no new messages: ~ + 1 of 1 nodes online: ~ + DEL: ~ + "User name: ": ~ + "Modem Preset: LONG FAST": ~ + "Channel: LongFast": ~ + "Role: Client": ~ + "Screen Timeout: 60s": ~ + "Screen Brightness: 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: ~ + : ~ + LONG FAST\nLONG SLOW\nVERY LONG SLOW\nMEDIUM SLOW\nMEDIUM FAST\nSHORT SLOW\nSHORT FAST\nLONG MODERATE: ~ + "FrequencySlot: 1 (902.0MHz)": ~ + Client\nClient Mute\nRouter\nRouter Client\nRepeater\nTracker\nSensor\nTAK\nClient Hidden\nLost & Found\nTAK Tracker: ~ + "Brightness: 60%": ~ + "Timeout: 60s": ~ + Mouse: ~ + Keyboard: ~ + Message Alert: ~ + NodeDB Reset\nFactory Reset: ~ + Channel Name: ~ + Pre-shared Key: ~ + New Message from\n: ~ + Resynch...: ~ + "User name: %s": ~ + "Device Role: %s": ~ + "Screen Calibration: %s": ~ + done: ~ + default: ~ + "Region: %s": ~ + "Modem Preset: %s": ~ + "Channel: %s": ~ + "Language: %s": ~ diff --git a/locale/lv_i18n.c b/locale/lv_i18n.c new file mode 100644 index 0000000..4c780d0 --- /dev/null +++ b/locale/lv_i18n.c @@ -0,0 +1,393 @@ +#include "./lv_i18n.h" + +//////////////////////////////////////////////////////////////////////////////// +// Define plural operands +// http://unicode.org/reports/tr35/tr35-numbers.html#Operands + +// Integer version, simplified + +#define UNUSED(x) (void)(x) + +static inline uint32_t op_n(int32_t val) +{ + return (uint32_t)(val < 0 ? -val : val); +} +static inline uint32_t op_i(uint32_t val) +{ + return val; +} +// always zero, when decimal part not exists. +static inline uint32_t op_v(uint32_t val) +{ + UNUSED(val); + return 0; +} +static inline uint32_t op_w(uint32_t val) +{ + UNUSED(val); + return 0; +} +static inline uint32_t op_f(uint32_t val) +{ + UNUSED(val); + return 0; +} +static inline uint32_t op_t(uint32_t val) +{ + UNUSED(val); + return 0; +} + +static uint8_t en_plural_fn(int32_t num) +{ + uint32_t n = op_n(num); + UNUSED(n); + uint32_t i = op_i(n); + UNUSED(i); + uint32_t v = op_v(n); + UNUSED(v); + + if ((i == 1 && v == 0)) + return LV_I18N_PLURAL_TYPE_ONE; + return LV_I18N_PLURAL_TYPE_OTHER; +} + +static const lv_i18n_lang_t en_lang = {.locale_name = "en", + + .locale_plural_fn = en_plural_fn}; + +static lv_i18n_phrase_t de_singulars[] = { + {"User name: %s", "Benutzer: %s"}, + {"Device Role: %s", "Gerätemodus: %s"}, + {"no new messages", "keine neue Nachricht"}, + {"User name: ", "Benutzer: "}, + {"Modem Preset: LONG FAST", "Modem: LONG FAST"}, + {"Channel: LongFast", "Gruppen-Kanäle: LongFast"}, + {"Role: Client", "Gerätemodus: Client"}, + {"Screen Timeout: 60s", "Bild aus nach: 60s"}, + {"Screen Brightness: 60%", "Bildschirmhelligkeit: 60%"}, + {"Screen Calibration: default", "Kalibrierung: Standard"}, + {"Input Control: none/none", "Eingabe: ohne/ohne"}, + {"Message Alert Buzzer: on", "Akustischer Alarm: ein"}, + {"Language: English", "Sprache: Deutsch"}, + {"Configuration Reset", "Einstellungen zurücksetzen"}, + {"Reboot / Shutdown", "Neustart / Ausschalten"}, + {"Group Channels", "Gruppen Kanäle"}, + {"no messages", "Keine Nachrichten"}, + {"Settings", "Einstellungen"}, + {"Settings (advanced)", "Erweiterte Einstellungen"}, + {"Locations Map", "Karte"}, + {"no chats", "Keine Gespräche"}, + {"Node Options", "Optionen"}, + {"Short Name", "Kurzname"}, + {"Long Name", "Langname"}, + {"", ""}, + {"FrequencySlot: 1 (902.0MHz)", "Frequenz: 1 (902.0MHz)"}, + {"Brightness: 60%", "Helligkeit: 60%"}, + {"Timeout: 60s", "Bild aus nach: 60s"}, + {"Mouse", "Maus"}, + {"Keyboard", "Tastatur"}, + {"Message Alert", "Alarm"}, + {"NodeDB Reset\\nFactory Reset", "Einstellungen zurücksetzen"}, + {"Channel Name", "Kanalname"}, + {"Pre-shared Key", "Schlüssel"}, + {"New Message from\\n", "Neue Nachricht von\\n"}, + {"Resynch...", "Neu Synchronisieren..."}, + {"Screen Calibration: %s", "Kalibrierung: %s"}, + {"done", "erledigt"}, + {"default", "Standard"}, + {"Modem Preset: %s", "Voreinstellung: %s"}, + {"Channel: %s", "Guppen-Kanäle: %s"}, + {"Language: %s", "Sprache: %s"}, + {NULL, NULL} // End mark +}; + +static uint8_t de_plural_fn(int32_t num) +{ + uint32_t n = op_n(num); + UNUSED(n); + uint32_t i = op_i(n); + UNUSED(i); + uint32_t v = op_v(n); + UNUSED(v); + + if ((i == 1 && v == 0)) + return LV_I18N_PLURAL_TYPE_ONE; + return LV_I18N_PLURAL_TYPE_OTHER; +} + +static const lv_i18n_lang_t de_lang = {.locale_name = "de", + .singulars = de_singulars, + + .locale_plural_fn = de_plural_fn}; + +static uint8_t es_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 es_lang = {.locale_name = "es", + + .locale_plural_fn = es_plural_fn}; + +static uint8_t fr_plural_fn(int32_t num) +{ + uint32_t n = op_n(num); + UNUSED(n); + uint32_t i = op_i(n); + UNUSED(i); + + if ((((i == 0) || (i == 1)))) + return LV_I18N_PLURAL_TYPE_ONE; + return LV_I18N_PLURAL_TYPE_OTHER; +} + +static const lv_i18n_lang_t fr_lang = {.locale_name = "fr", + + .locale_plural_fn = fr_plural_fn}; + +static uint8_t it_plural_fn(int32_t num) +{ + uint32_t n = op_n(num); + UNUSED(n); + uint32_t i = op_i(n); + UNUSED(i); + uint32_t v = op_v(n); + UNUSED(v); + + if ((i == 1 && v == 0)) + return LV_I18N_PLURAL_TYPE_ONE; + return LV_I18N_PLURAL_TYPE_OTHER; +} + +static const lv_i18n_lang_t it_lang = {.locale_name = "it", + + .locale_plural_fn = it_plural_fn}; + +static uint8_t pl_plural_fn(int32_t num) +{ + uint32_t n = op_n(num); + UNUSED(n); + uint32_t i = op_i(n); + UNUSED(i); + uint32_t v = op_v(n); + UNUSED(v); + uint32_t i10 = i % 10; + uint32_t i100 = i % 100; + if ((i == 1 && v == 0)) + return LV_I18N_PLURAL_TYPE_ONE; + if ((v == 0 && (2 <= i10 && i10 <= 4) && (!(12 <= i100 && i100 <= 14)))) + return LV_I18N_PLURAL_TYPE_FEW; + if ((v == 0 && i != 1 && (0 <= i10 && i10 <= 1)) || (v == 0 && (5 <= i10 && i10 <= 9)) || + (v == 0 && (12 <= i100 && i100 <= 14))) + return LV_I18N_PLURAL_TYPE_MANY; + return LV_I18N_PLURAL_TYPE_OTHER; +} + +static const lv_i18n_lang_t pl_lang = {.locale_name = "pl", + + .locale_plural_fn = pl_plural_fn}; + +static uint8_t pt_plural_fn(int32_t num) +{ + uint32_t n = op_n(num); + UNUSED(n); + uint32_t i = op_i(n); + UNUSED(i); + + if (((0 <= i && i <= 1))) + return LV_I18N_PLURAL_TYPE_ONE; + return LV_I18N_PLURAL_TYPE_OTHER; +} + +static const lv_i18n_lang_t pt_lang = {.locale_name = "pt", + + .locale_plural_fn = pt_plural_fn}; + +static uint8_t ro_plural_fn(int32_t num) +{ + uint32_t n = op_n(num); + UNUSED(n); + uint32_t i = op_i(n); + UNUSED(i); + uint32_t v = op_v(n); + UNUSED(v); + uint32_t n100 = n % 100; + if ((i == 1 && v == 0)) + return LV_I18N_PLURAL_TYPE_ONE; + if ((v != 0) || (n == 0) || (n != 1 && (1 <= n100 && n100 <= 19))) + return LV_I18N_PLURAL_TYPE_FEW; + return LV_I18N_PLURAL_TYPE_OTHER; +} + +static const lv_i18n_lang_t ro_lang = {.locale_name = "ro", + + .locale_plural_fn = ro_plural_fn}; + +const lv_i18n_language_pack_t lv_i18n_language_pack[] = { + &en_lang, &de_lang, &es_lang, &fr_lang, &it_lang, &pl_lang, &pt_lang, &ro_lang, + NULL // End mark +}; + +//////////////////////////////////////////////////////////////////////////////// + +// Internal state +static const lv_i18n_language_pack_t *current_lang_pack; +static const lv_i18n_lang_t *current_lang; + +/** + * Reset internal state. For testing. + */ +void __lv_i18n_reset(void) +{ + current_lang_pack = NULL; + current_lang = NULL; +} + +/** + * Set the languages for internationalization + * @param langs pointer to the array of languages. (Last element has to be `NULL`) + */ +int lv_i18n_init(const lv_i18n_language_pack_t *langs) +{ + if (langs == NULL) + return -1; + if (langs[0] == NULL) + return -1; + + current_lang_pack = langs; + current_lang = langs[0]; /*Automatically select the first language*/ + return 0; +} + +/** + * Change the localization (language) + * @param l_name name of the translation locale to use. E.g. "en-GB" + */ +int lv_i18n_set_locale(const char *l_name) +{ + if (current_lang_pack == NULL) + return -1; + + uint16_t i; + + for (i = 0; current_lang_pack[i] != NULL; i++) { + // Found -> finish + if (strcmp(current_lang_pack[i]->locale_name, l_name) == 0) { + current_lang = current_lang_pack[i]; + return 0; + } + } + + return -1; +} + +static const char *__lv_i18n_get_text_core(lv_i18n_phrase_t *trans, const char *msg_id) +{ + uint16_t i; + for (i = 0; trans[i].msg_id != NULL; i++) { + if (strcmp(trans[i].msg_id, msg_id) == 0) { + /*The msg_id has found. Check the translation*/ + if (trans[i].translation) + return trans[i].translation; + } + } + + return NULL; +} + +/** + * Get the translation from a message ID + * @param msg_id message ID + * @return the translation of `msg_id` on the set local + */ +const char *lv_i18n_get_text(const char *msg_id) +{ + if (current_lang == NULL) + return msg_id; + + const lv_i18n_lang_t *lang = current_lang; + const void *txt; + + // Search in current locale + if (lang->singulars != NULL) { + txt = __lv_i18n_get_text_core(lang->singulars, msg_id); + if (txt != NULL) + return txt; + } + + // Try to fallback + if (lang == current_lang_pack[0]) + return msg_id; + lang = current_lang_pack[0]; + + // Repeat search for default locale + if (lang->singulars != NULL) { + txt = __lv_i18n_get_text_core(lang->singulars, msg_id); + if (txt != NULL) + return txt; + } + + return msg_id; +} + +/** + * Get the translation from a message ID and apply the language's plural rule to get correct form + * @param msg_id message ID + * @param num an integer to select the correct plural form + * @return the translation of `msg_id` on the set local + */ +const char *lv_i18n_get_text_plural(const char *msg_id, int32_t num) +{ + if (current_lang == NULL) + return msg_id; + + const lv_i18n_lang_t *lang = current_lang; + const void *txt; + lv_i18n_plural_type_t ptype; + + // Search in current locale + if (lang->locale_plural_fn != NULL) { + ptype = lang->locale_plural_fn(num); + + if (lang->plurals[ptype] != NULL) { + txt = __lv_i18n_get_text_core(lang->plurals[ptype], msg_id); + if (txt != NULL) + return txt; + } + } + + // Try to fallback + if (lang == current_lang_pack[0]) + return msg_id; + lang = current_lang_pack[0]; + + // Repeat search for default locale + if (lang->locale_plural_fn != NULL) { + ptype = lang->locale_plural_fn(num); + + if (lang->plurals[ptype] != NULL) { + txt = __lv_i18n_get_text_core(lang->plurals[ptype], msg_id); + if (txt != NULL) + return txt; + } + } + + return msg_id; +} + +/** + * Get the name of the currently used locale. + * @return name of the currently used locale. E.g. "en-GB" + */ +const char *lv_i18n_get_current_locale(void) +{ + if (!current_lang) + return NULL; + return current_lang->locale_name; +} diff --git a/locale/lv_i18n.h b/locale/lv_i18n.h new file mode 100644 index 0000000..8a4af09 --- /dev/null +++ b/locale/lv_i18n.h @@ -0,0 +1,80 @@ +#ifndef LV_I18N_H +#define LV_I18N_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +typedef enum { + LV_I18N_PLURAL_TYPE_ZERO, + LV_I18N_PLURAL_TYPE_ONE, + LV_I18N_PLURAL_TYPE_TWO, + LV_I18N_PLURAL_TYPE_FEW, + LV_I18N_PLURAL_TYPE_MANY, + LV_I18N_PLURAL_TYPE_OTHER, + _LV_I18N_PLURAL_TYPE_NUM, +} lv_i18n_plural_type_t; + +typedef struct { + const char *msg_id; + const char *translation; +} lv_i18n_phrase_t; + +typedef struct { + const char *locale_name; + lv_i18n_phrase_t *singulars; + lv_i18n_phrase_t *plurals[_LV_I18N_PLURAL_TYPE_NUM]; + uint8_t (*locale_plural_fn)(int32_t num); +} lv_i18n_lang_t; + +// Null-terminated list of languages. First one used as default. +typedef const lv_i18n_lang_t *lv_i18n_language_pack_t; + +extern const lv_i18n_language_pack_t lv_i18n_language_pack[]; + +/** + * Set the languages for internationalization + * @param langs pointer to the array of languages. (Last element has to be `NULL`) + */ +int lv_i18n_init(const lv_i18n_language_pack_t *langs); + +/** + * Change the localization (language) + * @param l_name name of the translation locale to use. E.g. "en_GB" + */ +int lv_i18n_set_locale(const char *l_name); + +/** + * Get the translation from a message ID + * @param msg_id message ID + * @return the translation of `msg_id` on the set local + */ +const char *lv_i18n_get_text(const char *msg_id); + +/** + * Get the translation from a message ID and apply the language's plural rule to get correct form + * @param msg_id message ID + * @param num an integer to select the correct plural form + * @return the translation of `msg_id` on the set local + */ +const char *lv_i18n_get_text_plural(const char *msg_id, int32_t num); + +/** + * Get the name of the currently used localization. + * @return name of the currently used localization. E.g. "en_GB" + */ +const char *lv_i18n_get_current_locale(void); + +void __lv_i18n_reset(void); + +#define _(text) lv_i18n_get_text(text) +#define _p(text, num) lv_i18n_get_text_plural(text, num) + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_LANG_H*/ diff --git a/locale/pl.yml b/locale/pl.yml new file mode 100644 index 0000000..008bdb6 --- /dev/null +++ b/locale/pl.yml @@ -0,0 +1,48 @@ +pl: + no new messages: ~ + 1 of 1 nodes online: ~ + DEL: ~ + "User name: ": ~ + "Modem Preset: LONG FAST": ~ + "Channel: LongFast": ~ + "Role: Client": ~ + "Screen Timeout: 60s": ~ + "Screen Brightness: 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: ~ + : ~ + LONG FAST\nLONG SLOW\nVERY LONG SLOW\nMEDIUM SLOW\nMEDIUM FAST\nSHORT SLOW\nSHORT FAST\nLONG MODERATE: ~ + "FrequencySlot: 1 (902.0MHz)": ~ + Client\nClient Mute\nRouter\nRouter Client\nRepeater\nTracker\nSensor\nTAK\nClient Hidden\nLost & Found\nTAK Tracker: ~ + "Brightness: 60%": ~ + "Timeout: 60s": ~ + Mouse: ~ + Keyboard: ~ + Message Alert: ~ + NodeDB Reset\nFactory Reset: ~ + Channel Name: ~ + Pre-shared Key: ~ + New Message from\n: ~ + Resynch...: ~ + "User name: %s": ~ + "Device Role: %s": ~ + "Screen Calibration: %s": ~ + done: ~ + default: ~ + "Region: %s": ~ + "Modem Preset: %s": ~ + "Channel: %s": ~ + "Language: %s": ~ diff --git a/locale/pt.yml b/locale/pt.yml new file mode 100644 index 0000000..ee44456 --- /dev/null +++ b/locale/pt.yml @@ -0,0 +1,48 @@ +pt: + no new messages: ~ + 1 of 1 nodes online: ~ + DEL: ~ + "User name: ": ~ + "Modem Preset: LONG FAST": ~ + "Channel: LongFast": ~ + "Role: Client": ~ + "Screen Timeout: 60s": ~ + "Screen Brightness: 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: ~ + : ~ + LONG FAST\nLONG SLOW\nVERY LONG SLOW\nMEDIUM SLOW\nMEDIUM FAST\nSHORT SLOW\nSHORT FAST\nLONG MODERATE: ~ + "FrequencySlot: 1 (902.0MHz)": ~ + Client\nClient Mute\nRouter\nRouter Client\nRepeater\nTracker\nSensor\nTAK\nClient Hidden\nLost & Found\nTAK Tracker: ~ + "Brightness: 60%": ~ + "Timeout: 60s": ~ + Mouse: ~ + Keyboard: ~ + Message Alert: ~ + NodeDB Reset\nFactory Reset: ~ + Channel Name: ~ + Pre-shared Key: ~ + New Message from\n: ~ + Resynch...: ~ + "User name: %s": ~ + "Device Role: %s": ~ + "Screen Calibration: %s": ~ + done: ~ + default: ~ + "Region: %s": ~ + "Modem Preset: %s": ~ + "Channel: %s": ~ + "Language: %s": ~ diff --git a/locale/ro.yml b/locale/ro.yml new file mode 100644 index 0000000..bde46d0 --- /dev/null +++ b/locale/ro.yml @@ -0,0 +1,48 @@ +ro: + no new messages: ~ + 1 of 1 nodes online: ~ + DEL: ~ + "User name: ": ~ + "Modem Preset: LONG FAST": ~ + "Channel: LongFast": ~ + "Role: Client": ~ + "Screen Timeout: 60s": ~ + "Screen Brightness: 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: ~ + : ~ + LONG FAST\nLONG SLOW\nVERY LONG SLOW\nMEDIUM SLOW\nMEDIUM FAST\nSHORT SLOW\nSHORT FAST\nLONG MODERATE: ~ + "FrequencySlot: 1 (902.0MHz)": ~ + Client\nClient Mute\nRouter\nRouter Client\nRepeater\nTracker\nSensor\nTAK\nClient Hidden\nLost & Found\nTAK Tracker: ~ + "Brightness: 60%": ~ + "Timeout: 60s": ~ + Mouse: ~ + Keyboard: ~ + Message Alert: ~ + NodeDB Reset\nFactory Reset: ~ + Channel Name: ~ + Pre-shared Key: ~ + New Message from\n: ~ + Resynch...: ~ + "User name: %s": ~ + "Device Role: %s": ~ + "Screen Calibration: %s": ~ + done: ~ + default: ~ + "Region: %s": ~ + "Modem Preset: %s": ~ + "Channel: %s": ~ + "Language: %s": ~ diff --git a/source/TFTView_320x240.cpp b/source/TFTView_320x240.cpp index eda1c3b..7eb8baa 100644 --- a/source/TFTView_320x240.cpp +++ b/source/TFTView_320x240.cpp @@ -9,6 +9,7 @@ #include "LoRaPresets.h" #include "ViewController.h" #include "images.h" +#include "lv_i18n.h" #include "ui.h" // this is the ui generated by eez-studio #include #include @@ -112,6 +113,10 @@ void TFTView_320x240::init(IClientBase *client) setInputGroup(); setInputButtonLabel(); + + // localization + lv_i18n_init(lv_i18n_language_pack); + lv_i18n_set_locale("en"); } /** @@ -917,7 +922,7 @@ void TFTView_320x240::ui_event_calibration_screen_loaded(lv_event_t *e) { bool done = THIS->displaydriver->calibrate(); char buf[32]; - lv_snprintf(buf, sizeof(buf), "Screen Calibration: %s", done ? "done" : "default"); + lv_snprintf(buf, sizeof(buf), _("Screen Calibration: %s"), done ? _("done") : _("default")); lv_label_set_text(objects.basic_settings_calibration_label, buf); lv_screen_load_anim(objects.main_screen, LV_SCR_LOAD_ANIM_FADE_ON, 200, 0, false); } @@ -936,7 +941,7 @@ void TFTView_320x240::ui_event_ok(lv_event_t *e) char buf[30]; const char *userShort = lv_textarea_get_text(objects.settings_user_short_textarea); const char *userLong = lv_textarea_get_text(objects.settings_user_long_textarea); - lv_snprintf(buf, sizeof(buf), "User name: %s", userShort); + lv_snprintf(buf, sizeof(buf), _("User name: %s"), userShort); lv_label_set_text(objects.basic_settings_user_label, buf); lv_label_set_text(objects.user_name_short_label, userShort); lv_label_set_text(objects.user_name_label, userLong); @@ -953,7 +958,7 @@ void TFTView_320x240::ui_event_ok(lv_event_t *e) case eDeviceRole: { char buf1[10], buf2[30]; lv_dropdown_get_selected_str(objects.settings_device_role_dropdown, buf1, sizeof(buf1)); - lv_snprintf(buf2, sizeof(buf2), "Device Role: %s", buf1); + lv_snprintf(buf2, sizeof(buf2), _("Device Role: %s"), buf1); lv_label_set_text(objects.basic_settings_role_label, buf2); meshtastic_Config_DeviceConfig &device = THIS->db.config.device; @@ -967,7 +972,7 @@ void TFTView_320x240::ui_event_ok(lv_event_t *e) case eRegion: { char buf1[10], buf2[30]; lv_dropdown_get_selected_str(objects.settings_region_dropdown, buf1, sizeof(buf1)); - lv_snprintf(buf2, sizeof(buf2), "Region: %s", buf1); + lv_snprintf(buf2, sizeof(buf2), _("Region: %s"), buf1); lv_label_set_text(objects.basic_settings_region_label, buf2); meshtastic_Config_LoRaConfig &lora = THIS->db.config.lora; @@ -983,7 +988,7 @@ void TFTView_320x240::ui_event_ok(lv_event_t *e) case eModemPreset: { char buf1[16], buf2[32]; lv_dropdown_get_selected_str(objects.settings_modem_preset_dropdown, buf1, sizeof(buf1)); - lv_snprintf(buf2, sizeof(buf2), "Modem Preset: %s", buf1); + lv_snprintf(buf2, sizeof(buf2), _("Modem Preset: %s"), buf1); lv_label_set_text(objects.basic_settings_modem_preset_label, buf2); meshtastic_Config_LoRaConfig &lora = THIS->db.config.lora; @@ -1009,7 +1014,7 @@ void TFTView_320x240::ui_event_ok(lv_event_t *e) int8_t ch = (signed long)THIS->ch_label[0]->user_data; char buf[32]; - lv_snprintf(buf, sizeof(buf), "Channel: %s", THIS->db.channel[ch].settings.name); + lv_snprintf(buf, sizeof(buf), _("Channel: %s"), THIS->db.channel[ch].settings.name); lv_label_set_text(objects.basic_settings_channel_label, buf); lv_obj_clear_state(objects.settings_channel_panel, LV_STATE_DISABLED); @@ -1020,9 +1025,21 @@ void TFTView_320x240::ui_event_ok(lv_event_t *e) case eLanguage: { char buf1[10], buf2[30]; lv_dropdown_get_selected_str(objects.settings_language_dropdown, buf1, sizeof(buf1)); - lv_snprintf(buf2, sizeof(buf2), "Language: %s", buf1); + lv_snprintf(buf2, sizeof(buf2), _("Language: %s"), buf1); lv_label_set_text(objects.basic_settings_language_label, buf2); // TODO: change language acc. lvgl localization + switch (lv_dropdown_get_selected(objects.settings_language_dropdown)) { + case 0: + lv_i18n_set_locale("en"); + break; + case 1: + lv_i18n_set_locale("de"); + break; + default: + ILOG_WARN("Language %s not implemented\n", buf1); + break; + } + lv_obj_add_flag(objects.settings_language_panel, LV_OBJ_FLAG_HIDDEN); break; } @@ -1624,9 +1641,9 @@ void TFTView_320x240::updateNode(uint32_t nodeNum, uint8_t ch, const char *userS if (it->first == ownNode) { // update related settings buttons and store role in image user data char buf[30]; - lv_snprintf(buf, sizeof(buf), "Username: %s", userShort); + lv_snprintf(buf, sizeof(buf), _("User name: %s"), userShort); lv_label_set_text(objects.basic_settings_user_label, buf); - lv_snprintf(buf, sizeof(buf), "Device Role: %s", deviceRoleToString(role)); + lv_snprintf(buf, sizeof(buf), _("Device Role: %s"), deviceRoleToString(role)); lv_label_set_text(objects.basic_settings_role_label, buf); it->second->LV_OBJ_IDX(node_img_idx)->user_data = (void *)role; // TODO: not used -> remove?