diff --git a/scripts/generate_fullscreen_ui_translation_strings.py b/scripts/generate_fullscreen_ui_translation_strings.py index 0d5c89a0e..2abb4fe07 100644 --- a/scripts/generate_fullscreen_ui_translation_strings.py +++ b/scripts/generate_fullscreen_ui_translation_strings.py @@ -6,11 +6,15 @@ import re START_IDENT = "// TRANSLATION-STRING-AREA-BEGIN" END_IDENT = "// TRANSLATION-STRING-AREA-END" +SRC_FILES = ["src/core/fullscreen_ui.cpp", "src/util/imgui_fullscreen.cpp", "src/util/imgui_fullscreen.h"] +DST_FILE = "src/core/fullscreen_ui.cpp" -src_file = os.path.join(os.path.dirname(__file__), "..", "src", "core", "fullscreen_ui.cpp") - -with open(src_file, "r") as f: - full_source = f.read() +full_source = "" +for src_file in SRC_FILES: + path = os.path.join(os.path.dirname(__file__), "..", src_file) + with open(path, "r") as f: + full_source += f.read() + full_source += "\n" strings = set() for token in ["FSUI_STR", "FSUI_CSTR", "FSUI_FSTR", "FSUI_NSTR", "FSUI_VSTR", "FSUI_ICONSTR", "FSUI_ICONVSTR", "FSUI_ICONCSTR"]: @@ -57,6 +61,10 @@ for token in ["FSUI_STR", "FSUI_CSTR", "FSUI_FSTR", "FSUI_NSTR", "FSUI_VSTR", "F print(f"Found {len(strings)} unique strings.") +full_source = "" +dst_path = os.path.join(os.path.dirname(__file__), "..", DST_FILE) +with open(dst_path, "r") as f: + full_source = f.read() start = full_source.find(START_IDENT) end = full_source.find(END_IDENT) assert start >= 0 and end > start @@ -66,5 +74,5 @@ for string in sorted(list(strings)): new_area += f"TRANSLATE_NOOP(\"FullscreenUI\", \"{string}\");\n" full_source = full_source[:start+len(START_IDENT)+1] + new_area + full_source[end:] -with open(src_file, "w") as f: +with open(dst_path, "w") as f: f.write(full_source) diff --git a/src/core/fullscreen_ui.cpp b/src/core/fullscreen_ui.cpp index 7b0b8f39b..5d633ba80 100644 --- a/src/core/fullscreen_ui.cpp +++ b/src/core/fullscreen_ui.cpp @@ -52,35 +52,6 @@ LOG_CHANNEL(FullscreenUI); -using namespace std::literals::string_view_literals; - -#define TR_CONTEXT "FullscreenUI"sv - -namespace { -template -class IconStackString : public SmallStackString -{ -public: - ALWAYS_INLINE IconStackString(std::string_view icon, std::string_view str) - { - SmallStackString::format("{} {}", icon, Host::TranslateToStringView(TR_CONTEXT, str)); - } - ALWAYS_INLINE IconStackString(std::string_view icon, std::string_view str, std::string_view suffix) - { - SmallStackString::format("{} {}##{}", icon, Host::TranslateToStringView(TR_CONTEXT, str), suffix); - } -}; -} // namespace - -#define FSUI_ICONSTR(icon, str) fmt::format("{} {}", icon, Host::TranslateToStringView(TR_CONTEXT, str)) -#define FSUI_ICONVSTR(icon, str) IconStackString<128>(icon, str).view() -#define FSUI_ICONCSTR(icon, str) IconStackString<128>(icon, str).c_str() -#define FSUI_STR(str) Host::TranslateToString(TR_CONTEXT, str##sv) -#define FSUI_CSTR(str) Host::TranslateToCString(TR_CONTEXT, str##sv) -#define FSUI_VSTR(str) Host::TranslateToStringView(TR_CONTEXT, str##sv) -#define FSUI_FSTR(str) fmt::runtime(Host::TranslateToStringView(TR_CONTEXT, str##sv)) -#define FSUI_NSTR(str) str - using ImGuiFullscreen::ChoiceDialogOptions; using ImGuiFullscreen::FocusResetType; @@ -361,12 +332,13 @@ static bool DrawToggleSetting(SettingsInterface* bsi, std::string_view title, st static void DrawIntListSetting(SettingsInterface* bsi, std::string_view title, std::string_view summary, const char* section, const char* key, int default_value, std::span options, bool translate_options = true, - int option_offset = 0, bool enabled = true, std::string_view tr_context = TR_CONTEXT); + int option_offset = 0, bool enabled = true, + std::string_view tr_context = FSUI_TR_CONTEXT); static void DrawIntListSetting(SettingsInterface* bsi, std::string_view title, std::string_view summary, const char* section, const char* key, int default_value, std::span options, bool translate_options, std::span values, bool enabled = true, - std::string_view tr_context = TR_CONTEXT); + std::string_view tr_context = FSUI_TR_CONTEXT); static void DrawIntRangeSetting(SettingsInterface* bsi, std::string_view title, std::string_view summary, const char* section, const char* key, int default_value, int min_value, int max_value, const char* format = "%d", bool enabled = true); @@ -390,7 +362,7 @@ static void DrawStringListSetting(SettingsInterface* bsi, std::string_view title const char* section, const char* key, const char* default_value, std::span options, std::span option_values, bool enabled = true, void (*changed_callback)(std::string_view) = nullptr, - std::string_view tr_context = TR_CONTEXT); + std::string_view tr_context = FSUI_TR_CONTEXT); template static void DrawEnumSetting(SettingsInterface* bsi, std::string_view title, std::string_view summary, const char* section, const char* key, DataType default_value, @@ -3573,7 +3545,7 @@ void FullscreenUI::DrawFloatListSetting(SettingsInterface* bsi, std::string_view title, summary, value.has_value() ? ((index < option_count) ? - (translate_options ? Host::TranslateToStringView(TR_CONTEXT, options[index]) : options[index]) : + (translate_options ? Host::TranslateToStringView(FSUI_TR_CONTEXT, options[index]) : options[index]) : FSUI_VSTR("Unknown")) : FSUI_VSTR("Use Global Setting"), enabled)) @@ -3584,7 +3556,7 @@ void FullscreenUI::DrawFloatListSetting(SettingsInterface* bsi, std::string_view cd_options.emplace_back(FSUI_STR("Use Global Setting"), !value.has_value()); for (size_t i = 0; i < option_count; i++) { - cd_options.emplace_back(translate_options ? Host::TranslateToString(TR_CONTEXT, options[i]) : + cd_options.emplace_back(translate_options ? Host::TranslateToString(FSUI_TR_CONTEXT, options[i]) : std::string(options[i]), (value.has_value() && i == static_cast(index))); } @@ -3961,7 +3933,7 @@ void FullscreenUI::DrawSettingsWindow() NavTitle(s_state.game_settings_entry ? std::string_view(s_state.game_settings_entry->title) : - Host::TranslateToStringView(TR_CONTEXT, titles[static_cast(pages[index])].first)); + Host::TranslateToStringView(FSUI_TR_CONTEXT, titles[static_cast(pages[index])].first)); RightAlignNavButtons(count); @@ -7926,7 +7898,7 @@ void FullscreenUI::DrawGameListWindow() if (NavButton(ICON_PF_NAVIGATION_BACK, true, true)) BeginTransition([]() { SwitchToMainWindow(MainWindowType::Landing); }); - NavTitle(Host::TranslateToStringView(TR_CONTEXT, titles[static_cast(s_state.game_list_view)])); + NavTitle(Host::TranslateToStringView(FSUI_TR_CONTEXT, titles[static_cast(s_state.game_list_view)])); RightAlignNavButtons(count); for (u32 i = 0; i < count; i++) @@ -9428,6 +9400,8 @@ TRANSLATE_NOOP("FullscreenUI", "900% [540 FPS (NTSC) / 450 FPS (PAL)]"); TRANSLATE_NOOP("FullscreenUI", "9x"); TRANSLATE_NOOP("FullscreenUI", "9x (18x Speed)"); TRANSLATE_NOOP("FullscreenUI", "9x (for 4K)"); +TRANSLATE_NOOP("FullscreenUI", ""); +TRANSLATE_NOOP("FullscreenUI", ""); TRANSLATE_NOOP("FullscreenUI", "A cover already exists for this game. Are you sure that you want to overwrite it?"); TRANSLATE_NOOP("FullscreenUI", "AMOLED"); TRANSLATE_NOOP("FullscreenUI", "About"); @@ -9810,6 +9784,7 @@ TRANSLATE_NOOP("FullscreenUI", "Multitap Mode"); TRANSLATE_NOOP("FullscreenUI", "Mute All Sound"); TRANSLATE_NOOP("FullscreenUI", "Mute CD Audio"); TRANSLATE_NOOP("FullscreenUI", "Navigate"); +TRANSLATE_NOOP("FullscreenUI", "No"); TRANSLATE_NOOP("FullscreenUI", "No Game Selected"); TRANSLATE_NOOP("FullscreenUI", "No Vibration"); TRANSLATE_NOOP("FullscreenUI", "No cheats are available for this game."); @@ -10133,6 +10108,7 @@ TRANSLATE_NOOP("FullscreenUI", "Widescreen Rendering"); TRANSLATE_NOOP("FullscreenUI", "Window Animations"); TRANSLATE_NOOP("FullscreenUI", "Wireframe Rendering"); TRANSLATE_NOOP("FullscreenUI", "Writes backgrounds that can be replaced to the dump directory."); +TRANSLATE_NOOP("FullscreenUI", "Yes"); TRANSLATE_NOOP("FullscreenUI", "Yes, {} now and risk memory card corruption."); TRANSLATE_NOOP("FullscreenUI", "\"Challenge\" mode for achievements, including leaderboard tracking. Disables save state, cheats, and slowdown functions."); TRANSLATE_NOOP("FullscreenUI", "\"PlayStation\" and \"PSX\" are registered trademarks of Sony Interactive Entertainment Europe Limited. This software is not affiliated in any way with Sony Interactive Entertainment."); diff --git a/src/util/imgui_fullscreen.cpp b/src/util/imgui_fullscreen.cpp index 40fb2a0f3..fecde981d 100644 --- a/src/util/imgui_fullscreen.cpp +++ b/src/util/imgui_fullscreen.cpp @@ -657,6 +657,16 @@ bool ImGuiFullscreen::UpdateLayoutScale() #endif } +ImGuiFullscreen::IconStackString::IconStackString(std::string_view icon, std::string_view str) +{ + SmallStackString::format("{} {}", icon, Host::TranslateToStringView(FSUI_TR_CONTEXT, str)); +} + +ImGuiFullscreen::IconStackString::IconStackString(std::string_view icon, std::string_view str, std::string_view suffix) +{ + SmallStackString::format("{} {}##{}", icon, Host::TranslateToStringView(FSUI_TR_CONTEXT, str), suffix); +} + ImRect ImGuiFullscreen::CenterImage(const ImVec2& fit_size, const ImVec2& image_size) { const float fit_ar = fit_size.x / fit_size.y; @@ -3021,7 +3031,8 @@ void ImGuiFullscreen::FileSelectorDialog::PopulateItems() parent_path.push_back(FS_OSPATH_SEPARATOR_CHARACTER); } - m_items.emplace_back(ICON_EMOJI_FILE_FOLDER_OPEN " ", std::move(parent_path), false); + m_items.emplace_back(fmt::format(ICON_EMOJI_FILE_FOLDER_OPEN " {}", FSUI_VSTR("")), + std::move(parent_path), false); m_first_item_is_parent_directory = true; for (const FILESYSTEM_FIND_DATA& fd : results) @@ -3095,8 +3106,11 @@ void ImGuiFullscreen::FileSelectorDialog::Draw() if (m_is_directory && !m_current_directory.empty()) { - if (MenuButtonWithoutSummary(ICON_EMOJI_FILE_FOLDER_OPEN " ")) + if (MenuButtonWithoutSummary( + SmallString::from_format(ICON_EMOJI_FILE_FOLDER_OPEN " {}", FSUI_VSTR("")))) + { directory_selected = true; + } } for (Item& item : m_items) @@ -3608,7 +3622,7 @@ void ImGuiFullscreen::ProgressDialog::Draw() if (m_user_closeable) { BeginHorizontalMenuButtons(1, 150.0f); - if (HorizontalMenuButton("Cancel")) + if (HorizontalMenuButton(FSUI_ICONSTR(ICON_FA_SQUARE_XMARK, "Cancel"))) StartClose(); EndHorizontalMenuButtons(); } @@ -3616,7 +3630,8 @@ void ImGuiFullscreen::ProgressDialog::Draw() EndRender(); } -std::unique_ptr ImGuiFullscreen::ProgressDialog::GetProgressCallback(std::string title, float window_unscaled_width) +std::unique_ptr ImGuiFullscreen::ProgressDialog::GetProgressCallback(std::string title, + float window_unscaled_width) { if (m_state == PopupDialog::State::Open) { @@ -3704,7 +3719,8 @@ bool ImGuiFullscreen::ProgressDialog::ProgressCallbackImpl::IsCancelled() const return s_state.progress_dialog.m_cancelled.load(std::memory_order_acquire); } -std::unique_ptr ImGuiFullscreen::OpenModalProgressDialog(std::string title, float window_unscaled_width) +std::unique_ptr ImGuiFullscreen::OpenModalProgressDialog(std::string title, + float window_unscaled_width) { return s_state.progress_dialog.GetProgressCallback(std::move(title), window_unscaled_width); } diff --git a/src/util/imgui_fullscreen.h b/src/util/imgui_fullscreen.h index 2b9fdacf1..b7b584140 100644 --- a/src/util/imgui_fullscreen.h +++ b/src/util/imgui_fullscreen.h @@ -3,12 +3,17 @@ #pragma once +#include "host.h" + +#include "common/small_string.h" #include "common/types.h" #include "IconsFontAwesome6.h" #include "imgui.h" #include "imgui_internal.h" +#include "fmt/format.h" + #include #include #include @@ -20,7 +25,6 @@ class Image; class GPUTexture; -class SmallStringBase; class ProgressCallback; namespace ImGuiFullscreen { @@ -172,6 +176,25 @@ ALWAYS_INLINE static std::string_view RemoveHash(std::string_view s) return (pos != std::string_view::npos) ? s.substr(0, pos) : s; } +/// Localization support. +#define FSUI_TR_CONTEXT std::string_view("FullscreenUI") + +class IconStackString : public SmallStackString<128> +{ +public: + IconStackString(std::string_view icon, std::string_view str); + IconStackString(std::string_view icon, std::string_view str, std::string_view suffix); +}; + +#define FSUI_ICONSTR(icon, str) fmt::format("{} {}", icon, Host::TranslateToStringView(FSUI_TR_CONTEXT, str)) +#define FSUI_ICONVSTR(icon, str) ::ImGuiFullscreen::IconStackString(icon, str).view() +#define FSUI_ICONCSTR(icon, str) ::ImGuiFullscreen::IconStackString(icon, str).c_str() +#define FSUI_STR(str) Host::TranslateToString(FSUI_TR_CONTEXT, std::string_view(str)) +#define FSUI_CSTR(str) Host::TranslateToCString(FSUI_TR_CONTEXT, std::string_view(str)) +#define FSUI_VSTR(str) Host::TranslateToStringView(FSUI_TR_CONTEXT, std::string_view(str)) +#define FSUI_FSTR(str) fmt::runtime(Host::TranslateToStringView(FSUI_TR_CONTEXT, std::string_view(str))) +#define FSUI_NSTR(str) str + /// Centers an image within the specified bounds, scaling up or down as needed. ImRect CenterImage(const ImVec2& fit_size, const ImVec2& image_size); ImRect CenterImage(const ImVec2& fit_rect, const GPUTexture* texture); @@ -326,9 +349,9 @@ bool ToggleButton(std::string_view title, std::string_view summary, bool* v, boo bool ThreeWayToggleButton(std::string_view title, std::string_view summary, std::optional* v, bool enabled = true); bool RangeButton(std::string_view title, std::string_view summary, s32* value, s32 min, s32 max, s32 increment, - const char* format = "%d", bool enabled = true, std::string_view ok_text = "OK"); + const char* format = "%d", bool enabled = true, std::string_view ok_text = FSUI_VSTR("OK")); bool RangeButton(std::string_view title, std::string_view summary, float* value, float min, float max, float increment, - const char* format = "%f", bool enabled = true, std::string_view ok_text = "OK"); + const char* format = "%f", bool enabled = true, std::string_view ok_text = FSUI_VSTR("OK")); bool EnumChoiceButtonImpl(std::string_view title, std::string_view summary, s32* value_pointer, const char* (*to_display_name_function)(s32 value, void* opaque), void* opaque, u32 count, bool enabled); @@ -403,10 +426,10 @@ using InfoMessageDialogCallback = std::function; using MessageDialogCallback = std::function; bool IsMessageBoxDialogOpen(); void OpenConfirmMessageDialog(std::string_view title, std::string message, ConfirmMessageDialogCallback callback, - std::string yes_button_text = ICON_FA_CHECK " Yes", - std::string no_button_text = ICON_FA_XMARK " No"); + std::string yes_button_text = FSUI_ICONSTR(ICON_FA_CHECK, "Yes"), + std::string no_button_text = FSUI_ICONSTR(ICON_FA_XMARK, "No")); void OpenInfoMessageDialog(std::string_view title, std::string message, InfoMessageDialogCallback callback = {}, - std::string button_text = ICON_FA_SQUARE_XMARK " Close"); + std::string button_text = FSUI_ICONSTR(ICON_FA_SQUARE_XMARK, "Close")); void OpenMessageDialog(std::string_view title, std::string message, MessageDialogCallback callback, std::string first_button_text, std::string second_button_text, std::string third_button_text); void CloseMessageDialog();