mirror of https://github.com/PCSX2/pcsx2.git
parent
3a0b26225d
commit
cfecbf53aa
|
@ -8,4 +8,4 @@ set -e
|
|||
# for just updating translations. Saves building it for this action alone.
|
||||
"$SCRIPTDIR/../../../../tools/retry.sh" sudo apt-get -y install qt6-l10n-tools
|
||||
|
||||
PATH=/usr/lib/qt6/bin:$PATH "$SCRIPTDIR/../../../../pcsx2-qt/Translations/update_en_translation.sh"
|
||||
PATH=/usr/lib/qt6/bin:$PATH "$SCRIPTDIR/../../../../pcsx2-qt/Translations/update_base_translation.sh"
|
||||
|
|
|
@ -743,6 +743,23 @@ s32 Host::Internal::GetTranslatedStringImpl(
|
|||
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;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Platform specific code
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -259,6 +259,17 @@ int GameListModel::columnCount(const QModelIndex& parent) const
|
|||
return Column_Count;
|
||||
}
|
||||
|
||||
QString GameListModel::formatTimespan(time_t timespan)
|
||||
{
|
||||
// avoid an extra string conversion
|
||||
const u32 hours = static_cast<u32>(timespan / 3600);
|
||||
const u32 minutes = static_cast<u32>((timespan % 3600) / 60);
|
||||
if (hours > 0)
|
||||
return qApp->translate("GameList", "%n hours", "", hours);
|
||||
else
|
||||
return qApp->translate("GameList", "%n minutes", "", minutes);
|
||||
}
|
||||
|
||||
QVariant GameListModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
|
@ -296,7 +307,7 @@ QVariant GameListModel::data(const QModelIndex& index, int role) const
|
|||
if (ge->total_played_time == 0)
|
||||
return {};
|
||||
else
|
||||
return QString::fromStdString(GameList::FormatTimespan(ge->total_played_time, true));
|
||||
return formatTimespan(ge->total_played_time);
|
||||
}
|
||||
|
||||
case Column_LastPlayed:
|
||||
|
|
|
@ -82,6 +82,8 @@ private:
|
|||
void loadOrGenerateCover(const GameList::Entry* ge);
|
||||
void invalidateCoverForPath(const std::string& path);
|
||||
|
||||
static QString formatTimespan(time_t timespan);
|
||||
|
||||
float m_cover_scale = 0.0f;
|
||||
std::atomic<u32> m_cover_scale_counter{0};
|
||||
bool m_show_titles_for_covers = false;
|
||||
|
|
|
@ -95,7 +95,7 @@ static QString getSystemLanguage()
|
|||
}
|
||||
// No matches :(
|
||||
Console.Warning("Couldn't find translation for system language %s, using en instead", locale.toStdString().c_str());
|
||||
return QStringLiteral("en");
|
||||
return QStringLiteral("en-US");
|
||||
}
|
||||
|
||||
void QtHost::InstallTranslator(QWidget* dialog_parent)
|
||||
|
@ -213,6 +213,11 @@ s32 Host::Internal::GetTranslatedStringImpl(
|
|||
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::vector<std::pair<QString, QString>> QtHost::GetAvailableLanguageList()
|
||||
{
|
||||
return {
|
||||
|
@ -224,7 +229,7 @@ std::vector<std::pair<QString, QString>> QtHost::GetAvailableLanguageList()
|
|||
{QStringLiteral("Dansk (da-DK)"), QStringLiteral("da-DK")},
|
||||
{QStringLiteral("Deutsch (de-DE)"), QStringLiteral("de-DE")},
|
||||
{QStringLiteral("Ελληνικά (el-GR)"), QStringLiteral("el-GR")},
|
||||
{QStringLiteral("English (en)"), QStringLiteral("en")},
|
||||
{QStringLiteral("English (en)"), QStringLiteral("en-US")},
|
||||
{QStringLiteral("Español (Hispanoamérica) (es-419)"), QStringLiteral("es-419")},
|
||||
{QStringLiteral("Español (España) (es-ES)"), QStringLiteral("es-ES")},
|
||||
{QStringLiteral("فارسی (fa-IR)"), QStringLiteral("fa-IR")},
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1" language="en_US" sourcelanguage="en_US">
|
||||
<context>
|
||||
<name>AchievementSettingsWidget</name>
|
||||
<message numerus="yes">
|
||||
<location filename="../Settings/AchievementSettingsWidget.cpp" line="134"/>
|
||||
<location filename="../Settings/AchievementSettingsWidget.cpp" line="141"/>
|
||||
<source>%n seconds</source>
|
||||
<translation>
|
||||
<numerusform>%n second</numerusform>
|
||||
<numerusform>%n seconds</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Achievements</name>
|
||||
<message numerus="yes">
|
||||
<location filename="../../pcsx2/Achievements.cpp" line="1021"/>
|
||||
<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="../../pcsx2/Achievements.cpp" line="1024"/>
|
||||
<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="../../pcsx2/Achievements.cpp" line="1109"/>
|
||||
<source>%n achievements</source>
|
||||
<comment>Mastery popup</comment>
|
||||
<translation>
|
||||
<numerusform>%n achievement</numerusform>
|
||||
<numerusform>%n achievements</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<location filename="../../pcsx2/Achievements.cpp" line="1111"/>
|
||||
<source>%n points</source>
|
||||
<comment>Mastery popup</comment>
|
||||
<translation>
|
||||
<numerusform>%n point</numerusform>
|
||||
<numerusform>%n points</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameList</name>
|
||||
<message numerus="yes">
|
||||
<location filename="../GameList/GameListModel.cpp" line="268"/>
|
||||
<location filename="../../pcsx2/GameList.cpp" line="1142"/>
|
||||
<source>%n hours</source>
|
||||
<translation>
|
||||
<numerusform>%n hour</numerusform>
|
||||
<numerusform>%n hours</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<location filename="../GameList/GameListModel.cpp" line="270"/>
|
||||
<location filename="../../pcsx2/GameList.cpp" line="1144"/>
|
||||
<source>%n minutes</source>
|
||||
<translation>
|
||||
<numerusform>%n minute</numerusform>
|
||||
<numerusform>%n minutes</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>InputBindingWidget</name>
|
||||
<message numerus="yes">
|
||||
<location filename="../Settings/InputBindingWidget.cpp" line="73"/>
|
||||
<source>%n bindings</source>
|
||||
<translation>
|
||||
<numerusform>%n binding</numerusform>
|
||||
<numerusform>%n bindings</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Patch</name>
|
||||
<message numerus="yes">
|
||||
<location filename="../../pcsx2/Patch.cpp" line="698"/>
|
||||
<source>%n GameDB patches are active.</source>
|
||||
<comment>OSD Message</comment>
|
||||
<translation>
|
||||
<numerusform>%n GameDB patch is active.</numerusform>
|
||||
<numerusform>%n GameDB patches are active.</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<location filename="../../pcsx2/Patch.cpp" line="705"/>
|
||||
<source>%n game patches are active.</source>
|
||||
<comment>OSD Message</comment>
|
||||
<translation>
|
||||
<numerusform>%n game patch is active.</numerusform>
|
||||
<numerusform>%n game patches are active.</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<location filename="../../pcsx2/Patch.cpp" line="712"/>
|
||||
<source>%n cheat patches are active.</source>
|
||||
<comment>OSD Message</comment>
|
||||
<translation>
|
||||
<numerusform>%n cheat patch is active.</numerusform>
|
||||
<numerusform>%n cheat patches are active.</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,10 @@
|
|||
@echo off
|
||||
|
||||
set QTBIN=..\..\deps\bin
|
||||
set SRCDIRS=../ ../../pcsx2/
|
||||
|
||||
set OPTS=-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
|
||||
|
||||
"%QTBIN%\lupdate.exe" %SRCDIRS% %OPTS% -no-obsolete -source-language en -ts pcsx2-qt_en.ts
|
||||
|
||||
pause
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
|
||||
|
||||
OPTS="-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"
|
||||
SRCDIRS=$(realpath "$SCRIPTDIR/..")/\ $(realpath "$SCRIPTDIR/../../pcsx2")/
|
||||
OUTDIR=$(realpath "$SCRIPTDIR")
|
||||
|
||||
lupdate $SRCDIRS $OPTS -no-obsolete -source-language en -ts "$OUTDIR/pcsx2-qt_en.ts"
|
|
@ -3,8 +3,7 @@
|
|||
set QTBIN=..\..\deps\bin
|
||||
set SRCDIRS=../ ../../pcsx2/
|
||||
|
||||
set OPTS=-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 OPTS=-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
|
||||
|
||||
"%QTBIN%\lupdate.exe" %SRCDIRS% %OPTS% -no-obsolete -source-language en -ts pcsx2-qt_en.ts
|
||||
|
||||
pause
|
||||
"%QTBIN%\lupdate.exe" %SRCDIRS% %OPTS% -no-obsolete -source-language en_US -ts pcsx2-qt_en-US.ts
|
||||
start %QTBIN%\linguist.exe %~dp0\pcsx2-qt_en-US.ts
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
|
||||
|
||||
OPTS="-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"
|
||||
OPTS="-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"
|
||||
SRCDIRS=$(realpath "$SCRIPTDIR/..")/\ $(realpath "$SCRIPTDIR/../../pcsx2")/
|
||||
OUTDIR=$(realpath "$SCRIPTDIR")
|
||||
|
||||
lupdate $SRCDIRS $OPTS -no-obsolete -source-language en -ts "$OUTDIR/pcsx2-qt_en.ts"
|
||||
lupdate $SRCDIRS $OPTS -no-obsolete -source-language en_US -ts "$OUTDIR/pcsx2-qt_en-US.ts"
|
||||
|
|
|
@ -1016,9 +1016,14 @@ void Achievements::DisplayAchievementSummary()
|
|||
std::string summary;
|
||||
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);
|
||||
summary = fmt::format(
|
||||
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
|
||||
{
|
||||
|
@ -1099,8 +1104,11 @@ void Achievements::HandleGameCompleteEvent(const rc_client_event_t* event)
|
|||
if (EmuConfig.Achievements.Notifications)
|
||||
{
|
||||
std::string title = fmt::format(TRANSLATE_FS("Achievements", "Mastered {}"), s_game_title);
|
||||
std::string message = fmt::format(TRANSLATE_FS("Achievements", "{0} achievements, {1} 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));
|
||||
|
||||
MTGS::RunOnGSThread([title = std::move(title), message = std::move(message), icon = s_game_icon]() {
|
||||
if (ImGuiManager::InitializeFullscreenUI())
|
||||
|
|
|
@ -1139,9 +1139,9 @@ std::string GameList::FormatTimespan(std::time_t timespan, bool long_format)
|
|||
else
|
||||
{
|
||||
if (hours > 0)
|
||||
ret = fmt::format(TRANSLATE_FS("GameList", "{} hours"), hours);
|
||||
ret.assign(TRANSLATE_PLURAL_STR("GameList", "%n hours", "", hours));
|
||||
else
|
||||
ret = fmt::format(TRANSLATE_FS("GameList", "{} minutes"), minutes);
|
||||
ret.assign(TRANSLATE_PLURAL_STR("GameList", "%n minutes", "", minutes));
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -42,6 +42,9 @@ namespace Host
|
|||
/// Returns a localized version of the specified string within the specified context.
|
||||
std::string TranslateToString(const std::string_view& context, const 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();
|
||||
|
||||
|
@ -164,6 +167,10 @@ namespace Host
|
|||
#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
|
||||
|
|
|
@ -93,10 +93,9 @@ 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::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;
|
||||
}
|
||||
|
|
|
@ -689,27 +689,27 @@ void Patch::UpdateActivePatches(bool reload_enabled_list, bool verbose, bool ver
|
|||
s_override_aspect_ratio.reset();
|
||||
s_override_interlace_mode.reset();
|
||||
|
||||
std::string message;
|
||||
SmallString message;
|
||||
u32 gp_count = 0;
|
||||
if (EmuConfig.EnablePatches)
|
||||
{
|
||||
gp_count = EnablePatches(s_gamedb_patches, EnablePatchList());
|
||||
if (gp_count > 0)
|
||||
fmt::format_to(std::back_inserter(message), TRANSLATE_FS("Patch", "{} GameDB patches"), gp_count);
|
||||
message.append(TRANSLATE_PLURAL_STR("Patch", "%n GameDB patches are active.", "OSD Message", gp_count));
|
||||
}
|
||||
|
||||
const u32 p_count = EnablePatches(s_game_patches, s_enabled_patches);
|
||||
if (p_count > 0)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(message), TRANSLATE_FS("Patch", "{}{} game patches"),
|
||||
message.empty() ? "" : ", ", p_count);
|
||||
message.append_format("{}{}", message.empty() ? "" : "\n",
|
||||
TRANSLATE_PLURAL_STR("Patch", "%n game patches are active.", "OSD Message", p_count));
|
||||
}
|
||||
|
||||
const u32 c_count = EmuConfig.EnableCheats ? EnablePatches(s_cheat_patches, s_enabled_cheats) : 0;
|
||||
if (c_count > 0)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(message), TRANSLATE_FS("Patch", "{}{} cheat patches"),
|
||||
message.empty() ? "" : ", ", c_count);
|
||||
message.append_format("{}{}", message.empty() ? "" : "\n",
|
||||
TRANSLATE_PLURAL_STR("Patch", "%n cheat patches are active.", "OSD Message", c_count));
|
||||
}
|
||||
|
||||
// Display message on first boot when we load patches.
|
||||
|
@ -719,8 +719,7 @@ void Patch::UpdateActivePatches(bool reload_enabled_list, bool verbose, bool ver
|
|||
{
|
||||
if (!message.empty())
|
||||
{
|
||||
Host::AddIconOSDMessage("LoadPatches", ICON_FA_BAND_AID,
|
||||
fmt::format(TRANSLATE_FS("Patch", "{} are active."), message), Host::OSD_INFO_DURATION);
|
||||
Host::AddIconOSDMessage("LoadPatches", ICON_FA_BAND_AID, message, Host::OSD_INFO_DURATION);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -191,6 +191,23 @@ s32 Host::Internal::GetTranslatedStringImpl(
|
|||
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::OnAchievementsLoginRequested(Achievements::LoginRequestReason reason)
|
||||
{
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue