Host: Re-introduce plural translation support

This commit is contained in:
Stenzek 2024-05-13 01:46:45 +10:00
parent a2abcc9bb3
commit f3aec0c965
No known key found for this signature in database
13 changed files with 230 additions and 150 deletions

View file

@ -1018,9 +1018,13 @@ void Achievements::DisplayAchievementSummary()
if (s_game_summary.num_core_achievements > 0)
{
summary = fmt::format(
TRANSLATE_FS("Achievements", "You have unlocked {0} of {1} achievements, and earned {2} of {3} points."),
s_game_summary.num_unlocked_achievements, s_game_summary.num_core_achievements, s_game_summary.points_unlocked,
s_game_summary.points_core);
TRANSLATE_FS("Achievements", "{0}, {1}."),
SmallString::from_format(TRANSLATE_PLURAL_FS("Achievements", "You have unlocked {} of %n achievements",
"Achievement popup", s_game_summary.num_core_achievements),
s_game_summary.num_unlocked_achievements),
SmallString::from_format(TRANSLATE_PLURAL_FS("Achievements", "and earned {} of %n points", "Achievement popup",
s_game_summary.points_core),
s_game_summary.points_unlocked));
}
else
{
@ -1091,8 +1095,11 @@ void Achievements::HandleGameCompleteEvent(const rc_client_event_t* event)
if (g_settings.achievements_notifications && FullscreenUI::Initialize())
{
std::string title = fmt::format(TRANSLATE_FS("Achievements", "Mastered {}"), s_game_title);
std::string message = fmt::format(TRANSLATE_FS("Achievements", "{} achievements, {} points"),
s_game_summary.num_unlocked_achievements, s_game_summary.points_unlocked);
std::string message = fmt::format(
TRANSLATE_FS("Achievements", "{0}, {1}"),
TRANSLATE_PLURAL_STR("Achievements", "%n achievements", "Mastery popup",
s_game_summary.num_unlocked_achievements),
TRANSLATE_PLURAL_STR("Achievements", "%n points", "Mastery popup", s_game_summary.num_unlocked_achievements));
ImGuiFullscreen::AddNotification("achievement_mastery", GAME_COMPLETE_NOTIFICATION_TIME, std::move(title),
std::move(message), s_game_icon);

View file

@ -1067,7 +1067,7 @@ TinyString GameList::FormatTimespan(std::time_t timespan, bool long_format)
if (hours > 0)
ret.format(TRANSLATE_FS("GameList", "{} hours"), hours);
else
ret.format(TRANSLATE_FS("GameList", "{} minutes"), minutes);
ret.assign(TRANSLATE_PLURAL_STR("GameList", "%n minutes", "", minutes));
}
return ret;

View file

@ -2476,7 +2476,7 @@ bool CompressAndWriteTextureToFile(u32 width, u32 height, std::string filename,
if (!osd_key.empty())
{
Host::AddIconOSDMessage(std::move(osd_key), ICON_FA_CAMERA,
fmt::format(result ? TRANSLATE_FS("GS", "Saved screenshot to '{}'.") :
fmt::format(result ? TRANSLATE_FS("GPU", "Saved screenshot to '{}'.") :
TRANSLATE_FS("GPU", "Failed to save screenshot to '{}'."),
Path::GetFileName(filename),
result ? Host::OSD_INFO_DURATION : Host::OSD_ERROR_DURATION));

View file

@ -146,11 +146,10 @@ static bool CanPause()
const float delta = static_cast<float>(Common::Timer::ConvertValueToSeconds(time - s_last_pause_time));
if (delta < PAUSE_INTERVAL)
{
Host::AddIconOSDMessage(
"PauseCooldown", ICON_FA_CLOCK,
fmt::format(TRANSLATE_FS("Hotkeys", "You cannot pause until another {:.1f} seconds have passed."),
PAUSE_INTERVAL - delta),
Host::OSD_QUICK_DURATION);
Host::AddIconOSDMessage("PauseCooldown", ICON_FA_CLOCK,
TRANSLATE_PLURAL_STR("Hotkeys", "You cannot pause until another %n second(s) have passed.",
"", static_cast<int>(std::ceil(PAUSE_INTERVAL - delta))),
Host::OSD_QUICK_DURATION);
return false;
}
@ -543,36 +542,35 @@ DEFINE_HOTKEY("AudioVolumeDown", TRANSLATE_NOOP("Hotkeys", "Audio"), TRANSLATE_N
// NOTE: All save/load state hotkeys are deferred, because it can trigger setting reapply, which reloads bindings.
DEFINE_HOTKEY("LoadSelectedSaveState", TRANSLATE_NOOP("Hotkeys", "Save States"),
TRANSLATE_NOOP("Hotkeys", "Load From Selected Slot"),
[](s32 pressed) {
TRANSLATE_NOOP("Hotkeys", "Load From Selected Slot"), [](s32 pressed) {
if (!pressed)
Host::RunOnCPUThread(SaveStateSelectorUI::LoadCurrentSlot);
})
DEFINE_HOTKEY(
"SaveSelectedSaveState", TRANSLATE_NOOP("Hotkeys", "Save States"), TRANSLATE_NOOP("Hotkeys", "Save To Selected Slot"),
[](s32 pressed) {
if (!pressed)
Host::RunOnCPUThread(SaveStateSelectorUI::SaveCurrentSlot);
}) DEFINE_HOTKEY("SelectPreviousSaveStateSlot", TRANSLATE_NOOP("Hotkeys", "Save States"),
TRANSLATE_NOOP("Hotkeys", "Select Previous Save Slot"),
[](s32 pressed) {
if (!pressed)
Host::RunOnCPUThread([]() { SaveStateSelectorUI::SelectPreviousSlot(true); });
}) DEFINE_HOTKEY("SelectNextSaveStateSlot", TRANSLATE_NOOP("Hotkeys", "Save States"),
TRANSLATE_NOOP("Hotkeys", "Select Next Save Slot"),
[](s32 pressed) {
if (!pressed)
Host::RunOnCPUThread([]() { SaveStateSelectorUI::SelectNextSlot(true); });
}) DEFINE_HOTKEY("SaveStateAndSelectNextSlot",
TRANSLATE_NOOP("Hotkeys", "Save States"),
TRANSLATE_NOOP("Hotkeys", "Save State and Select Next Slot"),
[](s32 pressed) {
if (!pressed && System::IsValid())
{
SaveStateSelectorUI::SaveCurrentSlot();
SaveStateSelectorUI::SelectNextSlot(false);
}
})
DEFINE_HOTKEY("SaveSelectedSaveState", TRANSLATE_NOOP("Hotkeys", "Save States"),
TRANSLATE_NOOP("Hotkeys", "Save To Selected Slot"),
[](s32 pressed) {
if (!pressed)
Host::RunOnCPUThread(SaveStateSelectorUI::SaveCurrentSlot);
})
DEFINE_HOTKEY("SelectPreviousSaveStateSlot", TRANSLATE_NOOP("Hotkeys", "Save States"),
TRANSLATE_NOOP("Hotkeys", "Select Previous Save Slot"),
[](s32 pressed) {
if (!pressed)
Host::RunOnCPUThread([]() { SaveStateSelectorUI::SelectPreviousSlot(true); });
}) DEFINE_HOTKEY("SelectNextSaveStateSlot", TRANSLATE_NOOP("Hotkeys", "Save States"),
TRANSLATE_NOOP("Hotkeys", "Select Next Save Slot"),
[](s32 pressed) {
if (!pressed)
Host::RunOnCPUThread([]() { SaveStateSelectorUI::SelectNextSlot(true); });
}) DEFINE_HOTKEY("SaveStateAndSelectNextSlot", TRANSLATE_NOOP("Hotkeys", "Save States"),
TRANSLATE_NOOP("Hotkeys", "Save State and Select Next Slot"),
[](s32 pressed) {
if (!pressed && System::IsValid())
{
SaveStateSelectorUI::SaveCurrentSlot();
SaveStateSelectorUI::SelectNextSlot(false);
}
})
DEFINE_HOTKEY("UndoLoadState", TRANSLATE_NOOP("Hotkeys", "Save States"), TRANSLATE_NOOP("Hotkeys", "Undo Load State"),
[](s32 pressed) {
@ -593,71 +591,79 @@ DEFINE_HOTKEY(
Host::RunOnCPUThread([]() { HotkeySaveStateSlot(global, slot); }); \
})
MAKE_LOAD_STATE_HOTKEY(false, 1, TRANSLATE_NOOP("Hotkeys", "Load Game State 1")) MAKE_SAVE_STATE_HOTKEY(
false, 1, TRANSLATE_NOOP("Hotkeys", "Save Game State 1"))
MAKE_LOAD_STATE_HOTKEY(false, 2, TRANSLATE_NOOP("Hotkeys", "Load Game State 2")) MAKE_SAVE_STATE_HOTKEY(
false, 2, TRANSLATE_NOOP("Hotkeys", "Save Game State 2"))
MAKE_LOAD_STATE_HOTKEY(false, 3, TRANSLATE_NOOP("Hotkeys", "Load Game State 3")) MAKE_SAVE_STATE_HOTKEY(
false, 3, TRANSLATE_NOOP("Hotkeys", "Save Game State 3"))
MAKE_LOAD_STATE_HOTKEY(false, 4, TRANSLATE_NOOP("Hotkeys", "Load Game State 4")) MAKE_SAVE_STATE_HOTKEY(
false, 4,
TRANSLATE_NOOP("Hotkeys", "Save Game State 4")) MAKE_LOAD_STATE_HOTKEY(false, 5,
TRANSLATE_NOOP("Hotkeys",
"Load Game State 5"))
MAKE_SAVE_STATE_HOTKEY(false, 5, TRANSLATE_NOOP("Hotkeys", "Save Game State 5")) MAKE_LOAD_STATE_HOTKEY(
false, 6,
TRANSLATE_NOOP("Hotkeys", "Load Game State 6"))
MAKE_SAVE_STATE_HOTKEY(false, 6, TRANSLATE_NOOP("Hotkeys", "Save Game State 6")) MAKE_LOAD_STATE_HOTKEY(
false, 7,
TRANSLATE_NOOP("Hotkeys", "Load Game State 7"))
MAKE_SAVE_STATE_HOTKEY(false, 7, TRANSLATE_NOOP("Hotkeys", "Save Game State 7")) MAKE_LOAD_STATE_HOTKEY(
false, 8,
TRANSLATE_NOOP("Hotkeys", "Load Game State 8"))
MAKE_SAVE_STATE_HOTKEY(false, 8, TRANSLATE_NOOP("Hotkeys", "Save Game State 8"))
MAKE_LOAD_STATE_HOTKEY(false, 9, TRANSLATE_NOOP("Hotkeys", "Load Game State 9"))
MAKE_SAVE_STATE_HOTKEY(false, 9, TRANSLATE_NOOP("Hotkeys", "Save Game State 9"))
MAKE_LOAD_STATE_HOTKEY(false, 10, TRANSLATE_NOOP("Hotkeys", "Load Game State 10"))
MAKE_SAVE_STATE_HOTKEY(false, 10, TRANSLATE_NOOP("Hotkeys", "Save Game State 10"))
MAKE_LOAD_STATE_HOTKEY(false, 1, TRANSLATE_NOOP("Hotkeys", "Load Game State 1"))
MAKE_SAVE_STATE_HOTKEY(false, 1, TRANSLATE_NOOP("Hotkeys", "Save Game State 1"))
MAKE_LOAD_STATE_HOTKEY(false, 2, TRANSLATE_NOOP("Hotkeys", "Load Game State 2")) MAKE_SAVE_STATE_HOTKEY(
false, 2, TRANSLATE_NOOP("Hotkeys", "Save Game State 2"))
MAKE_LOAD_STATE_HOTKEY(false, 3, TRANSLATE_NOOP("Hotkeys", "Load Game State 3")) MAKE_SAVE_STATE_HOTKEY(
false, 3, TRANSLATE_NOOP("Hotkeys", "Save Game State 3"))
MAKE_LOAD_STATE_HOTKEY(false, 4, TRANSLATE_NOOP("Hotkeys", "Load Game State 4")) MAKE_SAVE_STATE_HOTKEY(
false, 4, TRANSLATE_NOOP("Hotkeys", "Save Game State 4"))
MAKE_LOAD_STATE_HOTKEY(false, 5, TRANSLATE_NOOP("Hotkeys", "Load Game State 5")) MAKE_SAVE_STATE_HOTKEY(
false, 5, TRANSLATE_NOOP("Hotkeys", "Save Game State 5"))
MAKE_LOAD_STATE_HOTKEY(false, 6, TRANSLATE_NOOP("Hotkeys", "Load Game State 6")) MAKE_SAVE_STATE_HOTKEY(
false, 6, TRANSLATE_NOOP("Hotkeys", "Save Game State 6"))
MAKE_LOAD_STATE_HOTKEY(false, 7, TRANSLATE_NOOP("Hotkeys", "Load Game State 7"))
MAKE_SAVE_STATE_HOTKEY(false, 7, TRANSLATE_NOOP("Hotkeys", "Save Game State 7"))
MAKE_LOAD_STATE_HOTKEY(false, 8, TRANSLATE_NOOP("Hotkeys", "Load Game State 8"))
MAKE_SAVE_STATE_HOTKEY(false, 8, TRANSLATE_NOOP("Hotkeys", "Save Game State 8"))
MAKE_LOAD_STATE_HOTKEY(false, 9, TRANSLATE_NOOP("Hotkeys", "Load Game State 9"))
MAKE_SAVE_STATE_HOTKEY(false, 9, TRANSLATE_NOOP("Hotkeys", "Save Game State 9"))
MAKE_LOAD_STATE_HOTKEY(false, 10, TRANSLATE_NOOP("Hotkeys", "Load Game State 10"))
MAKE_SAVE_STATE_HOTKEY(false, 10, TRANSLATE_NOOP("Hotkeys", "Save Game State 10"))
MAKE_LOAD_STATE_HOTKEY(true, 1, TRANSLATE_NOOP("Hotkeys", "Load Global State 1"))
MAKE_SAVE_STATE_HOTKEY(true, 1, TRANSLATE_NOOP("Hotkeys", "Save Global State 1"))
MAKE_LOAD_STATE_HOTKEY(true, 2, TRANSLATE_NOOP("Hotkeys", "Load Global State 2"))
MAKE_SAVE_STATE_HOTKEY(true, 2, TRANSLATE_NOOP("Hotkeys", "Save Global State 2"))
MAKE_LOAD_STATE_HOTKEY(true, 3, TRANSLATE_NOOP("Hotkeys", "Load Global State 3"))
MAKE_SAVE_STATE_HOTKEY(true, 3, TRANSLATE_NOOP("Hotkeys", "Save Global State 3"))
MAKE_LOAD_STATE_HOTKEY(true,
4, TRANSLATE_NOOP("Hotkeys", "Load Global State 4"))
MAKE_SAVE_STATE_HOTKEY(true,
4, TRANSLATE_NOOP("Hotkeys", "Save Global State 4"))
MAKE_LOAD_STATE_HOTKEY(true,
5, TRANSLATE_NOOP("Hotkeys", "Load Global State 5"))
MAKE_SAVE_STATE_HOTKEY(
true, 5, TRANSLATE_NOOP("Hotkeys", "Save Global State 5"))
MAKE_LOAD_STATE_HOTKEY(
true, 6, TRANSLATE_NOOP("Hotkeys", "Load Global State 6"))
MAKE_SAVE_STATE_HOTKEY(
true, 6, TRANSLATE_NOOP("Hotkeys", "Save Global State 6"))
MAKE_LOAD_STATE_HOTKEY(
true, 7, TRANSLATE_NOOP("Hotkeys", "Load Global State 7"))
MAKE_SAVE_STATE_HOTKEY(
true, 7, TRANSLATE_NOOP("Hotkeys", "Save Global State 7"))
MAKE_LOAD_STATE_HOTKEY(
true, 8, TRANSLATE_NOOP("Hotkeys", "Load Global State 8"))
MAKE_SAVE_STATE_HOTKEY(
true, 8, TRANSLATE_NOOP("Hotkeys", "Save Global State 8"))
MAKE_LOAD_STATE_HOTKEY(
true, 9, TRANSLATE_NOOP("Hotkeys", "Load Global State 9"))
MAKE_SAVE_STATE_HOTKEY(
true, 9,
TRANSLATE_NOOP("Hotkeys", "Save Global State 9"))
MAKE_LOAD_STATE_HOTKEY(
true, 10,
TRANSLATE_NOOP("Hotkeys", "Load Global State 10"))
MAKE_SAVE_STATE_HOTKEY(
true, 10,
TRANSLATE_NOOP("Hotkeys", "Save Global State 10"))
MAKE_LOAD_STATE_HOTKEY(true, 1, TRANSLATE_NOOP("Hotkeys", "Load Global State 1"))
MAKE_SAVE_STATE_HOTKEY(true, 1, TRANSLATE_NOOP("Hotkeys", "Save Global State 1"))
MAKE_LOAD_STATE_HOTKEY(true, 2, TRANSLATE_NOOP("Hotkeys", "Load Global State 2"))
MAKE_SAVE_STATE_HOTKEY(true, 2,
TRANSLATE_NOOP("Hotkeys", "Save Global State 2"))
MAKE_LOAD_STATE_HOTKEY(true,
3, TRANSLATE_NOOP("Hotkeys", "Load Global State 3"))
MAKE_SAVE_STATE_HOTKEY(true, 3,
TRANSLATE_NOOP("Hotkeys", "Save Global State 3"))
MAKE_LOAD_STATE_HOTKEY(true, 4,
TRANSLATE_NOOP("Hotkeys", "Load Global State 4"))
MAKE_SAVE_STATE_HOTKEY(true, 4,
TRANSLATE_NOOP("Hotkeys", "Save Global State 4"))
MAKE_LOAD_STATE_HOTKEY(true, 5,
TRANSLATE_NOOP("Hotkeys",
"Load Global State 5"))
MAKE_SAVE_STATE_HOTKEY(true, 5,
TRANSLATE_NOOP("Hotkeys",
"Save Global State 5"))
MAKE_LOAD_STATE_HOTKEY(true, 6,
TRANSLATE_NOOP("Hotkeys",
"Load Global State 6"))
MAKE_SAVE_STATE_HOTKEY(true, 6,
TRANSLATE_NOOP("Hotkeys",
"Save Global State 6"))
MAKE_LOAD_STATE_HOTKEY(true, 7,
TRANSLATE_NOOP("Hotkeys",
"Load Global State 7"))
MAKE_SAVE_STATE_HOTKEY(
true, 7, TRANSLATE_NOOP("Hotkeys", "Save Global State 7"))
MAKE_LOAD_STATE_HOTKEY(
true, 8,
TRANSLATE_NOOP("Hotkeys", "Load Global State 8"))
MAKE_SAVE_STATE_HOTKEY(
true, 8,
TRANSLATE_NOOP("Hotkeys", "Save Global State 8"))
MAKE_LOAD_STATE_HOTKEY(
true, 9,
TRANSLATE_NOOP("Hotkeys", "Load Global State 9"))
MAKE_SAVE_STATE_HOTKEY(
true, 9,
TRANSLATE_NOOP("Hotkeys", "Save Global State 9"))
MAKE_LOAD_STATE_HOTKEY(
true, 10,
TRANSLATE_NOOP("Hotkeys",
"Load Global State 10"))
MAKE_SAVE_STATE_HOTKEY(
true, 10,
TRANSLATE_NOOP("Hotkeys",
"Save Global State 10"))
#undef MAKE_SAVE_STATE_HOTKEY
#undef MAKE_LOAD_STATE_HOTKEY
END_HOTKEY_LIST()
END_HOTKEY_LIST()

View file

@ -336,7 +336,7 @@ bool MemoryCard::SaveIfChanged(bool display_osd_message)
Host::AddIconOSDMessage(
std::move(osd_key), ICON_FA_SD_CARD,
fmt::format(TRANSLATE_FS("OSDMessage", "Failed to save memory card to '{}'."), Path::GetFileName(display_name)),
20.0f);
Host::OSD_ERROR_DURATION);
}
return false;
@ -346,7 +346,8 @@ bool MemoryCard::SaveIfChanged(bool display_osd_message)
{
Host::AddIconOSDMessage(
std::move(osd_key), ICON_FA_SD_CARD,
fmt::format(TRANSLATE_FS("OSDMessage", "Saved memory card to '{}'."), Path::GetFileName(display_name)), 5.0f);
fmt::format(TRANSLATE_FS("OSDMessage", "Saved memory card to '{}'."), Path::GetFileName(display_name)),
Host::OSD_QUICK_DURATION);
}
return true;

View file

@ -2935,12 +2935,12 @@ void System::DoToggleCheats()
}
cl->SetMasterEnable(!cl->GetMasterEnable());
Host::AddKeyedOSDMessage(
"ToggleCheats",
Host::AddIconOSDMessage(
"ToggleCheats", ICON_FA_EXCLAMATION_TRIANGLE,
cl->GetMasterEnable() ?
fmt::format(TRANSLATE_FS("OSDMessage", "{} cheats are now active."), cl->GetEnabledCodeCount()) :
fmt::format(TRANSLATE_FS("OSDMessage", "{} cheats are now inactive."), cl->GetEnabledCodeCount()),
10.0f);
TRANSLATE_PLURAL_STR("System", "%n cheat(s) are now active.", "", cl->GetEnabledCodeCount()) :
TRANSLATE_PLURAL_STR("System", "%n cheat(s) are now inactive.", "", cl->GetEnabledCodeCount()),
Host::OSD_QUICK_DURATION);
}
static bool LoadEXEToRAM(const char* filename, bool patch_bios)
@ -3993,25 +3993,26 @@ void System::WarnAboutUnsafeSettings()
if (g_settings.cpu_overclock_active)
{
append(ICON_FA_MICROCHIP,
fmt::format(TRANSLATE_FS("System", "CPU clock speed is set to {}% ({} / {}). This may crash games."),
g_settings.GetCPUOverclockPercent(), g_settings.cpu_overclock_numerator,
g_settings.cpu_overclock_denominator));
append(
ICON_FA_MICROCHIP,
SmallString::from_format(TRANSLATE_FS("System", "CPU clock speed is set to {}% ({} / {}). This may crash games."),
g_settings.GetCPUOverclockPercent(), g_settings.cpu_overclock_numerator,
g_settings.cpu_overclock_denominator));
}
if (g_settings.cdrom_read_speedup > 1)
{
append(
ICON_FA_COMPACT_DISC,
fmt::format(TRANSLATE_FS("System", "CD-ROM read speedup set to {}x (effective speed {}x). This may crash games."),
g_settings.cdrom_read_speedup, g_settings.cdrom_read_speedup * 2));
append(ICON_FA_COMPACT_DISC,
SmallString::from_format(
TRANSLATE_FS("System", "CD-ROM read speedup set to {}x (effective speed {}x). This may crash games."),
g_settings.cdrom_read_speedup, g_settings.cdrom_read_speedup * 2));
}
if (g_settings.cdrom_seek_speedup != 1)
{
append(ICON_FA_COMPACT_DISC,
fmt::format(TRANSLATE_FS("System", "CD-ROM seek speedup set to {}. This may crash games."),
(g_settings.cdrom_seek_speedup == 0) ?
TinyString(TRANSLATE_SV("System", "Instant")) :
TinyString::from_format("{}x", g_settings.cdrom_seek_speedup)));
SmallString::from_format(TRANSLATE_FS("System", "CD-ROM seek speedup set to {}. This may crash games."),
(g_settings.cdrom_seek_speedup == 0) ?
TinyString(TRANSLATE_SV("System", "Instant")) :
TinyString::from_format("{}x", g_settings.cdrom_seek_speedup)));
}
if (g_settings.gpu_force_ntsc_timings)
{
@ -4030,8 +4031,8 @@ void System::WarnAboutUnsafeSettings()
if (s_cheat_list && s_cheat_list->GetEnabledCodeCount() > 0)
{
append(ICON_FA_EXCLAMATION_TRIANGLE,
fmt::format(TRANSLATE_FS("System", "{} cheats are enabled. This may crash games."),
s_cheat_list->GetEnabledCodeCount()));
TRANSLATE_PLURAL_STR("System", "%n cheat(s) are enabled. This may crash games.", "",
s_cheat_list->GetEnabledCodeCount()));
}
if (!messages.empty())

View file

@ -173,6 +173,11 @@ s32 Host::Internal::GetTranslatedStringImpl(std::string_view context, std::strin
return static_cast<s32>(translated_size);
}
std::string Host::TranslatePluralToString(const char* context, const char* msg, const char* disambiguation, int count)
{
return qApp->translate(context, msg, disambiguation, count).toStdString();
}
std::span<const std::pair<const char*, const char*>> Host::GetAvailableLanguageList()
{
static constexpr const std::pair<const char*, const char*> languages[] = {{"English", "en"},

View file

@ -66,7 +66,7 @@ REM A good .ts file has been passed
ECHO Updating %filename%...
ECHO.
SET "linguist=..\..\..\dep\msvc\deps-x64\bin"
SET "context=.././ ../../core/ ../../util/ -tr-function-alias QT_TRANSLATE_NOOP+=TRANSLATE,QT_TRANSLATE_NOOP+=TRANSLATE_SV,QT_TRANSLATE_NOOP+=TRANSLATE_STR,QT_TRANSLATE_NOOP+=TRANSLATE_FS,QT_TRANSLATE_N_NOOP3+=TRANSLATE_FMT,QT_TRANSLATE_NOOP+=TRANSLATE_NOOP"
SET "context=.././ ../../core/ ../../util/ -tr-function-alias QT_TRANSLATE_NOOP+=TRANSLATE,QT_TRANSLATE_NOOP+=TRANSLATE_SV,QT_TRANSLATE_NOOP+=TRANSLATE_STR,QT_TRANSLATE_NOOP+=TRANSLATE_FS,QT_TRANSLATE_N_NOOP3+=TRANSLATE_FMT,QT_TRANSLATE_NOOP+=TRANSLATE_NOOP,translate+=TRANSLATE_PLURAL_STR,translate+=TRANSLATE_PLURAL_FS"
"%linguist%\lupdate.exe" %context% -ts %filename%
ECHO.

View file

@ -7,17 +7,46 @@
<location filename="../achievementsettingswidget.cpp" line="164"/>
<location filename="../achievementsettingswidget.cpp" line="171"/>
<source>%n seconds</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
<translation>
<numerusform>%n second</numerusform>
<numerusform>%n seconds</numerusform>
</translation>
</message>
</context>
<context>
<name>EmuThread</name>
<name>Achievements</name>
<message numerus="yes">
<location filename="../../core/achievements.cpp" line="1022"/>
<source>You have unlocked {} of %n achievements</source>
<comment>Achievement popup</comment>
<translation>
<numerusform>You have unlocked {} of %n achievements</numerusform>
<numerusform>You have unlocked {} of %n achievements</numerusform>
</translation>
</message>
<message numerus="yes">
<location filename="../../core/achievements.cpp" line="1025"/>
<source>and earned {} of %n points</source>
<comment>Achievement popup</comment>
<translation>
<numerusform>and earned {} of %n points</numerusform>
<numerusform>and earned {} of %n points</numerusform>
</translation>
</message>
<message numerus="yes">
<location filename="../../core/achievements.cpp" line="1100"/>
<source>%n achievements</source>
<comment>Mastery popup</comment>
<translation>
<numerusform>%n achievement</numerusform>
<numerusform>%n achievements</numerusform>
</translation>
</message>
<message numerus="yes">
<location filename="../../core/achievements.cpp" line="1102"/>
<source>%n points</source>
<translation type="vanished">
<comment>Mastery popup</comment>
<translation>
<numerusform>%n point</numerusform>
<numerusform>%n points</numerusform>
</translation>
@ -26,7 +55,7 @@
<context>
<name>EmulationSettingsWidget</name>
<message numerus="yes">
<location filename="../emulationsettingswidget.cpp" line="196"/>
<location filename="../emulationsettingswidget.cpp" line="242"/>
<source>Rewind for %n frame(s), lasting %1 second(s) will require up to %2MB of RAM and %3MB of VRAM.</source>
<translation>
<numerusform>Rewind for %n frame, lasting %1 second(s) will require up to %2MB of RAM and %3MB of VRAM.</numerusform>
@ -34,6 +63,17 @@
</translation>
</message>
</context>
<context>
<name>GameList</name>
<message numerus="yes">
<location filename="../../core/game_list.cpp" line="1070"/>
<source>%n minutes</source>
<translation>
<numerusform>%n minute</numerusform>
<numerusform>%n minutes</numerusform>
</translation>
</message>
</context>
<context>
<name>InputBindingWidget</name>
<message numerus="yes">
@ -46,9 +86,9 @@
</message>
</context>
<context>
<name>MemoryCardEditorDialog</name>
<name>MemoryCardEditorWindow</name>
<message numerus="yes">
<location filename="../memorycardeditordialog.cpp" line="296"/>
<location filename="../memorycardeditorwindow.cpp" line="301"/>
<source>%n block(s) free%1</source>
<translation>
<numerusform>%n block free%1</numerusform>
@ -57,33 +97,29 @@
</message>
</context>
<context>
<name>OSDMessage</name>
<name>System</name>
<message numerus="yes">
<source>%n cheats are now active.</source>
<translation type="vanished">
<location filename="../../core/system.cpp" line="2941"/>
<source>%n cheat(s) are now active.</source>
<translation>
<numerusform>%n cheat is now active.</numerusform>
<numerusform>%n cheats are now active.</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n cheats are now inactive.</source>
<translation type="vanished">
<location filename="../../core/system.cpp" line="2942"/>
<source>%n cheat(s) are now inactive.</source>
<translation>
<numerusform>%n cheat is now inactive.</numerusform>
<numerusform>%n cheats are now inactive.</numerusform>
</translation>
</message>
<message numerus="yes">
<source>Saved %n cheats to &apos;%s&apos;.</source>
<translation type="vanished">
<numerusform>Saved %n cheat to &apos;%s&apos;.</numerusform>
<numerusform>Saved %n cheats to &apos;%s&apos;.</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n cheats are enabled. This may result in instability.</source>
<translation type="vanished">
<numerusform>%n cheat is enabled. This may result in instability.</numerusform>
<numerusform>%n cheats are enabled. This may result in instability.</numerusform>
<location filename="../../core/system.cpp" line="4034"/>
<source>%n cheat(s) are enabled. This may crash games.</source>
<translation>
<numerusform>%n cheat is enabled. This may crash games.</numerusform>
<numerusform>%n cheats are enabled. This may crash games.</numerusform>
</translation>
</message>
</context>

View file

@ -1,7 +1,7 @@
@echo off
set "linguist=..\..\..\dep\msvc\deps-x64\bin"
set context=../ ../../core/ ../../util/ -tr-function-alias QT_TRANSLATE_NOOP+=TRANSLATE,QT_TRANSLATE_NOOP+=TRANSLATE_SV,QT_TRANSLATE_NOOP+=TRANSLATE_STR,QT_TRANSLATE_NOOP+=TRANSLATE_FS,QT_TRANSLATE_N_NOOP3+=TRANSLATE_FMT,QT_TRANSLATE_NOOP+=TRANSLATE_NOOP -pluralonly
set context=../ ../../core/ ../../util/ -tr-function-alias QT_TRANSLATE_NOOP+=TRANSLATE,QT_TRANSLATE_NOOP+=TRANSLATE_SV,QT_TRANSLATE_NOOP+=TRANSLATE_STR,QT_TRANSLATE_NOOP+=TRANSLATE_FS,QT_TRANSLATE_N_NOOP3+=TRANSLATE_FMT,QT_TRANSLATE_NOOP+=TRANSLATE_NOOP,translate+=TRANSLATE_PLURAL_STR,translate+=TRANSLATE_PLURAL_FS -pluralonly -no-obsolete
"%linguist%\lupdate.exe" %context% -ts duckstation-qt_en.ts
pause

View file

@ -3,7 +3,7 @@
if not defined lang (echo Please set your language first & pause & exit)
set "linguist=..\..\..\dep\msvc\deps-x64\bin"
SET "context=.././ ../../core/ ../../util/ -tr-function-alias QT_TRANSLATE_NOOP+=TRANSLATE,QT_TRANSLATE_NOOP+=TRANSLATE_SV,QT_TRANSLATE_NOOP+=TRANSLATE_STR,QT_TRANSLATE_NOOP+=TRANSLATE_FS,QT_TRANSLATE_N_NOOP3+=TRANSLATE_FMT,QT_TRANSLATE_NOOP+=TRANSLATE_NOOP"
SET "context=.././ ../../core/ ../../util/ -tr-function-alias QT_TRANSLATE_NOOP+=TRANSLATE,QT_TRANSLATE_NOOP+=TRANSLATE_SV,QT_TRANSLATE_NOOP+=TRANSLATE_STR,QT_TRANSLATE_NOOP+=TRANSLATE_FS,QT_TRANSLATE_N_NOOP3+=TRANSLATE_FMT,QT_TRANSLATE_NOOP+=TRANSLATE_NOOP,translate+=TRANSLATE_PLURAL_STR,translate+=TRANSLATE_PLURAL_FS"
"%linguist%\lupdate.exe" %context% -noobsolete -ts duckstation-qt_%lang%.ts
pause

View file

@ -178,6 +178,23 @@ s32 Host::Internal::GetTranslatedStringImpl(std::string_view context, std::strin
return static_cast<s32>(msg.size());
}
std::string Host::TranslatePluralToString(const char* context, const char* msg, const char* disambiguation, int count)
{
TinyString count_str = TinyString::from_format("{}", count);
std::string ret(msg);
for (;;)
{
std::string::size_type pos = ret.find("%n");
if (pos == std::string::npos)
break;
ret.replace(pos, pos + 2, count_str.view());
}
return ret;
}
void Host::LoadSettings(SettingsInterface& si, std::unique_lock<std::mutex>& lock)
{
}

View file

@ -59,6 +59,9 @@ std::string_view TranslateToStringView(std::string_view context, std::string_vie
/// Returns a localized version of the specified string within the specified context.
std::string TranslateToString(std::string_view context, std::string_view msg);
/// Returns a localized version of the specified string within the specified context, adjusting for plurals using %n.
std::string TranslatePluralToString(const char* context, const char* msg, const char* disambiguation, int count);
/// Clears the translation cache. All previously used strings should be considered invalid.
void ClearTranslationCache();
@ -73,6 +76,10 @@ s32 GetTranslatedStringImpl(std::string_view context, std::string_view msg, char
#define TRANSLATE_SV(context, msg) Host::TranslateToStringView(context, msg)
#define TRANSLATE_STR(context, msg) Host::TranslateToString(context, msg)
#define TRANSLATE_FS(context, msg) fmt::runtime(Host::TranslateToStringView(context, msg))
#define TRANSLATE_PLURAL_STR(context, msg, disambiguation, count) \
Host::TranslatePluralToString(context, msg, disambiguation, count)
#define TRANSLATE_PLURAL_FS(context, msg, disambiguation, count) \
fmt::runtime(Host::TranslatePluralToString(context, msg, disambiguation, count))
// Does not translate the string at runtime, but allows the UI to in its own way.
#define TRANSLATE_NOOP(context, msg) msg