FullscreenUI: Localize base strings (e.g. dir selector)

This commit is contained in:
Stenzek 2025-07-19 17:46:19 +10:00
parent 63e0acbe9c
commit 75314f79de
No known key found for this signature in database
4 changed files with 75 additions and 52 deletions

View File

@ -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)

View File

@ -52,35 +52,6 @@
LOG_CHANNEL(FullscreenUI);
using namespace std::literals::string_view_literals;
#define TR_CONTEXT "FullscreenUI"sv
namespace {
template<size_t L>
class IconStackString : public SmallStackString<L>
{
public:
ALWAYS_INLINE IconStackString(std::string_view icon, std::string_view str)
{
SmallStackString<L>::format("{} {}", icon, Host::TranslateToStringView(TR_CONTEXT, str));
}
ALWAYS_INLINE IconStackString(std::string_view icon, std::string_view str, std::string_view suffix)
{
SmallStackString<L>::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<const char* const> 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<const char* const> options, bool translate_options,
std::span<const int> 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<const char* const> options, std::span<const char* const> 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<typename DataType, typename SizeType>
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<size_t>(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<u32>(pages[index])].first));
Host::TranslateToStringView(FSUI_TR_CONTEXT, titles[static_cast<u32>(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<u32>(s_state.game_list_view)]));
NavTitle(Host::TranslateToStringView(FSUI_TR_CONTEXT, titles[static_cast<u32>(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", "<Parent Directory>");
TRANSLATE_NOOP("FullscreenUI", "<Use This Directory>");
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.");

View File

@ -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 " <Parent Directory>", std::move(parent_path), false);
m_items.emplace_back(fmt::format(ICON_EMOJI_FILE_FOLDER_OPEN " {}", FSUI_VSTR("<Parent Directory>")),
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 " <Use This Directory>"))
if (MenuButtonWithoutSummary(
SmallString::from_format(ICON_EMOJI_FILE_FOLDER_OPEN " {}", FSUI_VSTR("<Use This Directory>"))))
{
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<ProgressCallback> ImGuiFullscreen::ProgressDialog::GetProgressCallback(std::string title, float window_unscaled_width)
std::unique_ptr<ProgressCallback> 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<ProgressCallback> ImGuiFullscreen::OpenModalProgressDialog(std::string title, float window_unscaled_width)
std::unique_ptr<ProgressCallback> ImGuiFullscreen::OpenModalProgressDialog(std::string title,
float window_unscaled_width)
{
return s_state.progress_dialog.GetProgressCallback(std::move(title), window_unscaled_width);
}

View File

@ -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 <functional>
#include <memory>
#include <optional>
@ -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<bool>* 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<void()>;
using MessageDialogCallback = std::function<void(s32)>;
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();