From 511b8091ebc60586efef0e3d07205f6b5bc49345 Mon Sep 17 00:00:00 2001 From: longpanda Date: Fri, 2 Dec 2022 20:35:59 +0800 Subject: [PATCH] Add muli-languages support for Ventoy menu. F5 ---> Menu Language Select Language files are in INSTALL/grub/menu/ directory. --- .../grub-2.04/grub-core/commands/menuentry.c | 18 +++- .../grub-2.04/grub-core/gfxmenu/gui_label.c | 6 +- .../MOD_SRC/grub-2.04/grub-core/normal/menu.c | 9 +- .../grub-2.04/grub-core/normal/menu_text.c | 4 +- .../grub-core/ventoy/ventoy_browser.c | 10 +- .../grub-2.04/grub-core/ventoy/ventoy_cmd.c | 47 ++++++--- .../grub-2.04/grub-core/ventoy/ventoy_def.h | 7 ++ .../grub-core/ventoy/ventoy_plugin.c | 92 +++++++++++++++++- INSTALL/grub/checksum.cfg | 18 ++-- INSTALL/grub/debug.cfg | 66 ++++++------- INSTALL/grub/grub.cfg | 14 ++- INSTALL/grub/hwinfo.cfg | 2 +- INSTALL/grub/keyboard.cfg | 2 +- INSTALL/grub/localboot.cfg | 24 ++--- INSTALL/grub/menu/en_US.json | 81 +++++++++++++++ INSTALL/grub/menu/zh_CN.json | 81 +++++++++++++++ INSTALL/grub/menulang.cfg | 3 + INSTALL/grub/power.cfg | 10 +- INSTALL/ventoy_pack.sh | 20 ++++ LANGUAGES/check.sh | 15 ++- Plugson/pack.sh | 4 + Plugson/src/Web/ventoy_http.c | 50 +++++++++- Plugson/src/Web/ventoy_http.h | 3 +- .../VentoyPlugson/Release/VentoyPlugson.exe | Bin 370176 -> 371200 bytes Plugson/www/menulist | 1 + Plugson/www/plugson_control.html | 50 +++++++++- 26 files changed, 537 insertions(+), 100 deletions(-) create mode 100644 INSTALL/grub/menu/en_US.json create mode 100644 INSTALL/grub/menu/zh_CN.json create mode 100644 INSTALL/grub/menulang.cfg create mode 100644 Plugson/www/menulist diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/menuentry.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/menuentry.c index 9faf2be0..cb74cd92 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/menuentry.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/menuentry.c @@ -25,6 +25,10 @@ #include #include +typedef const char * (*get_vmenu_title_pf)(const char *vMenu); +static get_vmenu_title_pf g_pfvmenu_title = NULL; + + static const struct grub_arg_option options[] = { {"class", 1, GRUB_ARG_OPTION_REPEATABLE, @@ -86,6 +90,8 @@ grub_normal_add_menu_entry (int argc, const char **args, char *menu_title = NULL; char *menu_sourcecode = NULL; char *menu_id = NULL; + const char *vmenu = NULL; + const char *vaddr = NULL; struct grub_menu_entry_class *menu_classes = NULL; grub_menu_t menu; @@ -145,7 +151,17 @@ grub_normal_add_menu_entry (int argc, const char **args, goto fail; } - menu_title = grub_strdup (args[0]); + if (!g_pfvmenu_title) { + vaddr = grub_env_get("VTOY_VMENU_FUNC_ADDR"); + if (vaddr) + g_pfvmenu_title = (get_vmenu_title_pf)(unsigned long)grub_strtoul(vaddr, NULL, 16); + } + + if (g_pfvmenu_title && grub_strncmp(args[0], "@VTMENU_", 8) == 0) + vmenu = g_pfvmenu_title(args[0] + 1); + + menu_title = grub_strdup (vmenu ? vmenu : args[0]); + if (! menu_title) goto fail; diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/gui_label.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/gui_label.c index 63d8c7be..008cfd5a 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/gui_label.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/gui_label.c @@ -31,6 +31,7 @@ extern int g_ventoy_iso_raw; extern int g_ventoy_grub2_mode; extern int g_ventoy_wimboot_mode; extern int g_ventoy_iso_uefi_drv; +extern char g_ventoy_hotkey_tip[256]; static const char *align_options[] = { @@ -230,10 +231,7 @@ label_set_property (void *vself, const char *name, const char *value) value = g_ventoy_iso_uefi_drv ? grub_env_get("VTOY_ISO_UEFI_DRV_STR") : " "; } else if (grub_strcmp (value, "@VTOY_HOTKEY_TIP@") == 0) { - value = grub_env_get("VTOY_HOTKEY_TIP"); - if (value == NULL) { - value = _(" "); - } + value = g_ventoy_hotkey_tip; } self->template = grub_strdup (value); diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu.c index aa23be3b..ddd79484 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu.c @@ -50,6 +50,8 @@ int g_ventoy_menu_esc = 0; int g_ventoy_fn_mutex = 0; int g_ventoy_secondary_menu_on = 0; int g_ventoy_terminal_output = 0; +char g_ventoy_hotkey_tip[256]; +int g_ventoy_virt_esc = 0; #define VTOY_COMM_HOTKEY(cmdkey) \ if (0 == g_ventoy_fn_mutex && 0 == g_ventoy_secondary_menu_on) { \ @@ -796,7 +798,12 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) return default_entry; } - c = grub_getkey_noblock (); + if (g_ventoy_virt_esc > 0) { + c = GRUB_TERM_ESC; + g_ventoy_virt_esc--; + } else { + c = grub_getkey_noblock (); + } /* Negative values are returned on error. */ if ((c != GRUB_TERM_NO_KEY) && (c > 0)) diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu_text.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu_text.c index 24aa094d..549d9029 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu_text.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu_text.c @@ -31,6 +31,8 @@ static grub_uint8_t grub_color_menu_normal; static grub_uint8_t grub_color_menu_highlight; +extern char g_ventoy_hotkey_tip[256]; + struct menu_viewer_data { int first, offset; @@ -204,7 +206,7 @@ command-line or ESC to discard edits and return to the GRUB menu."), ret += grub_print_message_indented_real(szLine, STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run); ret += grub_print_message_indented_real("\n", STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run); - ret += grub_print_message_indented_real(grub_env_get("VTOY_HOTKEY_TIP"), + ret += grub_print_message_indented_real(g_ventoy_hotkey_tip, 3, 6, term, dry_run); } } diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_browser.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_browser.c index 785e4978..768faf0e 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_browser.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_browser.c @@ -616,13 +616,15 @@ grub_err_t ventoy_cmd_browser_disk(grub_extcmd_context_t ctxt, int argc, char ** if (g_tree_view_menu_style == 0) { - browser_ssprintf(&mbuf, "menuentry \"%-10s [Return]\" --class=\"vtoyret\" VTOY_RET {\n " - " echo 'return ...' \n}\n", "<--"); + browser_ssprintf(&mbuf, "menuentry \"%-10s [%s]\" --class=\"vtoyret\" VTOY_RET {\n " + " echo 'return ...' \n}\n", "<--", + ventoy_get_vmenu_title("VTMENU_BROWER_RETURN")); } else { - browser_ssprintf(&mbuf, "menuentry \"[Return]\" --class=\"vtoyret\" VTOY_RET {\n " - " echo 'return ...' \n}\n"); + browser_ssprintf(&mbuf, "menuentry \"[%s]\" --class=\"vtoyret\" VTOY_RET {\n " + " echo 'return ...' \n}\n", + ventoy_get_vmenu_title("VTMENU_BROWER_RETURN")); } grub_disk_dev_iterate(ventoy_browser_iterate_disk, &mbuf); diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c index 73e98215..4fbfe7f7 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c @@ -2346,16 +2346,16 @@ static int ventoy_dynamic_tree_menu(img_iterator_node *node) if (g_tree_view_menu_style == 0) { vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, - "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n " + "menuentry \"%-10s [%s]\" --class=\"vtoyret\" VTOY_RET {\n " " echo 'return ...' \n" - "}\n", "<--"); + "}\n", "<--", ventoy_get_vmenu_title("VTMENU_RET_TO_LISTVIEW")); } else { vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, - "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n " + "menuentry \"[%s]\" --class=\"vtoyret\" VTOY_RET {\n " " echo 'return ...' \n" - "}\n"); + "}\n", ventoy_get_vmenu_title("VTMENU_RET_TO_LISTVIEW")); } } @@ -2934,9 +2934,9 @@ static grub_err_t ventoy_cmd_list_img(grub_extcmd_context_t ctxt, int argc, char if (g_default_menu_mode == 1) { vtoy_ssprintf(g_list_script_buf, g_list_script_pos, - "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n " + "menuentry \"%s [%s]\" --class=\"vtoyret\" VTOY_RET {\n " " echo 'return ...' \n" - "}\n", "<--"); + "}\n", "<--", ventoy_get_vmenu_title("VTMENU_RET_TO_TREEVIEW")); } for (cur = g_ventoy_img_list; cur; cur = cur->next) @@ -3705,13 +3705,14 @@ static grub_err_t ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt, int ar vtoy_ssprintf(buf, pos, "set timeout=%d\n", node->timeout); } - vtoy_ssprintf(buf, pos, "menuentry \"Boot without auto installation template\" --class=\"sel_auto_install\" {\n" + vtoy_ssprintf(buf, pos, "menuentry \"@VTMENU_NO_AUTOINS_SCRIPT\" --class=\"sel_auto_install\" {\n" " echo %s\n}\n", ""); for (i = 0; i < node->templatenum; i++) { - vtoy_ssprintf(buf, pos, "menuentry \"Boot with %s\" --class=\"sel_auto_install\" {\n" + vtoy_ssprintf(buf, pos, "menuentry \"%s %s\" --class=\"sel_auto_install\" {\n" " echo \"\"\n}\n", + ventoy_get_vmenu_title("VTMENU_AUTOINS_USE"), node->templatepath[i].path); } @@ -3811,13 +3812,14 @@ static grub_err_t ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt, int arg vtoy_ssprintf(buf, pos, "set timeout=%d\n", node->timeout); } - vtoy_ssprintf(buf, pos, "menuentry \"Boot without persistence\" --class=\"sel_persistence\" {\n" + vtoy_ssprintf(buf, pos, "menuentry \"@VTMENU_NO_PERSISTENCE\" --class=\"sel_persistence\" {\n" " echo %s\n}\n", ""); for (i = 0; i < node->backendnum; i++) { - vtoy_ssprintf(buf, pos, "menuentry \"Boot with %s\" --class=\"sel_persistence\" {\n" + vtoy_ssprintf(buf, pos, "menuentry \"%s %s\" --class=\"sel_persistence\" {\n" " echo \"\"\n}\n", + ventoy_get_vmenu_title("VTMENU_PERSIST_USE"), node->backendpath[i].path); } @@ -6073,26 +6075,26 @@ static grub_err_t ventoy_cmd_show_secondary_menu(grub_extcmd_context_t ctxt, int fsize = grub_strtoull(args[2], NULL, 10); - vtoy_dummy_menuentry(cmd, pos, len, "Boot in normal mode", "second_normal"); seldata[n++] = 1; + vtoy_dummy_menuentry(cmd, pos, len, "@VTMENU_NORMAL_MODE", "second_normal"); seldata[n++] = 1; if (grub_strcmp(args[1], "Unix") != 0) { if (grub_strcmp(args[1], "Windows") == 0) { - vtoy_dummy_menuentry(cmd, pos, len, "Boot in wimboot mode", "second_wimboot"); seldata[n++] = 2; + vtoy_dummy_menuentry(cmd, pos, len, "@VTMENU_WIMBOOT_MODE", "second_wimboot"); seldata[n++] = 2; } else { - vtoy_dummy_menuentry(cmd, pos, len, "Boot in grub2 mode", "second_grub2"); seldata[n++] = 3; + vtoy_dummy_menuentry(cmd, pos, len, "@VTMENU_GRUB2_MODE", "second_grub2"); seldata[n++] = 3; } if (fsize <= VTOY_SIZE_1GB) { - vtoy_dummy_menuentry(cmd, pos, len, "Boot in memdisk mode", "second_memdisk"); seldata[n++] = 4; + vtoy_dummy_menuentry(cmd, pos, len, "@VTMENU_MEMDISK_MODE", "second_memdisk"); seldata[n++] = 4; } } - vtoy_dummy_menuentry(cmd, pos, len, "File checksum", "second_checksum"); seldata[n++] = 5; + vtoy_dummy_menuentry(cmd, pos, len, "@VTMENU_FILE_CHKSUM", "second_checksum"); seldata[n++] = 5; do { g_ventoy_menu_esc = 1; @@ -6175,6 +6177,15 @@ static grub_err_t ventoy_cmd_fs_ignore_case(grub_extcmd_context_t ctxt, int argc return 0; } +static grub_err_t ventoy_cmd_load_menu_lang(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + + ventoy_plugin_load_menu_lang(args[0]); + VENTOY_CMD_RETURN(0); +} + int ventoy_env_init(void) { int i; @@ -6216,6 +6227,10 @@ int ventoy_env_init(void) grub_snprintf(buf, sizeof(buf), "0x%lx", (ulong)ventoy_chain_file_read); grub_env_set("vtoy_chain_file_read", buf); grub_env_export("vtoy_chain_file_read"); + + grub_snprintf(buf, sizeof(buf), "0x%lx", (ulong)ventoy_get_vmenu_title); + grub_env_set("VTOY_VMENU_FUNC_ADDR", buf); + grub_env_export("VTOY_VMENU_FUNC_ADDR"); return 0; } @@ -6383,6 +6398,8 @@ static cmd_para ventoy_cmds[] = { "vt_systemd_menu", ventoy_cmd_linux_systemd_menu, 0, NULL, "", "", NULL }, { "vt_limine_menu", ventoy_cmd_linux_limine_menu, 0, NULL, "", "", NULL }, { "vt_secondary_recover_mode", ventoy_cmd_secondary_recover_mode, 0, NULL, "", "", NULL }, + { "vt_load_menu_lang", ventoy_cmd_load_menu_lang, 0, NULL, "", "", NULL }, + { "vt_cur_menu_lang", ventoy_cmd_cur_menu_lang, 0, NULL, "", "", NULL }, }; int ventoy_register_all_cmd(void) diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h index 89119ac8..75d98da3 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h @@ -1053,6 +1053,10 @@ extern int g_ventoy_case_insensitive; extern int g_ventoy_fn_mutex; extern grub_uint8_t g_ventoy_chain_type; extern int g_vhdboot_enable; +extern int g_default_menu_mode; +extern char g_ventoy_hotkey_tip[256]; +extern int g_ventoy_menu_refresh; +extern int g_ventoy_virt_esc; #define VENTOY_IMG_WHITE_LIST 1 #define VENTOY_IMG_BLACK_LIST 2 @@ -1258,6 +1262,9 @@ grub_err_t ventoy_cmd_browser_disk(grub_extcmd_context_t ctxt, int argc, char ** int ventoy_get_fs_type(const char *fs); int ventoy_img_name_valid(const char *filename, grub_size_t namelen); void * ventoy_alloc_chain(grub_size_t size); +int ventoy_plugin_load_menu_lang(const char *lang); +const char *ventoy_get_vmenu_title(const char *vMenu); +grub_err_t ventoy_cmd_cur_menu_lang(grub_extcmd_context_t ctxt, int argc, char **args); #endif /* __VENTOY_DEF_H__ */ diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c index b0dd1d52..aad1cbfa 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c @@ -56,12 +56,14 @@ static injection_config *g_injection_head = NULL; static auto_memdisk *g_auto_memdisk_head = NULL; static image_list *g_image_list_head = NULL; static conf_replace *g_conf_replace_head = NULL; +static VTOY_JSON *g_menu_lang_json = NULL; static int g_theme_id = 0; static int g_theme_num = 0; static theme_list *g_theme_head = NULL; static int g_theme_random = vtoy_theme_random_boot_second; static char g_theme_single_file[256]; +static char g_cur_menu_language[32] = {0}; static int ventoy_plugin_is_parent(const char *pat, int patlen, const char *isopath) { @@ -2446,6 +2448,7 @@ grub_err_t ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **a int ret = 0; int offset = 0; char *buf = NULL; + const char *env = NULL; grub_uint8_t *code = NULL; grub_file_t file; VTOY_JSON *json = NULL; @@ -2539,6 +2542,9 @@ grub_err_t ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **a grub_env_unset("VTOY_MENU_TIP_ENABLE"); } + env = grub_env_get("VTOY_MENU_LANGUAGE"); + ventoy_plugin_load_menu_lang(env ? env : "en_US"); + VENTOY_CMD_RETURN(GRUB_ERR_NONE); } @@ -3369,7 +3375,7 @@ grub_err_t ventoy_cmd_select_theme_cfg(grub_extcmd_context_t ctxt, int argc, cha } pos += grub_snprintf(buf + pos, bufsize - pos, - "menuentry 'Return to previous menu [Esc]' --class=vtoyret VTOY_RET {\n" + "menuentry '@VTMENU_RETURN_PREVIOUS' --class=vtoyret VTOY_RET {\n" "echo 'Return ...'\n" "}\n"); @@ -3467,3 +3473,87 @@ grub_err_t ventoy_cmd_set_theme_path(grub_extcmd_context_t ctxt, int argc, char VENTOY_CMD_RETURN(GRUB_ERR_NONE); } +const char *ventoy_get_vmenu_title(const char *vMenu) +{ + return vtoy_json_get_string_ex(g_menu_lang_json->pstChild, vMenu); +} + +int ventoy_plugin_load_menu_lang(const char *lang) +{ + int ret = 1; + grub_file_t file = NULL; + char *buf = NULL; + + if (grub_strcmp(lang, g_cur_menu_language) == 0) + { + debug("Same menu lang %s\n", lang); + return 0; + } + grub_snprintf(g_cur_menu_language, sizeof(g_cur_menu_language), "%s", lang); + + debug("Load menu lang %s\n", g_cur_menu_language); + + if (g_menu_lang_json) + { + vtoy_json_destroy(g_menu_lang_json); + g_menu_lang_json = NULL; + } + + g_menu_lang_json = vtoy_json_create(); + if (!g_menu_lang_json) + { + goto end; + } + + file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "(vt_menu_tarfs)/menu/%s.json", lang); + if (!file) + { + goto end; + } + + buf = grub_malloc(file->size + 1); + if (!buf) + { + grub_printf("Failed to malloc memory %lu.\n", (ulong)(file->size + 1)); + goto end; + } + + buf[file->size] = 0; + grub_file_read(file, buf, file->size); + + vtoy_json_parse(g_menu_lang_json, buf); + + if (g_default_menu_mode == 0) + { + grub_snprintf(g_ventoy_hotkey_tip, sizeof(g_ventoy_hotkey_tip), "%s", ventoy_get_vmenu_title("VTMENU_STR_HOTKEY_TREE")); + } + else + { + grub_snprintf(g_ventoy_hotkey_tip, sizeof(g_ventoy_hotkey_tip), "%s", ventoy_get_vmenu_title("VTMENU_STR_HOTKEY_LIST")); + } + + g_ventoy_virt_esc = 2; + g_ventoy_menu_refresh = 1; + ret = 0; + +end: + + check_free(file, grub_file_close); + grub_check_free(buf); + + return ret; +} + +grub_err_t ventoy_cmd_cur_menu_lang(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + (void)args; + + grub_printf("%s\n", g_cur_menu_language); + grub_printf("%s\n", g_ventoy_hotkey_tip); + grub_refresh(); + + VENTOY_CMD_RETURN(0); +} + diff --git a/INSTALL/grub/checksum.cfg b/INSTALL/grub/checksum.cfg index 21dd0de0..b57de6ef 100644 --- a/INSTALL/grub/checksum.cfg +++ b/INSTALL/grub/checksum.cfg @@ -1,7 +1,7 @@ if [ -e "${vtoy_iso_part}${VTOY_CHKSUM_FILE_PATH}.md5" ]; then set default=0 - menuentry "Calculate and check md5sum" --class=checksum_md5 { + menuentry "@VTMENU_CHKSUM_MD5_CALC_CHK" --class=checksum_md5 { md5sum "${vtoy_iso_part}${VTOY_CHKSUM_FILE_PATH}" vt_1st_line "${vtoy_iso_part}${VTOY_CHKSUM_FILE_PATH}.md5" vtReadChecksum @@ -18,7 +18,7 @@ if [ -e "${vtoy_iso_part}${VTOY_CHKSUM_FILE_PATH}.md5" ]; then read vtInputKey } else - menuentry "Calculate md5sum" --class=checksum_md5 { + menuentry "@VTMENU_CHKSUM_MD5_CALC" --class=checksum_md5 { md5sum "${vtoy_iso_part}${VTOY_CHKSUM_FILE_PATH}" echo -e "\n\npress ENTER to exit ..." @@ -28,7 +28,7 @@ fi if [ -e "${vtoy_iso_part}${VTOY_CHKSUM_FILE_PATH}.sha1" ]; then set default=1 - menuentry "Calculate and check sha1sum" --class=checksum_sha1 { + menuentry "@VTMENU_CHKSUM_SHA1_CALC_CHK" --class=checksum_sha1 { sha1sum "${vtoy_iso_part}${VTOY_CHKSUM_FILE_PATH}" vt_1st_line "${vtoy_iso_part}${VTOY_CHKSUM_FILE_PATH}.sha1" vtReadChecksum @@ -45,7 +45,7 @@ if [ -e "${vtoy_iso_part}${VTOY_CHKSUM_FILE_PATH}.sha1" ]; then read vtInputKey } else - menuentry "Calculate sha1sum" --class=checksum_sha1 { + menuentry "@VTMENU_CHKSUM_SHA1_CALC" --class=checksum_sha1 { sha1sum "${vtoy_iso_part}${VTOY_CHKSUM_FILE_PATH}" echo -e "\n\npress ENTER to exit ..." @@ -57,7 +57,7 @@ fi if [ -e "${vtoy_iso_part}${VTOY_CHKSUM_FILE_PATH}.sha256" ]; then set default=2 - menuentry "Calculate and check sha256sum" --class=checksum_sha256 { + menuentry "@VTMENU_CHKSUM_SHA256_CALC_CHK" --class=checksum_sha256 { sha256sum "${vtoy_iso_part}${VTOY_CHKSUM_FILE_PATH}" vt_1st_line "${vtoy_iso_part}${VTOY_CHKSUM_FILE_PATH}.sha256" vtReadChecksum @@ -74,7 +74,7 @@ if [ -e "${vtoy_iso_part}${VTOY_CHKSUM_FILE_PATH}.sha256" ]; then read vtInputKey } else - menuentry "Calculate sha256sum" --class=checksum_sha256 { + menuentry "@VTMENU_CHKSUM_SHA256_CALC" --class=checksum_sha256 { sha256sum "${vtoy_iso_part}${VTOY_CHKSUM_FILE_PATH}" echo -e "\n\npress ENTER to exit ..." @@ -86,7 +86,7 @@ fi if [ -e "${vtoy_iso_part}${VTOY_CHKSUM_FILE_PATH}.sha512" ]; then set default=3 - menuentry "Calculate and check sha512sum" --class=checksum_sha512{ + menuentry "@VTMENU_CHKSUM_SHA512_CALC_CHK" --class=checksum_sha512{ sha512sum "${vtoy_iso_part}${VTOY_CHKSUM_FILE_PATH}" vt_1st_line "${vtoy_iso_part}${VTOY_CHKSUM_FILE_PATH}.sha512" vtReadChecksum @@ -103,7 +103,7 @@ if [ -e "${vtoy_iso_part}${VTOY_CHKSUM_FILE_PATH}.sha512" ]; then read vtInputKey } else - menuentry "Calculate sha512sum" --class=checksum_sha512{ + menuentry "@VTMENU_CHKSUM_SHA512_CALC" --class=checksum_sha512{ sha512sum "${vtoy_iso_part}${VTOY_CHKSUM_FILE_PATH}" echo -e "\n\npress ENTER to exit ..." @@ -112,6 +112,6 @@ else fi -menuentry 'Return to previous menu [Esc]' --class=vtoyret VTOY_RET { +menuentry '@VTMENU_RETURN_PREVIOUS' --class=vtoyret VTOY_RET { echo 'Return ...' } diff --git a/INSTALL/grub/debug.cfg b/INSTALL/grub/debug.cfg index 31525238..12db218e 100644 --- a/INSTALL/grub/debug.cfg +++ b/INSTALL/grub/debug.cfg @@ -1,10 +1,11 @@ +source $prefix/menulang.cfg source $prefix/power.cfg source $prefix/hwinfo.cfg source $prefix/keyboard.cfg -submenu "Resolution Configuration" --class=debug_resolution --class=F5tool { - menuentry 'Return to previous menu [Esc]' --class=vtoyret VTOY_RET { +submenu "@VTMENU_RESOLUTION_CFG" --class=debug_resolution --class=F5tool { + menuentry '@VTMENU_RETURN_PREVIOUS' --class=vtoyret VTOY_RET { echo 'Return ...' } @@ -28,27 +29,27 @@ submenu "Resolution Configuration" --class=debug_resolution --class=F5tool { done } -submenu "Screen Display Mode" --class=debug_screen_mode --class=F5tool { - menuentry 'Force Text Mode' --class=debug_text_mode --class=debug_screen_mode --class=F5tool { +submenu "@VTMENU_SCREEN_MODE" --class=debug_screen_mode --class=F5tool { + menuentry '@VTMENU_SCREEN_TEXT_MODE' --class=debug_text_mode --class=debug_screen_mode --class=F5tool { terminal_output console } - menuentry 'Force Graphics Mode' --class=debug_gui_mode --class=debug_screen_mode --class=F5tool { + menuentry '@VTMENU_SCREEN_GUI_MODE' --class=debug_gui_mode --class=debug_screen_mode --class=F5tool { terminal_output gfxterm } - menuentry 'Return to previous menu [Esc]' --class=vtoyret VTOY_RET { + menuentry '@VTMENU_RETURN_PREVIOUS' --class=vtoyret VTOY_RET { echo 'Return ...' } } -if [ $VTOY_THEME_COUNT -gt 1 ]; then - submenu "Theme Select" --class=debug_theme_select --class=F5tool { +if [ -n "$VTOY_THEME_COUNT" -a $VTOY_THEME_COUNT -gt 1 ]; then + submenu "@VTMENU_THEME_SELECT" --class=debug_theme_select --class=F5tool { vt_select_theme_cfg } fi if [ "$grub_platform" != "pc" ]; then submenu 'Ventoy UEFI Utilities' --class=debug_util --class=F5tool { - menuentry 'Show EFI Drivers' --class=debug_util_efidrv --class=debug_util --class=F5tool { + menuentry '@VTMENU_UTIL_SHOW_EFI_DRV' --class=debug_util_efidrv --class=debug_util --class=F5tool { vt_push_pager chainloader ${vtoy_path}/vtoyutil_${VTOY_EFI_ARCH}.efi env_param=${env_param} ${vtdebug_flag} feature=show_efi_drivers boot @@ -57,22 +58,22 @@ if [ "$grub_platform" != "pc" ]; then read vtInputKey } - menuentry 'Fixup Windows BlinitializeLibrary Failure' --class=debug_util_blinit --class=debug_util --class=F5tool { + menuentry '@VTMENU_UTIL_FIX_BLINIT_FAIL' --class=debug_util_blinit --class=debug_util --class=F5tool { chainloader ${vtoy_path}/vtoyutil_${VTOY_EFI_ARCH}.efi env_param=${env_param} ${vtdebug_flag} feature=fix_windows_mmap boot echo -e "\npress ENTER to exit ..." read vtInputKey } - menuentry 'Return to previous menu [Esc]' --class=vtoyret VTOY_RET { + menuentry '@VTMENU_RETURN_PREVIOUS' --class=vtoyret VTOY_RET { echo 'Return ...' } } fi -submenu 'Check plugin json configuration (ventoy.json)' --class=debug_json --class=F5tool { - menuentry 'Check global control plugin configuration' --class=debug_control --class=debug_json --class=F5tool { +submenu '@VTMENU_JSON_CHK_JSON' --class=debug_json --class=F5tool { + menuentry '@VTMENU_JSON_CHK_CONTROL' --class=debug_control --class=debug_json --class=F5tool { set pager=1 vt_check_plugin_json $vt_plugin_path control $vtoy_iso_part @@ -81,7 +82,7 @@ submenu 'Check plugin json configuration (ventoy.json)' --class=debug_json --cla unset pager } - menuentry 'Check theme plugin configuration' --class=debug_theme --class=debug_json --class=F5tool { + menuentry '@VTMENU_JSON_CHK_THEME' --class=debug_theme --class=debug_json --class=F5tool { set pager=1 vt_check_plugin_json $vt_plugin_path theme $vtoy_iso_part @@ -90,7 +91,7 @@ submenu 'Check plugin json configuration (ventoy.json)' --class=debug_json --cla unset pager } - menuentry 'Check auto install plugin configuration' --class=debug_autoinstall --class=debug_json --class=F5tool { + menuentry '@VTMENU_JSON_CHK_AUTOINS' --class=debug_autoinstall --class=debug_json --class=F5tool { set pager=1 vt_check_plugin_json $vt_plugin_path auto_install $vtoy_iso_part @@ -99,7 +100,7 @@ submenu 'Check plugin json configuration (ventoy.json)' --class=debug_json --cla unset pager } - menuentry 'Check persistence plugin configuration' --class=debug_persistence --class=debug_json --class=F5tool { + menuentry '@VTMENU_JSON_CHK_PERSIST' --class=debug_persistence --class=debug_json --class=F5tool { set pager=1 vt_check_plugin_json $vt_plugin_path persistence $vtoy_iso_part @@ -111,7 +112,7 @@ submenu 'Check plugin json configuration (ventoy.json)' --class=debug_json --cla unset pager } - menuentry 'Check menu alias plugin configuration' --class=debug_menualias --class=debug_json --class=F5tool { + menuentry '@VTMENU_JSON_CHK_MENU_ALIAS' --class=debug_menualias --class=debug_json --class=F5tool { set pager=1 vt_check_plugin_json $vt_plugin_path menu_alias $vtoy_iso_part @@ -120,7 +121,7 @@ submenu 'Check plugin json configuration (ventoy.json)' --class=debug_json --cla unset pager } - menuentry 'Check menu tip plugin configuration' --class=debug_menutip --class=debug_json --class=F5tool { + menuentry '@VTMENU_JSON_CHK_MENU_TIP' --class=debug_menutip --class=debug_json --class=F5tool { set pager=1 vt_check_plugin_json $vt_plugin_path menu_tip $vtoy_iso_part @@ -129,7 +130,7 @@ submenu 'Check plugin json configuration (ventoy.json)' --class=debug_json --cla unset pager } - menuentry 'Check menu class plugin configuration' --class=debug_menuclass --class=debug_json --class=F5tool { + menuentry '@VTMENU_JSON_CHK_MENU_CLASS' --class=debug_menuclass --class=debug_json --class=F5tool { set pager=1 vt_check_plugin_json $vt_plugin_path menu_class $vtoy_iso_part @@ -138,7 +139,7 @@ submenu 'Check plugin json configuration (ventoy.json)' --class=debug_json --cla unset pager } - menuentry 'Check injection plugin configuration' --class=debug_injection --class=debug_json --class=F5tool { + menuentry '@VTMENU_JSON_CHK_INJECTION' --class=debug_injection --class=debug_json --class=F5tool { set pager=1 vt_check_plugin_json $vt_plugin_path injection $vtoy_iso_part @@ -147,7 +148,7 @@ submenu 'Check plugin json configuration (ventoy.json)' --class=debug_json --cla unset pager } - menuentry 'Check auto memdisk plugin configuration' --class=debug_automemdisk --class=debug_json --class=F5tool { + menuentry '@VTMENU_JSON_CHK_AUTO_MEMDISK' --class=debug_automemdisk --class=debug_json --class=F5tool { set pager=1 vt_check_plugin_json $vt_plugin_path auto_memdisk $vtoy_iso_part @@ -156,7 +157,7 @@ submenu 'Check plugin json configuration (ventoy.json)' --class=debug_json --cla unset pager } - menuentry 'Check image list plugin configuration' --class=debug_imagelist --class=debug_json --class=F5tool { + menuentry '@VTMENU_JSON_CHK_IMG_LIST' --class=debug_imagelist --class=debug_json --class=F5tool { set pager=1 vt_check_plugin_json $vt_plugin_path image_list $vtoy_iso_part @@ -165,7 +166,7 @@ submenu 'Check plugin json configuration (ventoy.json)' --class=debug_json --cla unset pager } - menuentry 'Check image blacklist plugin configuration' --class=debug_imageblacklist --class=debug_json --class=F5tool { + menuentry '@VTMENU_JSON_CHK_IMG_BLIST' --class=debug_imageblacklist --class=debug_json --class=F5tool { set pager=1 vt_check_plugin_json $vt_plugin_path image_blacklist $vtoy_iso_part @@ -174,7 +175,7 @@ submenu 'Check plugin json configuration (ventoy.json)' --class=debug_json --cla unset pager } - menuentry 'Check boot conf replace plugin configuration' --class=debug_bootconf_replace --class=debug_json --class=F5tool { + menuentry '@VTMENU_JSON_CHK_CONF_REPLACE' --class=debug_bootconf_replace --class=debug_json --class=F5tool { set pager=1 vt_check_plugin_json $vt_plugin_path conf_replace $vtoy_iso_part @@ -183,7 +184,7 @@ submenu 'Check plugin json configuration (ventoy.json)' --class=debug_json --cla unset pager } - menuentry 'Check dud plugin configuration' --class=debug_dud --class=debug_json --class=F5tool { + menuentry '@VTMENU_JSON_CHK_DUD' --class=debug_dud --class=debug_json --class=F5tool { set pager=1 vt_check_plugin_json $vt_plugin_path dud $vtoy_iso_part @@ -192,7 +193,7 @@ submenu 'Check plugin json configuration (ventoy.json)' --class=debug_json --cla unset pager } - menuentry 'Check password plugin configuration' --class=debug_pwd --class=debug_json --class=F5tool { + menuentry '@VTMENU_JSON_CHK_PASSWORD' --class=debug_pwd --class=debug_json --class=F5tool { set pager=1 vt_check_plugin_json $vt_plugin_path password $vtoy_iso_part @@ -201,21 +202,12 @@ submenu 'Check plugin json configuration (ventoy.json)' --class=debug_json --cla unset pager } - menuentry 'Check custom boot plugin configuration' --class=debug_custom_boot --class=debug_json --class=F5tool { - set pager=1 - vt_check_plugin_json $vt_plugin_path custom_boot $vtoy_iso_part - - echo -e "\npress ENTER to exit ..." - read vtInputKey - unset pager - } - - menuentry 'Return to previous menu [Esc]' --class=vtoyret VTOY_RET { + menuentry '@VTMENU_RETURN_PREVIOUS' --class=vtoyret VTOY_RET { echo 'Return ...' } } -menuentry 'Return to previous menu [Esc]' --class=vtoyret VTOY_RET { +menuentry '@VTMENU_RETURN_PREVIOUS' --class=vtoyret VTOY_RET { echo 'Return ...' } diff --git a/INSTALL/grub/grub.cfg b/INSTALL/grub/grub.cfg index b3977d62..179cc6d6 100644 --- a/INSTALL/grub/grub.cfg +++ b/INSTALL/grub/grub.cfg @@ -108,6 +108,11 @@ function ventoy_show_help { fi } +function ventoy_load_menu_lang_file { + vt_load_file_to_mem "auto" $vtoy_efi_part/grub/menu.tar.gz vtoy_menu_lang_mem + loopback vt_menu_tarfs mem:${vtoy_menu_lang_mem_addr}:size:${vtoy_menu_lang_mem_size} +} + function get_os_type { set vtoy_os=Linux @@ -2344,7 +2349,7 @@ function img_unsupport_menuentry { ############################################################# ############################################################# -set VENTOY_VERSION="1.0.82" +set VENTOY_VERSION="1.0.83" #ACPI not compatible with Window7/8, so disable by default set VTOY_PARAM_NO_ACPI=1 @@ -2433,6 +2438,9 @@ fi #Load Partition Table vt_load_part_table $vtoydev +#Load menu lang file +ventoy_load_menu_lang_file + #Load Plugin if [ -f $vtoy_iso_part/ventoy/ventoy.json ]; then clear @@ -2442,6 +2450,7 @@ else vt_check_json_path_case $vtoy_iso_part fi + if [ -n "$VTOY_MENU_TIMEOUT" ]; then set timeout=$VTOY_MENU_TIMEOUT else @@ -2463,10 +2472,8 @@ fi if [ $VTOY_DEFAULT_MENU_MODE -eq 0 ]; then set VTOY_F3_CMD="vt_dynamic_menu 1 1" - set VTOY_HOTKEY_TIP="h:Help F1:Memdisk F2:Browser F3:TreeView F4:Localboot F5:Tools F6:ExMenu" else set VTOY_F3_CMD="vt_dynamic_menu 1 0" - set VTOY_HOTKEY_TIP="h:Help F1:Memdisk F2:Browser F3:ListView F4:Localboot F5:Tools F6:ExMenu" fi terminal_output console @@ -2575,7 +2582,6 @@ export VTOY_HELP_CMD export VTOY_CHKSUM_CMD export VTOY_HELP_TXT_LANGUAGE export VTOY_CHKSUM_FILE_PATH -export VTOY_HOTKEY_TIP #colect all image files (iso files) diff --git a/INSTALL/grub/hwinfo.cfg b/INSTALL/grub/hwinfo.cfg index 3d3be5ac..a72daad8 100644 --- a/INSTALL/grub/hwinfo.cfg +++ b/INSTALL/grub/hwinfo.cfg @@ -1,4 +1,4 @@ -menuentry 'Hardware Information' --class=debug_hwinfo --class=F5tool { +menuentry '@VTMENU_HWINFO' --class=debug_hwinfo --class=F5tool { smbios -t 4 -s 0x10 --set=cpu_brand set system_vendor="-"; diff --git a/INSTALL/grub/keyboard.cfg b/INSTALL/grub/keyboard.cfg index 8145dcbf..8e499e66 100644 --- a/INSTALL/grub/keyboard.cfg +++ b/INSTALL/grub/keyboard.cfg @@ -1,4 +1,4 @@ -submenu "Keyboard Layouts" --class=debug_krdlayout --class=F5tool { +submenu "@VTMENU_KEYBRD_LAYOUT" --class=debug_krdlayout --class=F5tool { menuentry QWERTY_USA --class=debug_kbd --class=debug_krdlayout --class=F5tool { set_keyboard_layout QWERTY_USA } diff --git a/INSTALL/grub/localboot.cfg b/INSTALL/grub/localboot.cfg index 9366b68c..ce333a3a 100644 --- a/INSTALL/grub/localboot.cfg +++ b/INSTALL/grub/localboot.cfg @@ -1,6 +1,6 @@ if [ "$grub_platform" = "pc" ]; then - menuentry 'Search and boot Windows' --class=boot_windows --class=F4boot { + menuentry '@VTMENU_LB_SBOOT_WINDOWS' --class=boot_windows --class=F4boot { set partid=3 while [ $partid -le 128 ]; do @@ -38,7 +38,7 @@ if [ "$grub_platform" = "pc" ]; then fi } - menuentry 'Search and boot Grub4dos' --class=boot_g4d --class=F4boot { + menuentry '@VTMENU_LB_SBOOT_G4D' --class=boot_g4d --class=F4boot { if search -n -s -f /grldr; then ntldr /grldr else @@ -46,19 +46,19 @@ if [ "$grub_platform" = "pc" ]; then fi } - menuentry 'Boot the 1st local disk' --class=boot_disk --class=F4boot { + menuentry '@VTMENU_LB_SBOOT_HDD1' --class=boot_disk --class=F4boot { set root=(hd0,1) chainloader +1 boot } - menuentry 'Boot the 2nd local disk' --class=boot_disk --class=F4boot { + menuentry '@VTMENU_LB_SBOOT_HDD2' --class=boot_disk --class=F4boot { set root=(hd1,1) chainloader +1 boot } - menuentry 'Boot the 3rd local disk' --class=boot_disk --class=F4boot { + menuentry '@VTMENU_LB_SBOOT_HDD3' --class=boot_disk --class=F4boot { set root=(hd2,1) chainloader +1 boot @@ -66,7 +66,7 @@ if [ "$grub_platform" = "pc" ]; then else - menuentry 'Search and boot Windows' --class=boot_windows --class=F4boot { + menuentry '@VTMENU_LB_SBOOT_WINDOWS' --class=boot_windows --class=F4boot { set partid=3 while [ $partid -le 128 ]; do @@ -102,7 +102,7 @@ else } if [ "$grub_cpu" = "i386" ]; then - menuentry 'Search and boot BOOTIA32.EFI' --class=boot_uefi --class=F4boot { + menuentry '@VTMENU_LB_SBOOT_IA32EFI' --class=boot_uefi --class=F4boot { set VTOY_SEARCH_NO_VTOYEFI=1 if search -n -s -f /efi/boot/bootia32.efi; then unset VTOY_SEARCH_NO_VTOYEFI @@ -115,7 +115,7 @@ else fi } - menuentry 'Search and boot xorboot' --class=boot_xorboot --class=F4boot { + menuentry '@VTMENU_LB_SBOOT_XORBOOT' --class=boot_xorboot --class=F4boot { set VTOY_SEARCH_NO_VTOYEFI=1 if search -n -s -f /efi/xorboot/xorboot32.xor; then unset VTOY_SEARCH_NO_VTOYEFI @@ -132,7 +132,7 @@ else fi } elif [ "$grub_cpu" = "arm64" ]; then - menuentry 'Search and boot BOOTAA64.EFI' --class=boot_uefi --class=F4boot { + menuentry '@VTMENU_LB_SBOOT_AA64EFI' --class=boot_uefi --class=F4boot { set VTOY_SEARCH_NO_VTOYEFI=1 if search -n -s -f /efi/boot/bootaa64.efi; then unset VTOY_SEARCH_NO_VTOYEFI @@ -145,7 +145,7 @@ else fi } else - menuentry 'Search and boot BOOTX64.EFI' --class=boot_uefi --class=F4boot { + menuentry '@VTMENU_LB_SBOOT_X64EFI' --class=boot_uefi --class=F4boot { set VTOY_SEARCH_NO_VTOYEFI=1 if search -n -s -f /efi/boot/bootx64.efi; then unset VTOY_SEARCH_NO_VTOYEFI @@ -158,7 +158,7 @@ else fi } - menuentry 'Search and boot xorboot' --class=boot_xorboot --class=F4boot { + menuentry '@VTMENU_LB_SBOOT_XORBOOT' --class=boot_xorboot --class=F4boot { set VTOY_SEARCH_NO_VTOYEFI=1 if search -n -s -f /efi/xorboot/xorboot.xor; then unset VTOY_SEARCH_NO_VTOYEFI @@ -179,6 +179,6 @@ else fi -menuentry 'Return to previous menu [Esc]' --class=vtoyret VTOY_RET { +menuentry '@VTMENU_RETURN_PREVIOUS' --class=vtoyret VTOY_RET { echo 'Return ...' } diff --git a/INSTALL/grub/menu/en_US.json b/INSTALL/grub/menu/en_US.json new file mode 100644 index 00000000..00d37a93 --- /dev/null +++ b/INSTALL/grub/menu/en_US.json @@ -0,0 +1,81 @@ +{ + "VTMENU_LANGUAGE_NAME": "en_US (English)", + + "VTMENU_STR_HOTKEY_LIST": "h:Help F1:Memdisk F2:Browser F3:ListView F4:Localboot F5:Tools F6:ExMenu", + "VTMENU_STR_HOTKEY_TREE": "h:Help F1:Memdisk F2:Browser F3:TreeView F4:Localboot F5:Tools F6:ExMenu", + "VTMENU_RETURN_PREVIOUS": "Return to previous menu [Esc]", + + "VTMENU_MENU_LANG": "Menu Language Select", + + "VTMENU_LB_SBOOT_WINDOWS": "Search and boot Windows", + "VTMENU_LB_SBOOT_G4D": "Search and boot Grub4dos", + "VTMENU_LB_SBOOT_HDD1": "Boot the 1st local disk", + "VTMENU_LB_SBOOT_HDD2": "Boot the 2nd local disk", + "VTMENU_LB_SBOOT_HDD3": "Boot the 3rd local disk", + "VTMENU_LB_SBOOT_X64EFI": "Search and boot BOOTX64.EFI", + "VTMENU_LB_SBOOT_IA32EFI": "Search and boot BOOTIA32.EFI", + "VTMENU_LB_SBOOT_AA64EFI": "Search and boot BOOTAA64.EFI", + "VTMENU_LB_SBOOT_XORBOOT": "Search and boot xorboot", + + "VTMENU_FILE_CHKSUM": "File checksum", + "VTMENU_CHKSUM_MD5_CALC": "Calculate md5sum", + "VTMENU_CHKSUM_SHA1_CALC": "Calculate sha1sum", + "VTMENU_CHKSUM_SHA256_CALC": "Calculate sha256sum", + "VTMENU_CHKSUM_SHA512_CALC": "Calculate sha512sum", + "VTMENU_CHKSUM_MD5_CALC_CHK": "Calculate and check md5sum", + "VTMENU_CHKSUM_SHA1_CALC_CHK": "Calculate and check sha1sum", + "VTMENU_CHKSUM_SHA256_CALC_CHK": "Calculate and check sha256sum", + "VTMENU_CHKSUM_SHA512_CALC_CHK": "Calculate and check sha512sum", + + "VTMENU_POWER": "Power", + "VTMENU_POWER_REBOOT": "Reboot", + "VTMENU_POWER_HALT": "Halt", + "VTMENU_POWER_BOOT_EFIFW": "Reboot to EFI setup", + + "VTMENU_KEYBRD_LAYOUT": "Keyboard Layouts", + "VTMENU_HWINFO": "Hardware Information", + + "VTMENU_RESOLUTION_CFG": "Resolution Configuration", + "VTMENU_SCREEN_MODE": "Screen Display Mode", + "VTMENU_SCREEN_TEXT_MODE": "Force Text Mode", + "VTMENU_SCREEN_GUI_MODE": "Force Graphics Mode", + + "VTMENU_THEME_SELECT": "Theme Select", + + "VTMENU_UTIL_SHOW_EFI_DRV": "Show EFI Drivers", + "VTMENU_UTIL_FIX_BLINIT_FAIL": "Fixup Windows BlinitializeLibrary Failure", + + "VTMENU_JSON_CHK_JSON": "Check plugin json configuration (ventoy.json)", + "VTMENU_JSON_CHK_CONTROL": "Check global control plugin configuration", + "VTMENU_JSON_CHK_THEME": "Check theme plugin configuration", + "VTMENU_JSON_CHK_AUTOINS": "Check auto install plugin configuration", + "VTMENU_JSON_CHK_PERSIST": "Check persistence plugin configuration", + "VTMENU_JSON_CHK_MENU_ALIAS": "Check menu alias plugin configuration", + "VTMENU_JSON_CHK_MENU_TIP": "Check menu tip plugin configuration", + "VTMENU_JSON_CHK_MENU_CLASS": "Check menu class plugin configuration", + "VTMENU_JSON_CHK_INJECTION": "Check injection plugin configuration", + "VTMENU_JSON_CHK_AUTO_MEMDISK": "Check auto memdisk plugin configuration", + "VTMENU_JSON_CHK_IMG_LIST": "Check image list plugin configuration", + "VTMENU_JSON_CHK_IMG_BLIST": "Check image blacklist plugin configuration", + "VTMENU_JSON_CHK_CONF_REPLACE": "Check boot conf replace plugin configuration", + "VTMENU_JSON_CHK_DUD": "Check dud plugin configuration", + "VTMENU_JSON_CHK_PASSWORD": "Check password plugin configuration", + + "VTMENU_NORMAL_MODE": "Boot in normal mode", + "VTMENU_WIMBOOT_MODE": "Boot in wimboot mode", + "VTMENU_GRUB2_MODE": "Boot in grub2 mode", + "VTMENU_MEMDISK_MODE": "Boot in memdisk mode", + + "VTMENU_RET_TO_LISTVIEW": "Return to ListView", + "VTMENU_RET_TO_TREEVIEW": "Return to TreeView", + + "VTMENU_NO_AUTOINS_SCRIPT": "Boot without auto installation template", + "VTMENU_AUTOINS_USE": "Boot with", + + "VTMENU_NO_PERSIST": "Boot without persistence", + "VTMENU_PERSIST_USE": "Boot with", + + "VTMENU_BROWER_RETURN": "Return", + + "MENU_STR_XXX": "" +} diff --git a/INSTALL/grub/menu/zh_CN.json b/INSTALL/grub/menu/zh_CN.json new file mode 100644 index 00000000..9bb4958b --- /dev/null +++ b/INSTALL/grub/menu/zh_CN.json @@ -0,0 +1,81 @@ +{ + "VTMENU_LANGUAGE_NAME": "zh_CN (简体中文)", + + "VTMENU_STR_HOTKEY_LIST": "h:帮助 F1:内存模式 F2:本地浏览 F3:列表模式 F4:本地启动 F5:工具 F6:扩展菜单", + "VTMENU_STR_HOTKEY_TREE": "h:帮助 F1:内存模式 F2:本地浏览 F3:树形模式 F4:本地启动 F5:工具 F6:扩展菜单", + "VTMENU_RETURN_PREVIOUS": "返回上一级菜单 [Esc]", + + "VTMENU_MENU_LANG": "菜单语言", + + "VTMENU_LB_SBOOT_WINDOWS": "搜索并启动 Windows", + "VTMENU_LB_SBOOT_G4D": "搜索并启动 Grub4dos", + "VTMENU_LB_SBOOT_HDD1": "启动本地硬盘1中的系统", + "VTMENU_LB_SBOOT_HDD2": "启动本地硬盘2中的系统", + "VTMENU_LB_SBOOT_HDD3": "启动本地硬盘3中的系统", + "VTMENU_LB_SBOOT_X64EFI": "搜索并启动 BOOTX64.EFI", + "VTMENU_LB_SBOOT_IA32EFI": "搜索并启动 BOOTIA32.EFI", + "VTMENU_LB_SBOOT_AA64EFI": "搜索并启动 BOOTAA64.EFI", + "VTMENU_LB_SBOOT_XORBOOT": "搜索并启动 xorboot", + + "VTMENU_FILE_CHKSUM": "文件校验", + "VTMENU_CHKSUM_MD5_CALC": "计算 MD5 校验值", + "VTMENU_CHKSUM_SHA1_CALC": "计算 SHA1 校验值", + "VTMENU_CHKSUM_SHA256_CALC": "计算 SHA256 校验值", + "VTMENU_CHKSUM_SHA512_CALC": "计算 SHA512 校验值", + "VTMENU_CHKSUM_MD5_CALC_CHK": "计算并检查 MD5 校验值", + "VTMENU_CHKSUM_SHA1_CALC_CHK": "计算并检查 SHA1 校验值", + "VTMENU_CHKSUM_SHA256_CALC_CHK": "计算并检查 SHA256 校验值", + "VTMENU_CHKSUM_SHA512_CALC_CHK": "计算并检查 SHA512 校验值", + + "VTMENU_POWER": "电源", + "VTMENU_POWER_REBOOT": "重启", + "VTMENU_POWER_HALT": "关机", + "VTMENU_POWER_BOOT_EFIFW": "重启进入 UEFI 设置菜单", + + "VTMENU_KEYBRD_LAYOUT": "键盘布局", + "VTMENU_HWINFO": "硬件信息", + + "VTMENU_RESOLUTION_CFG": "屏幕分辨率", + "VTMENU_SCREEN_MODE": "显示模式", + "VTMENU_SCREEN_TEXT_MODE": "文本模式", + "VTMENU_SCREEN_GUI_MODE": "图形模式", + + "VTMENU_THEME_SELECT": "主题选择", + + "VTMENU_UTIL_SHOW_EFI_DRV": "显示 UEFI 驱动", + "VTMENU_UTIL_FIX_BLINIT_FAIL": "修复 Windows BlinitializeLibrary 错误", + + "VTMENU_JSON_CHK_JSON": "检查插件配置文件 (ventoy.json)", + "VTMENU_JSON_CHK_CONTROL": "配置检查 —— 全局控制插件", + "VTMENU_JSON_CHK_THEME": "配置检查 —— 主题插件", + "VTMENU_JSON_CHK_AUTOINS": "配置检查 —— 自动安装插件", + "VTMENU_JSON_CHK_PERSIST": "配置检查 —— 持久化插件", + "VTMENU_JSON_CHK_MENU_ALIAS": "配置检查 —— 菜单别名插件", + "VTMENU_JSON_CHK_MENU_TIP": "配置检查 —— 菜单提示插件", + "VTMENU_JSON_CHK_MENU_CLASS": "配置检查 —— 菜单类型插件", + "VTMENU_JSON_CHK_INJECTION": "配置检查 —— 文件注入插件", + "VTMENU_JSON_CHK_AUTO_MEMDISK": "配置检查 —— 自动内存盘模式插件", + "VTMENU_JSON_CHK_IMG_LIST": "配置检查 —— 文件列表插件(白名单)", + "VTMENU_JSON_CHK_IMG_BLIST": "配置检查 —— 文件列表插件(黑名单)", + "VTMENU_JSON_CHK_CONF_REPLACE": "配置检查 —— 启动配置替换插件", + "VTMENU_JSON_CHK_DUD": "配置检查 —— Driver Update Disk插件", + "VTMENU_JSON_CHK_PASSWORD": "配置检查 —— 密码插件", + + "VTMENU_NORMAL_MODE": "以正常模式启动", + "VTMENU_WIMBOOT_MODE": "以 wimboot 模式启动", + "VTMENU_GRUB2_MODE": "以 grub2 模式启动", + "VTMENU_MEMDISK_MODE": "以内存盘模式启动", + + "VTMENU_RET_TO_LISTVIEW": "返回到列表模式", + "VTMENU_RET_TO_TREEVIEW": "返回到树形模式", + + "VTMENU_NO_AUTOINS_SCRIPT": "不使用自动安装脚本", + "VTMENU_AUTOINS_USE": "使用", + + "VTMENU_NO_PERSIST": "不使用持久化数据文件", + "VTMENU_PERSIST_USE": "使用", + + "VTMENU_BROWER_RETURN": "返回", + + "MENU_STR_XXX": "" +} diff --git a/INSTALL/grub/menulang.cfg b/INSTALL/grub/menulang.cfg new file mode 100644 index 00000000..35d0d80f --- /dev/null +++ b/INSTALL/grub/menulang.cfg @@ -0,0 +1,3 @@ +submenu "@VTMENU_MENU_LANG" --class=debug_menu_lang --class=F5tool { +#ventoy_pack.sh will generate menuentry here + diff --git a/INSTALL/grub/power.cfg b/INSTALL/grub/power.cfg index 13b00cbf..e60eca02 100644 --- a/INSTALL/grub/power.cfg +++ b/INSTALL/grub/power.cfg @@ -1,25 +1,25 @@ -submenu "Power" --class=debug_power --class=F5tool { - menuentry Reboot --class=debug_reboot --class=debug_power --class=F5tool { +submenu "@VTMENU_POWER" --class=debug_power --class=F5tool { + menuentry "@VTMENU_POWER_REBOOT" --class=debug_reboot --class=debug_power --class=F5tool { echo -e '\n\nSystem is rebooting ... \n' sleep 1 reboot } - menuentry Halt --class=debug_halt --class=debug_power --class=F5tool { + menuentry "@VTMENU_POWER_HALT" --class=debug_halt --class=debug_power --class=F5tool { echo -e '\n\nSystem is halting ... \n' sleep 1 halt } if [ "$grub_platform" != "pc" ]; then - menuentry 'Reboot to EFI setup' --class=debug_efisetup --class=debug_power --class=F5tool { + menuentry '@VTMENU_POWER_BOOT_EFIFW' --class=debug_efisetup --class=debug_power --class=F5tool { echo -e '\n\nRebooting to enter UEFI firmware setup ... \n' sleep 1 fwsetup } fi - menuentry 'Return to previous menu [Esc]' --class=vtoyret VTOY_RET { + menuentry '@VTMENU_RETURN_PREVIOUS' --class=vtoyret VTOY_RET { echo 'Return ...' } } diff --git a/INSTALL/ventoy_pack.sh b/INSTALL/ventoy_pack.sh index 97915f10..d39ac6bb 100644 --- a/INSTALL/ventoy_pack.sh +++ b/INSTALL/ventoy_pack.sh @@ -88,6 +88,26 @@ tar czf help.tar.gz ./help/ rm -rf ./help cd ../../ +#tar menu txt & update menulang.cfg +cd $tmpmnt/grub/ + +for vtlang in $(ls menu/); do + vtlangname=${vtlang%.*} + vtlangtitle=$(grep VTMENU_LANGUAGE_NAME menu/$vtlang | awk -F\" '{print $4}') + echo "menuentry \"$vtlangtitle\" --class=menu_lang_item --class=debug_menu_lang --class=F5tool {" >> menulang.cfg + echo " vt_load_menu_lang $vtlangname" >> menulang.cfg + echo "}" >> menulang.cfg +done +echo "menuentry '@VTMENU_RETURN_PREVIOUS' --class=vtoyret VTOY_RET {" >> menulang.cfg +echo " echo 'Return ...'" >> menulang.cfg +echo "}" >> menulang.cfg +echo "}" >> menulang.cfg + +tar czf menu.tar.gz ./menu/ +rm -rf ./menu +cd ../../ + + cp $OPT ./ventoy $tmpmnt/ cp $OPT ./EFI $tmpmnt/ diff --git a/LANGUAGES/check.sh b/LANGUAGES/check.sh index a18c1a8d..836befd7 100644 --- a/LANGUAGES/check.sh +++ b/LANGUAGES/check.sh @@ -8,10 +8,23 @@ fi gcc -DFOR_VTOY_JSON_CHECK $VTOY_PATH/Ventoy2Disk/Ventoy2Disk/VentoyJson.c -I $VTOY_PATH/Ventoy2Disk/Ventoy2Disk/ -o checkjson +RET=0 + ./checkjson $VTOY_PATH/LANGUAGES/languages.json ret=$? +if [ $ret -eq 0 ]; then + for i in $(ls $VTOY_PATH/INSTALL/grub/menu); do + ./checkjson $VTOY_PATH/INSTALL/grub/menu/$i + ret=$? + if [ $ret -ne 0 ]; then + echo "INSTALL/grub/menu/$i invalid json format" + break + fi + done +else + echo "languages.json invalid json format" +fi rm -f ./checkjson [ $ret -eq 0 ] - diff --git a/Plugson/pack.sh b/Plugson/pack.sh index 46fbf032..52bc9e5d 100644 --- a/Plugson/pack.sh +++ b/Plugson/pack.sh @@ -21,6 +21,10 @@ fi ls -1 ../INSTALL/grub/help/ | while read line; do echo -n ${line:0:5} >> ./www/helplist done +[ -f ./www/menulist ] && rm -f ./www/menulist +ls -1 ../INSTALL/grub/menu/ | while read line; do + echo -n ${line:0:5} >> ./www/menulist +done echo -n "$plugson_verion" > ./www/buildtime tar cf www.tar www diff --git a/Plugson/src/Web/ventoy_http.c b/Plugson/src/Web/ventoy_http.c index a8a86dfb..900045eb 100644 --- a/Plugson/src/Web/ventoy_http.c +++ b/Plugson/src/Web/ventoy_http.c @@ -72,6 +72,7 @@ static const char *g_plugin_name[plugin_type_max] = }; static char g_ventoy_help_lang[MAX_LANGUAGE][8]; +static char g_ventoy_menu_lang[MAX_LANGUAGE][8]; static char g_pub_path[2 * MAX_PATH]; static data_control g_data_control[bios_max + 1]; @@ -522,6 +523,7 @@ void ventoy_data_default_control(data_control *data) strlcpy(data->default_kbd_layout, "QWERTY_USA"); strlcpy(data->help_text_language, "en_US"); + strlcpy(data->menu_language, "en_US"); } int ventoy_data_cmp_control(data_control *data1, data_control *data2) @@ -551,7 +553,8 @@ int ventoy_data_cmp_control(data_control *data1, data_control *data2) if (strcmp(data1->default_search_root, data2->default_search_root) || strcmp(data1->default_image, data2->default_image) || strcmp(data1->default_kbd_layout, data2->default_kbd_layout) || - strcmp(data1->help_text_language, data2->help_text_language)) + strcmp(data1->help_text_language, data2->help_text_language) || + strcmp(data1->menu_language, data2->menu_language)) { return 1; } @@ -595,6 +598,7 @@ int ventoy_data_save_control(data_control *data, const char *title, char *buf, i VTOY_JSON_FMT_CTRL_STRN(L2, "VTOY_DEFAULT_KBD_LAYOUT", default_kbd_layout); VTOY_JSON_FMT_CTRL_STRN(L2, "VTOY_HELP_TXT_LANGUAGE", help_text_language); + VTOY_JSON_FMT_CTRL_STRN(L2, "VTOY_MENU_LANGUAGE", menu_language); if (strcmp(def->default_search_root, data->default_search_root)) { @@ -642,6 +646,7 @@ int ventoy_data_json_control(data_control *ctrl, char *buf, int buflen) VTOY_JSON_FMT_SINT("secondary_menu_timeout", ctrl->secondary_menu_timeout); VTOY_JSON_FMT_STRN("default_kbd_layout", ctrl->default_kbd_layout); VTOY_JSON_FMT_STRN("help_text_language", ctrl->help_text_language); + VTOY_JSON_FMT_STRN("menu_language", ctrl->menu_language); valid = 0; if (ctrl->default_search_root[0] && ventoy_is_directory_exist("%s%s", g_cur_dir, ctrl->default_search_root)) @@ -669,7 +674,15 @@ int ventoy_data_json_control(data_control *ctrl, char *buf, int buflen) } VTOY_JSON_FMT_ARY_ENDEX(); + VTOY_JSON_FMT_KEY("menu_list"); + VTOY_JSON_FMT_ARY_BEGIN(); + for (i = 0; g_ventoy_menu_lang[i][0]; i++) + { + VTOY_JSON_FMT_ITEM(g_ventoy_menu_lang[i]); + } + VTOY_JSON_FMT_ARY_ENDEX(); + VTOY_JSON_FMT_OBJ_END(); VTOY_JSON_FMT_END(pos); @@ -713,6 +726,7 @@ static int ventoy_api_save_control(struct mg_connection *conn, VTOY_JSON *json) VTOY_JSON_STR("default_image", ctrl->default_image); VTOY_JSON_STR("default_search_root", ctrl->default_search_root); VTOY_JSON_STR("help_text_language", ctrl->help_text_language); + VTOY_JSON_STR("menu_language", ctrl->menu_language); VTOY_JSON_STR("default_kbd_layout", ctrl->default_kbd_layout); ret = ventoy_data_save_all(); @@ -4085,6 +4099,17 @@ static int ventoy_parse_control(VTOY_JSON *json, void *p) } } } + else if (strcmp(child->pcName, "VTOY_MENU_LANGUAGE") == 0) + { + for (i = 0; g_ventoy_menu_lang[i][0]; i++) + { + if (strcmp(child->unData.pcStrVal, g_ventoy_menu_lang[i]) == 0) + { + strlcpy(data->menu_language, child->unData.pcStrVal); + break; + } + } + } else if (strcmp(child->pcName, "VTOY_MENU_TIMEOUT") == 0) { data->menu_timeout = (int)strtol(child->unData.pcStrVal, NULL, 10); @@ -5326,6 +5351,19 @@ int ventoy_http_init(void) } free(Buffer); } + + Buffer = NULL; + BufLen = 0; + ventoy_read_file_to_buf("www/menulist", 4, (void **)&Buffer, &BufLen); + if (Buffer) + { + for (i = 0; i < BufLen / 5; i++) + { + memcpy(g_ventoy_menu_lang[i], Buffer + i * 5, 5); + g_ventoy_menu_lang[i][5] = 0; + } + free(Buffer); + } #else ventoy_file *file; file = ventoy_tar_find_file("www/helplist"); @@ -5337,6 +5375,16 @@ int ventoy_http_init(void) g_ventoy_help_lang[i][5] = 0; } } + + file = ventoy_tar_find_file("www/menulist"); + if (file) + { + for (i = 0; i < file->size / 5; i++) + { + memcpy(g_ventoy_menu_lang[i], (char *)(file->addr) + i * 5, 5); + g_ventoy_menu_lang[i][5] = 0; + } + } #endif if (!g_pub_json_buffer) diff --git a/Plugson/src/Web/ventoy_http.h b/Plugson/src/Web/ventoy_http.h index 0ec1e22c..27b7508f 100644 --- a/Plugson/src/Web/ventoy_http.h +++ b/Plugson/src/Web/ventoy_http.h @@ -22,7 +22,7 @@ #include -#define MAX_LANGUAGE 128 +#define MAX_LANGUAGE 256 #define L1 " " #define L2 " " @@ -84,6 +84,7 @@ typedef struct data_control char default_image[MAX_PATH]; char default_kbd_layout[32]; char help_text_language[32]; + char menu_language[32]; }data_control; #define display_mode_gui 0 diff --git a/Plugson/vs/VentoyPlugson/Release/VentoyPlugson.exe b/Plugson/vs/VentoyPlugson/Release/VentoyPlugson.exe index 109da8765a0ef9c6fdc52cd12297d598e7aff669..4267b012e45b7e4f3542799c629ad5f2e16b105f 100644 GIT binary patch delta 51762 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 delta 51004 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 Q3BtQ%m0y|@Yunm?0cBDP?EnA( diff --git a/Plugson/www/menulist b/Plugson/www/menulist new file mode 100644 index 00000000..c28c1f65 --- /dev/null +++ b/Plugson/www/menulist @@ -0,0 +1 @@ +en_USzh_CN \ No newline at end of file diff --git a/Plugson/www/plugson_control.html b/Plugson/www/plugson_control.html index 8cfbfcba..c490c537 100644 --- a/Plugson/www/plugson_control.html +++ b/Plugson/www/plugson_control.html @@ -32,6 +32,42 @@ + +
+
+

VTOY_MENU_LANGUAGE + —— 菜单语言

+
+ +
+
+
+ + + + + + + + + + + + + +
选项设置 + +
选项说明 + Ventoy 菜单的语言版本。默认是 "en_US"。 +
Option Description + Ventoy menu language. Default is "en_US", +
+
+
+ +
@@ -1092,6 +1128,7 @@ data.filter_vtoy = parseInt($('input:radio[name=id_ctrl_radio_filt_vtoy]:checked').val()); data.help_text_language = $('select[id=id_ctrl_sel_help_lang').val(); + data.menu_language = $('select[id=id_ctrl_sel_menu_lang').val(); } function VtoyFillCurrentPageItem(data) { @@ -1192,8 +1229,18 @@ $('select[id=id_ctrl_sel_help_lang').append(opt); } } + $('select[id=id_ctrl_sel_help_lang').val(data.help_language); - $('select[id=id_ctrl_sel_help_lang').val(data.help_text_language); + //VTOY_MENU_LANGUAGE + if ($("select[id=id_ctrl_sel_menu_lang")[0].options.length === 0) + { + for (var i = 0; i < data.menu_list.length; i++) { + var hlang = data.menu_list[i]; + var opt = ''; + $('select[id=id_ctrl_sel_menu_lang').append(opt); + } + } + $('select[id=id_ctrl_sel_menu_lang').val(data.menu_language); } function VtoySaveCurrentPage() { @@ -1329,6 +1376,7 @@ $('select[id=id_ctrl_sel_max_depth]').change(VtoySaveCurrentPage); $('select[id=id_ctrl_sel_kbd]').change(VtoySaveCurrentPage); $('select[id=id_ctrl_sel_help_lang]').change(VtoySaveCurrentPage); + $('select[id=id_ctrl_sel_menu_lang]').change(VtoySaveCurrentPage); $('input[id=id_ctrl_text_timeout]').change(function() { var value = $('input:text[id=id_ctrl_text_timeout]').val(); if (/^[0-9][0-9]*$/.test(value)) {