From 6aea02c6afdf339a87eaa42692ac1f5e3b4fd62d Mon Sep 17 00:00:00 2001 From: maron2000 <68574602+maron2000@users.noreply.github.com> Date: Mon, 28 Apr 2025 20:54:43 +0900 Subject: [PATCH 1/3] Fix translated messages in dialog box for macOS --- src/gui/sdlmain.cpp | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp index 6aafe4d5f..02e1375d7 100644 --- a/src/gui/sdlmain.cpp +++ b/src/gui/sdlmain.cpp @@ -1103,7 +1103,7 @@ void GFX_SetTitle(int32_t cycles, int frameskip, Bits timing, bool paused) { bool warn_on_mem_write = false; bool CodePageGuestToHostUTF8(char *d/*CROSS_LEN*/,const char *s/*CROSS_LEN*/) ; -#ifdef LINUX +#if defined(LINUX) std::string replaceNewlineWithEscaped(const std::string& input) { std::string output; size_t i = 0; @@ -1132,7 +1132,7 @@ std::string replaceNewlineWithEscaped(const std::string& input) { return output; } -#else +#elif defined(WIN32) char* convert_escape_newlines(const char* aMessage) { size_t len = strlen(aMessage); char* lMessage = (char*)malloc(len * 2 + 1); // Allocate memory considering convert to UTF8 @@ -1179,27 +1179,54 @@ char* revert_escape_newlines(const char* aMessage) { *dst = '\0'; // Terminate with NULL character return lMessage; } +#elif defined(MACOSX) +std::string replaceNewlineWithEscaped(const std::string& input) { + std::string output; + for (size_t i = 0; i < input.length(); ++i) { + if (input[i] == '\'') { // Close, escape and open + output += "'\\''"; + } + else if (input[i] == '\n'){ + output += "\\n"; // '\n' needs to be replaced to "\\n" + i++; + } + //else if (input[i] == '\"'){ + // output += "\\\""; // '"' needs to be replaced to "\\\"" + // i++; + //} + else { + output += input[i]; + } + } + return output; +} #endif bool systemmessagebox(char const * aTitle, char const * aMessage, char const * aDialogType, char const * aIconType, int aDefaultButton) { #if !defined(HX_DOS) if(!aMessage) aMessage = ""; std::string lDialogString(aMessage); + std::string lTitleString(aTitle); std::replace(lDialogString.begin(), lDialogString.end(), '\"', ' '); - + std::replace(lTitleString.begin(), lTitleString.end(), '\"', ' '); bool fs=sdl.desktop.fullscreen; if (fs) GFX_SwitchFullScreen(); MAPPER_ReleaseAllKeys(); GFX_LosingFocus(); GFX_ReleaseMouse(); -#ifdef LINUX +#ifndef WIN32 size_t aMessageLength = strlen(aMessage); + size_t aTitleLength = strlen(aTitle); char* lMessage = (char*)malloc((aMessageLength * 2 + 1) * sizeof(char)); // DBCS may expand to 3 to 4 bytes when converted to UTF-8 + char* lTitle = (char*)malloc((aTitleLength * 2 + 1) * sizeof(char)); // DBCS may expand to 3 to 4 bytes when converted to UTF-8 lDialogString = replaceNewlineWithEscaped(lDialogString); // String may include "\n" which needs to be escaped to "\\n" CodePageGuestToHostUTF8(lMessage, lDialogString.c_str()); - bool ret=tinyfd_messageBox(aTitle, lMessage, aDialogType, aIconType, aDefaultButton); + lTitleString = replaceNewlineWithEscaped(lTitleString); // String may include "\n" which needs to be escaped to "\\n" + CodePageGuestToHostUTF8(lTitle, lTitleString.c_str()); + bool ret=tinyfd_messageBox(lTitle, lMessage, aDialogType, aIconType, aDefaultButton); free(lMessage); + free(lTitle); #else char* temp_message = convert_escape_newlines(aMessage); //FIX_ME: CodePageGuestToHostUTF8() gives weird results for '\n' size_t max_utf8_len = strlen(temp_message) * 3 + 1; From dac5dcac2709919fc23e9a63965cec8f0c81b46d Mon Sep 17 00:00:00 2001 From: maron2000 <68574602+maron2000@users.noreply.github.com> Date: Mon, 28 Apr 2025 22:59:26 +0900 Subject: [PATCH 2/3] Add some more messages in dialog boxes to be translatable --- contrib/translations/en/en_US.lng | 44 +++++++++++++++++++++++++++++++ contrib/translations/ja/ja_JP.lng | 44 +++++++++++++++++++++++++++++++ src/dos/dos_programs.cpp | 16 ++++++++++- src/gui/render.cpp | 2 +- src/gui/sdl_mapper.cpp | 2 +- src/hardware/adlib.cpp | 10 ++++--- src/hardware/vga_draw.cpp | 1 + src/misc/savestates.cpp | 4 +-- src/output/direct3d/direct3d.cpp | 4 +-- src/output/output_ttf.cpp | 4 +-- 10 files changed, 119 insertions(+), 12 deletions(-) diff --git a/contrib/translations/en/en_US.lng b/contrib/translations/en/en_US.lng index 72d8df15e..d03ab26a6 100644 --- a/contrib/translations/en/en_US.lng +++ b/contrib/translations/en/en_US.lng @@ -4459,3 +4459,47 @@ Are you sure to use the language file for this system type? :LANG_CHANGE_CP The specified language file uses code page %d. Do you want to change to this code page accordingly?. . +:SCALER_LOAD_WARN +This scaler may not work properly or have undesired effect: + +%s + +Do you want to force load the scaler? +. +:PIXEL_SHADER_WARN +This pixel shader may be unneeded or have undesired effect: + +%s + +Do you want to load the pixel shader anyway? + +(You may append 'forced' to the pixelshader setting to force load the pixel shader without this message) +. +:PIXEL_SHADER_LOADED +Loaded pixel shader - %s +. +:MAPPEREDITOR_NOT_AVAILABLE +Mapper Editor is not currently available. +. +:OPL_REC_COMPLETED +Saved Raw OPL output to the file: + +%s +. +:OPL_CAPTURE_FAILED +Cannot capture Raw OPL output because ESFM native mode is being used by the current application, which is not supported by the Raw OPL format. +. +:TTF_DBCS_ONLY +This function is only available for the Chinese/Japanese/Korean code pages. +. +:SAVE_FAILED +Failed to save the current state. +. +:SAVE_CORRUPTED +Save state corrupted! Program may not work. +. +:SAVE_SCREENSHOT +Saved screenshot to the file: + +%s +. \ No newline at end of file diff --git a/contrib/translations/ja/ja_JP.lng b/contrib/translations/ja/ja_JP.lng index 28ffee5be..1ebb78b25 100644 --- a/contrib/translations/ja/ja_JP.lng +++ b/contrib/translations/ja/ja_JP.lng @@ -4477,4 +4477,48 @@ DOSBox-X を終了してよろしいですか? 指定した言語ファイルはコードページ %d を使用します。 このコードページへ変更しますか? +. +:SCALER_LOAD_WARN +このスケーラは正しく動作しないか意図しない動作をするかもしれません: + +%s + +このスケーラを強制的に適用しますか? +. +:PIXEL_SHADER_WARN +このピクセルシェーダは正しく動作しないか意図しない動作をするかもしれません: + +%s + +このピクセルシェーダを強制的に適用しますか? + +(ピクセルシェーダのオプションに 'forced' を追加すると、このメッセージを表示せずに強制的に適用します) +. +:PIXEL_SHADER_LOADED +適用したピクセルシェーダ - %s +. +:MAPPEREDITOR_NOT_AVAILABLE +マッパー・エディタは現在使用できません。 +. +:OPL_REC_COMPLETED +Raw OPL 出力をファイルに保存しました: + +%s +. +:OPL_CAPTURE_FAILED +現在のアプリケーションが Raw OPL フォーマットに対応していない ESFM ネイティブモードを使用しているため、Raw OPL 出力をキャプチャできません。 +. +:TTF_DBCS_ONLY +この機能は中国語 / 日本語 / 韓国語 のコードページで使います。 +. +:SAVE_FAILED +現在のステートを保存できませんでした。 +. +:SAVE_CORRUPTED +セーブ・ステートは壊れています! プログラムは動作しないかもしれません。 +. +:SAVE_SCREENSHOT +スクリーンショットを以下のファイルに保存しました: + +%s . \ No newline at end of file diff --git a/src/dos/dos_programs.cpp b/src/dos/dos_programs.cpp index 86a2f18a1..059a9dbd3 100644 --- a/src/dos/dos_programs.cpp +++ b/src/dos/dos_programs.cpp @@ -10460,7 +10460,21 @@ void DOS_SetupPrograms(void) { "because one or more files are currently open.\nAre you sure to quit anyway now?"); MSG_Add("QUIT_PROGRAM_DISABLED","You cannot quit DOSBox-X while running a program or game."); MSG_Add("QUIT_PROGRAM_CONFIRM","You are currently running a program or game.\nAre you sure to quit anyway now?"); - + MSG_Add("SCALER_LOAD_WARN","This scaler may not work properly or have undesired effect:\n\n%s\n\n" + "Do you want to force load the scaler?"); + MSG_Add("PIXEL_SHADER_WARN","This pixel shader may be unneeded or have undesired effect:\n\n%s\n\n" + "Do you want to load the pixel shader anyway?\n\n" + "(You may append 'forced' to the pixelshader setting to force load the pixel shader without this message)"); + MSG_Add("PIXEL_SHADER_LOADED", "Loaded pixel shader - %s"); + MSG_Add("MAPPEREDITOR_NOT_AVAILABLE","Mapper Editor is not currently available."); + MSG_Add("OPL_REC_COMPLETED","Saved Raw OPL output to the file:\n\n%s"); + MSG_Add("OPL_CAPTURE_FAILED","Cannot capture Raw OPL output because ESFM native mode is being used by the current " + "application, which is not supported by the Raw OPL format."); + MSG_Add("TTF_DBCS_ONLY","This function is only available for the Chinese/Japanese/Korean code pages."); + MSG_Add("SAVE_FAILED","Failed to save the current state."); + MSG_Add("SAVE_CORRUPTED","Save state corrupted! Program may not work."); + MSG_Add("SAVE_SCREENSHOT","Saved screenshot to the file:\n\n%s"); + const Section_prop * dos_section=static_cast(control->GetSection("dos")); hidefiles = dos_section->Get_string("drive z hide files"); diff --git a/src/gui/render.cpp b/src/gui/render.cpp index ae406f7be..4143db655 100644 --- a/src/gui/render.cpp +++ b/src/gui/render.cpp @@ -511,7 +511,7 @@ void RENDER_Reset( void ) { goto forcenormal; if(render.scale.prompt && (!dblh || !dblw) && !((dblh || dblw) && !render.scale.hardware) && scalerOpTV != render.scale.op && scaler != "none" && strncasecmp(scaler.c_str(), "normal", 6) && !render.scale.forced && sdl.desktop.want_type != SCREEN_TTF) { - std::string message = "This scaler may not work properly or have undesired effect:\n\n"+scaler+"\n\nDo you want to force load the scaler?"; + std::string message = formatString(MSG_Get("SCALER_LOAD_WARN"), scaler.c_str()); render.scale.forced = systemmessagebox("Loading scaler", message.c_str(), "yesno","question", 1); render.scale.prompt = false; } diff --git a/src/gui/sdl_mapper.cpp b/src/gui/sdl_mapper.cpp index d2f91e305..548053c40 100644 --- a/src/gui/sdl_mapper.cpp +++ b/src/gui/sdl_mapper.cpp @@ -5336,7 +5336,7 @@ void MAPPER_RunInternal() { /* Sorry, the MAPPER screws up 3Dfx OpenGL emulation. * Remove this block when fixed. */ if (GFX_GetPreventFullscreen()) { - systemmessagebox("Mapper Editor","Mapper Editor is not currently available.","ok", "info", 1); + systemmessagebox("Mapper Editor", MSG_Get("MAPPEREDITOR_NOT_AVAILABLE"),"ok", "info", 1); LOG_MSG("Mapper Editor is not available while 3Dfx OpenGL emulation is running"); return; } diff --git a/src/hardware/adlib.cpp b/src/hardware/adlib.cpp index 1385f0418..dbf6ce91e 100644 --- a/src/hardware/adlib.cpp +++ b/src/hardware/adlib.cpp @@ -1337,16 +1337,20 @@ void OPL_SaveRawEvent(bool pressed) { // SaveRad();return; /* Check for previously opened wave file */ - if ( module->capture ) { + std::string message; + if ( module->capture ) { delete module->capture; module->capture = nullptr; LOG_MSG("Stopped Raw OPL capturing."); - if (show_recorded_filename && pathopl.size()) systemmessagebox("Recording completed",("Saved Raw OPL output to the file:\n\n"+pathopl).c_str(),"ok", "info", 1); + if(show_recorded_filename && pathopl.size()) { + message = formatString(MSG_Get("OPL_REC_COMPLETED"), pathopl.c_str()); + systemmessagebox("Recording completed", message.c_str(), "ok", "info", 1); + } } else { if (module->oplmode == OPL_esfm && module->esfm_nativemode) { LOG_MSG("ERROR: Cannot capture Raw OPL output because ESFM native mode is being used by the current application, which is not supported by the Raw OPL format."); if (show_recorded_filename) { - systemmessagebox("Error", "Cannot capture Raw OPL output because ESFM native mode is being used by the current application, which is not supported by the Raw OPL format.", "ok", "error", 1); + systemmessagebox("Error",MSG_Get("OPL_CAPTURE_FAILED"), "ok", "error", 1); } } else { LOG_MSG("Preparing to capture Raw OPL, will start with first note played."); diff --git a/src/hardware/vga_draw.cpp b/src/hardware/vga_draw.cpp index ab2b70e31..2ab96fc7c 100644 --- a/src/hardware/vga_draw.cpp +++ b/src/hardware/vga_draw.cpp @@ -5642,6 +5642,7 @@ void WriteARawImage(rawscreenshot &rawimg,rawscreenshot &rawpal,const char *ext) png_destroy_write_struct(&png_ptr, &info_ptr); /*close file*/ fclose(fp); + std::string message = formatString(MSG_Get("SAVE_SCREENSHOT"), pathscr.c_str()); if (show_recorded_filename && pathscr.size()) systemmessagebox("Recording completed",("Saved screenshot to the file:\n\n"+pathscr).c_str(),"ok", "info", 1); } #endif diff --git a/src/misc/savestates.cpp b/src/misc/savestates.cpp index a1f8e7670..614ac3744 100644 --- a/src/misc/savestates.cpp +++ b/src/misc/savestates.cpp @@ -573,14 +573,14 @@ done: if (!dos_kernel_disabled) flagged_backup((char *)save.c_str()); if (save_err) - notifyError("Failed to save the current state."); + notifyError(MSG_Get("SAVE_FAILED")); else LOG_MSG("[%s]: Saved. (Slot %d)", getTime().c_str(), (int)slot+1); } void savestatecorrupt(const char* part) { LOG_MSG("Save state corrupted! Program in inconsistent state! - %s", part); - systemmessagebox("Error","Save state corrupted! Program may not work.","ok","error", 1); + systemmessagebox("Error", MSG_Get("SAVE_CORRUPTED"),"ok","error", 1); } bool confres=false; diff --git a/src/output/direct3d/direct3d.cpp b/src/output/direct3d/direct3d.cpp index 7befc2c0a..367cb64f1 100644 --- a/src/output/direct3d/direct3d.cpp +++ b/src/output/direct3d/direct3d.cpp @@ -1035,9 +1035,9 @@ HRESULT CDirect3D::LoadPixelShader(const char * shader, double scalex, double sc // Compare optimal scaling factor bool dblgfx=((scalex < scaley ? scalex : scaley) >= psEffect->getScale()); - std::string message = "This pixel shader may be unneeded or have undesired effect:\n\n"+std::string(shader)+"\n\nDo you want to load the pixel shader anyway?\n\n(You may append 'forced' to the pixelshader setting to force load the pixel shader without this message)"; + std::string message = formatString(MSG_Get("PIXEL_SHADER_WARN"), shader); if(dblgfx || forced || systemmessagebox("Direct3D shader", message.c_str(), "yesno","question", 1)) { - message = "Loaded pixel shader - "+std::string(shader); + message = formatString(MSG_Get("PIXEL_SHADER_LOADED"), shader); if (informd3d) systemmessagebox("Direct3D shader", message.c_str(), "ok","info", 1); LOG_MSG("D3D:Pixel shader %s active", shader); RENDER_SetForceUpdate(psEffect->getForceUpdate()); diff --git a/src/output/output_ttf.cpp b/src/output/output_ttf.cpp index 7451c80ad..8cb7e33a8 100644 --- a/src/output/output_ttf.cpp +++ b/src/output/output_ttf.cpp @@ -1345,7 +1345,7 @@ void TTF_DecreaseSize(bool pressed) { void DBCSSBCS_mapper_shortcut(bool pressed) { if (!pressed) return; if (!isDBCSCP()) { - systemmessagebox("Warning", "This function is only available for the Chinese/Japanese/Korean code pages.", "ok","warning", 1); + systemmessagebox("Warning", MSG_Get("TTF_DBCS_ONLY"), "ok","warning", 1); return; } dbcs_sbcs=!dbcs_sbcs; @@ -1357,7 +1357,7 @@ void DBCSSBCS_mapper_shortcut(bool pressed) { void AutoBoxDraw_mapper_shortcut(bool pressed) { if (!pressed) return; if (!isDBCSCP()) { - systemmessagebox("Warning", "This function is only available for the Chinese/Japanese/Korean code pages.", "ok","warning", 1); + systemmessagebox("Warning", MSG_Get("TTF_DBCS_ONLY"), "ok","warning", 1); return; } autoboxdraw=!autoboxdraw; From a68bf785ebff7ed08d3dab7d26f1a4a320f313bd Mon Sep 17 00:00:00 2001 From: maron2000 <68574602+maron2000@users.noreply.github.com> Date: Tue, 29 Apr 2025 07:56:35 +0900 Subject: [PATCH 3/3] Fallback to LINUX to avoid build error of missing functions --- src/gui/sdlmain.cpp | 60 ++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp index 02e1375d7..2c1c0ce33 100644 --- a/src/gui/sdlmain.cpp +++ b/src/gui/sdlmain.cpp @@ -1103,36 +1103,7 @@ void GFX_SetTitle(int32_t cycles, int frameskip, Bits timing, bool paused) { bool warn_on_mem_write = false; bool CodePageGuestToHostUTF8(char *d/*CROSS_LEN*/,const char *s/*CROSS_LEN*/) ; -#if defined(LINUX) -std::string replaceNewlineWithEscaped(const std::string& input) { - std::string output; - size_t i = 0; - - while (i < input.length()) { - if (input[i] == '\\') { - if(input[i+1] != 'n') output += '\\'; // "\n" needs to be escaped to "\\n" - } - else if (input[i] == '\n'){ - output += "\\\\n"; // '\n' needs to be replaced to "\\n" - i++; - } - else if(input[i] == '`'){ - output += "\\`"; // '`' needs to be replaced to "\\`" - i++; - } - else if(input[i] == '"'){ - output += "\\\""; // '"' needs to be replaced to "\\\"" - i++; - } - else { - output += input[i]; - i++; - } - } - - return output; -} -#elif defined(WIN32) +#if defined(WIN32) char* convert_escape_newlines(const char* aMessage) { size_t len = strlen(aMessage); char* lMessage = (char*)malloc(len * 2 + 1); // Allocate memory considering convert to UTF8 @@ -1200,6 +1171,35 @@ std::string replaceNewlineWithEscaped(const std::string& input) { } return output; } +#else +std::string replaceNewlineWithEscaped(const std::string& input) { + std::string output; + size_t i = 0; + + while(i < input.length()) { + if(input[i] == '\\') { + if(input[i + 1] != 'n') output += '\\'; // "\n" needs to be escaped to "\\n" + } + else if(input[i] == '\n') { + output += "\\\\n"; // '\n' needs to be replaced to "\\n" + i++; + } + else if(input[i] == '`') { + output += "\\`"; // '`' needs to be replaced to "\\`" + i++; + } + else if(input[i] == '"') { + output += "\\\""; // '"' needs to be replaced to "\\\"" + i++; + } + else { + output += input[i]; + i++; + } + } + + return output; +} #endif bool systemmessagebox(char const * aTitle, char const * aMessage, char const * aDialogType, char const * aIconType, int aDefaultButton) {