Added localization support to parts of the application

This commit is contained in:
Leon Styhre 2024-07-15 18:38:23 +02:00
parent 4ffc5d6bf9
commit d0605ea650
3 changed files with 185 additions and 164 deletions

View file

@ -13,6 +13,7 @@
#include "Log.h" #include "Log.h"
#include "Settings.h" #include "Settings.h"
#include "resources/ResourceManager.h" #include "resources/ResourceManager.h"
#include "utils/LocalizationUtil.h"
#include "utils/StringUtil.h" #include "utils/StringUtil.h"
#include "utils/TimeUtil.h" #include "utils/TimeUtil.h"
@ -198,8 +199,11 @@ void ApplicationUpdater::update()
return; return;
// Everything else is some sort of error. // Everything else is some sort of error.
std::string errorMessage {"Network error (status: "}; std::string errorMessage {_("Network error (status:")};
errorMessage.append(std::to_string(reqStatus)).append(") - ").append(mRequest->getErrorMsg()); errorMessage.append(" ")
.append(std::to_string(reqStatus))
.append(") - ")
.append(mRequest->getErrorMsg());
throw std::runtime_error(errorMessage); throw std::runtime_error(errorMessage);
} }
@ -435,21 +439,25 @@ void ApplicationUpdater::compareVersions()
.append("), release date: ") .append("), release date: ")
.append(releaseType->date); .append(releaseType->date);
mResults.append("New ");
if (releaseType == &mPrerelease) { if (releaseType == &mPrerelease) {
mResults.append("prerelease available:\n") mResults.append(_("New prerelease available:"))
.append("\n")
.append(releaseType->version) .append(releaseType->version)
.append(" (") .append(" (")
.append(releaseType->date) .append(releaseType->date)
.append(")"); .append(")");
} }
else { else {
mResults.append("release available: ").append(releaseType->version); mResults.append(_("New release available:"))
.append(" ")
.append(releaseType->version);
} }
if (mPackageType == PackageType::UNKNOWN) if (mPackageType == PackageType::UNKNOWN)
mResults.append("\nFor more information visit\n").append("https://es-de.org"); mResults.append("\n")
.append(_("For more information visit"))
.append("\n")
.append("https://es-de.org");
if (mPackage.message != "") if (mPackage.message != "")
mResults.append("\n").append(mPackage.message); mResults.append("\n").append(mPackage.message);

View file

@ -12,6 +12,7 @@
#include "ApplicationVersion.h" #include "ApplicationVersion.h"
#include "guis/GuiTextEditKeyboardPopup.h" #include "guis/GuiTextEditKeyboardPopup.h"
#include "guis/GuiTextEditPopup.h" #include "guis/GuiTextEditPopup.h"
#include "utils/LocalizationUtil.h"
#include "utils/PlatformUtil.h" #include "utils/PlatformUtil.h"
#include <SDL2/SDL_timer.h> #include <SDL2/SDL_timer.h>
@ -42,17 +43,17 @@ GuiApplicationUpdater::GuiApplicationUpdater()
setDownloadPath(); setDownloadPath();
// Set up grid. // Set up grid.
mTitle = std::make_shared<TextComponent>("APPLICATION UPDATER", Font::get(FONT_SIZE_LARGE), mTitle = std::make_shared<TextComponent>(_("APPLICATION UPDATER"), Font::get(FONT_SIZE_LARGE),
mMenuColorTitle, ALIGN_CENTER); mMenuColorTitle, ALIGN_CENTER);
mGrid.setEntry(mTitle, glm::ivec2 {0, 0}, false, true, glm::ivec2 {4, 1}, mGrid.setEntry(mTitle, glm::ivec2 {0, 0}, false, true, glm::ivec2 {4, 1},
GridFlags::BORDER_BOTTOM); GridFlags::BORDER_BOTTOM);
mStatusHeader = std::make_shared<TextComponent>( mStatusHeader = std::make_shared<TextComponent>(
"INSTALLATION STEPS:", Font::get(FONT_SIZE_MINI), mMenuColorPrimary, ALIGN_LEFT); _("INSTALLATION STEPS:"), Font::get(FONT_SIZE_MINI), mMenuColorPrimary, ALIGN_LEFT);
mGrid.setEntry(mStatusHeader, glm::ivec2 {1, 1}, false, true, glm::ivec2 {2, 1}); mGrid.setEntry(mStatusHeader, glm::ivec2 {1, 1}, false, true, glm::ivec2 {2, 1});
const std::string step1Text {mLinuxAppImage ? "DOWNLOAD NEW RELEASE" : const std::string step1Text {mLinuxAppImage ? _("DOWNLOAD NEW RELEASE") :
"DOWNLOAD NEW RELEASE TO THIS DIRECTORY:"}; _("DOWNLOAD NEW RELEASE TO THIS DIRECTORY:")};
mProcessStep1 = std::make_shared<TextComponent>(step1Text, Font::get(FONT_SIZE_MEDIUM), mProcessStep1 = std::make_shared<TextComponent>(step1Text, Font::get(FONT_SIZE_MEDIUM),
mMenuColorPrimary, ALIGN_LEFT); mMenuColorPrimary, ALIGN_LEFT);
mGrid.setEntry(mProcessStep1, glm::ivec2 {1, 2}, false, true, glm::ivec2 {2, 1}); mGrid.setEntry(mProcessStep1, glm::ivec2 {1, 2}, false, true, glm::ivec2 {2, 1});
@ -62,21 +63,21 @@ GuiApplicationUpdater::GuiApplicationUpdater()
Utils::String::replace(Utils::FileSystem::getParent(mDownloadPackageFilename), "/", "\\")}; Utils::String::replace(Utils::FileSystem::getParent(mDownloadPackageFilename), "/", "\\")};
#else #else
const std::string step2Text {mLinuxAppImage ? const std::string step2Text {mLinuxAppImage ?
"INSTALL PACKAGE" : _("INSTALL PACKAGE") :
Utils::FileSystem::getParent(mDownloadPackageFilename)}; Utils::FileSystem::getParent(mDownloadPackageFilename)};
#endif #endif
mProcessStep2 = std::make_shared<TextComponent>(step2Text, Font::get(FONT_SIZE_MEDIUM), mProcessStep2 = std::make_shared<TextComponent>(step2Text, Font::get(FONT_SIZE_MEDIUM),
mMenuColorPrimary, ALIGN_LEFT); mMenuColorPrimary, ALIGN_LEFT);
mGrid.setEntry(mProcessStep2, glm::ivec2 {1, 3}, false, true, glm::ivec2 {2, 1}); mGrid.setEntry(mProcessStep2, glm::ivec2 {1, 3}, false, true, glm::ivec2 {2, 1});
const std::string step3Text {mLinuxAppImage ? "QUIT AND MANUALLY RESTART ES-DE" : const std::string step3Text {mLinuxAppImage ? _("QUIT AND MANUALLY RESTART ES-DE") :
"QUIT AND MANUALLY UPGRADE ES-DE"}; _("QUIT AND MANUALLY UPGRADE ES-DE")};
mProcessStep3 = std::make_shared<TextComponent>(step3Text, Font::get(FONT_SIZE_MEDIUM), mProcessStep3 = std::make_shared<TextComponent>(step3Text, Font::get(FONT_SIZE_MEDIUM),
mMenuColorPrimary, ALIGN_LEFT); mMenuColorPrimary, ALIGN_LEFT);
mGrid.setEntry(mProcessStep3, glm::ivec2 {1, 4}, false, true, glm::ivec2 {2, 1}); mGrid.setEntry(mProcessStep3, glm::ivec2 {1, 4}, false, true, glm::ivec2 {2, 1});
mStatusMessageHeader = std::make_shared<TextComponent>( mStatusMessageHeader = std::make_shared<TextComponent>(
"STATUS MESSAGE:", Font::get(FONT_SIZE_MINI), mMenuColorPrimary, ALIGN_LEFT); _("STATUS MESSAGE:"), Font::get(FONT_SIZE_MINI), mMenuColorPrimary, ALIGN_LEFT);
mGrid.setEntry(mStatusMessageHeader, glm::ivec2 {1, 6}, false, true, glm::ivec2 {2, 1}); mGrid.setEntry(mStatusMessageHeader, glm::ivec2 {1, 6}, false, true, glm::ivec2 {2, 1});
mStatusMessage = std::make_shared<TextComponent>("", Font::get(FONT_SIZE_SMALL), mStatusMessage = std::make_shared<TextComponent>("", Font::get(FONT_SIZE_SMALL),
@ -90,32 +91,34 @@ GuiApplicationUpdater::GuiApplicationUpdater()
// Buttons. // Buttons.
std::vector<std::shared_ptr<ButtonComponent>> buttons; std::vector<std::shared_ptr<ButtonComponent>> buttons;
mButton1 = std::make_shared<ButtonComponent>("DOWNLOAD", "download new release", [this]() { mButton1 =
if (!mDownloading) { std::make_shared<ButtonComponent>(_("DOWNLOAD"), _("download new release"), [this]() {
if (!mLinuxAppImage) { if (!mDownloading) {
if (!Utils::FileSystem::exists( if (!mLinuxAppImage) {
Utils::FileSystem::getParent(mDownloadPackageFilename))) { if (!Utils::FileSystem::exists(
mMessage = "Download directory does not exist"; Utils::FileSystem::getParent(mDownloadPackageFilename))) {
return; mMessage = _("Download directory does not exist");
return;
}
} }
mMessage = "";
mStatusMessage->setText(mMessage);
mDownloadPercentage = 0;
mDownloading = true;
if (mThread) {
mThread->join();
mThread.reset();
}
mThread =
std::make_unique<std::thread>(&GuiApplicationUpdater::downloadPackage, this);
} }
mMessage = ""; });
mStatusMessage->setText(mMessage);
mDownloadPercentage = 0;
mDownloading = true;
if (mThread) {
mThread->join();
mThread.reset();
}
mThread = std::make_unique<std::thread>(&GuiApplicationUpdater::downloadPackage, this);
}
});
buttons.push_back(mButton1); buttons.push_back(mButton1);
if (!mLinuxAppImage) { if (!mLinuxAppImage) {
mButton2 = std::make_shared<ButtonComponent>( mButton2 = std::make_shared<ButtonComponent>(
"CHANGE DIRECTORY", "change download directory", [this]() { _("CHANGE DIRECTORY"), _("change download directory"), [this]() {
if (mDownloading || mHasDownloaded) if (mDownloading || mHasDownloaded)
return; return;
#if defined(_WIN64) #if defined(_WIN64)
@ -156,40 +159,40 @@ GuiApplicationUpdater::GuiApplicationUpdater()
}; };
if (Settings::getInstance()->getBool("VirtualKeyboard")) { if (Settings::getInstance()->getBool("VirtualKeyboard")) {
mWindow->pushGui(new GuiTextEditKeyboardPopup( mWindow->pushGui(new GuiTextEditKeyboardPopup(
getHelpStyle(), 0.0f, "ENTER DOWNLOAD DIRECTORY", currentDownloadDirectory, getHelpStyle(), 0.0f, _("ENTER DOWNLOAD DIRECTORY"),
directoryFunc, false)); currentDownloadDirectory, directoryFunc, false));
} }
else { else {
mWindow->pushGui( mWindow->pushGui(
new GuiTextEditPopup(getHelpStyle(), "ENTER DOWNLOAD DIRECTORY", new GuiTextEditPopup(getHelpStyle(), _("ENTER DOWNLOAD DIRECTORY"),
currentDownloadDirectory, directoryFunc, false)); currentDownloadDirectory, directoryFunc, false));
} }
}); });
buttons.push_back(mButton2); buttons.push_back(mButton2);
} }
mButton3 = std::make_shared<ButtonComponent>("CANCEL", "cancel", [this]() { mButton3 = std::make_shared<ButtonComponent>(_("CANCEL"), _("cancel"), [this]() {
mAbortDownload = true; mAbortDownload = true;
if (mThread) { if (mThread) {
mThread->join(); mThread->join();
mThread.reset(); mThread.reset();
} }
if (mDownloading) { if (mDownloading) {
mWindow->pushGui(
new GuiMsgBox(getHelpStyle(), "DOWNLOAD ABORTED\nNO PACKAGE SAVED TO DISK", "OK",
nullptr, "", nullptr, "", nullptr, nullptr, true, true,
(mRenderer->getIsVerticalOrientation() ?
0.70f :
0.45f * (1.778f / mRenderer->getScreenAspectRatio()))));
}
else if (mHasDownloaded || mReadyToInstall) {
mWindow->pushGui(new GuiMsgBox( mWindow->pushGui(new GuiMsgBox(
getHelpStyle(), "PACKAGE WAS DOWNLOADED AND\nCAN BE MANUALLY INSTALLED", "OK", getHelpStyle(), _("DOWNLOAD ABORTED") + "\n" + _("NO PACKAGE SAVED TO DISK"),
nullptr, "", nullptr, "", nullptr, nullptr, true, true, _("OK"), nullptr, "", nullptr, "", nullptr, nullptr, true, true,
(mRenderer->getIsVerticalOrientation() ? (mRenderer->getIsVerticalOrientation() ?
0.70f : 0.70f :
0.45f * (1.778f / mRenderer->getScreenAspectRatio())))); 0.45f * (1.778f / mRenderer->getScreenAspectRatio()))));
} }
else if (mHasDownloaded || mReadyToInstall) {
mWindow->pushGui(new GuiMsgBox(
getHelpStyle(), _("PACKAGE WAS DOWNLOADED AND CAN BE MANUALLY INSTALLED"), _("OK"),
nullptr, "", nullptr, "", nullptr, nullptr, true, true,
(mRenderer->getIsVerticalOrientation() ?
0.60f :
0.35f * (1.778f / mRenderer->getScreenAspectRatio()))));
}
delete this; delete this;
}); });
@ -217,7 +220,7 @@ GuiApplicationUpdater::GuiApplicationUpdater()
std::round(mRenderer->getScreenHeight() * 0.13f)); std::round(mRenderer->getScreenHeight() * 0.13f));
mBusyAnim.setSize(mSize); mBusyAnim.setSize(mSize);
mBusyAnim.setText("DOWNLOADING 100%"); mBusyAnim.setText(_("DOWNLOADING 100%"));
mBusyAnim.onSizeChanged(); mBusyAnim.onSizeChanged();
} }
@ -270,8 +273,9 @@ bool GuiApplicationUpdater::downloadPackage()
break; break;
} }
else if (reqStatus != HttpReq::REQ_IN_PROGRESS) { else if (reqStatus != HttpReq::REQ_IN_PROGRESS) {
std::string errorMessage {"Network error (status: "}; std::string errorMessage {_("Network error (status:")};
errorMessage.append(std::to_string(reqStatus)) errorMessage.append(" ")
.append(std::to_string(reqStatus))
.append(") - ") .append(") - ")
.append(mRequest->getErrorMsg()); .append(mRequest->getErrorMsg());
mRequest.reset(); mRequest.reset();
@ -301,7 +305,7 @@ bool GuiApplicationUpdater::downloadPackage()
mRequest.reset(); mRequest.reset();
if (Utils::Math::md5Hash(fileContents, false) != mPackage.md5) { if (Utils::Math::md5Hash(fileContents, false) != mPackage.md5) {
const std::string errorMessage {"Downloaded file does not match expected MD5 checksum"}; const std::string errorMessage {_("Downloaded file does not match expected MD5 checksum")};
LOG(LogError) << errorMessage; LOG(LogError) << errorMessage;
std::unique_lock<std::mutex> lock {mMutex}; std::unique_lock<std::mutex> lock {mMutex};
mMessage = "Error: " + errorMessage; mMessage = "Error: " + errorMessage;
@ -317,11 +321,9 @@ bool GuiApplicationUpdater::downloadPackage()
LOG(LogInfo) << "Temporary package file already exists, deleting it"; LOG(LogInfo) << "Temporary package file already exists, deleting it";
Utils::FileSystem::removeFile(mDownloadPackageFilename); Utils::FileSystem::removeFile(mDownloadPackageFilename);
if (Utils::FileSystem::exists(mDownloadPackageFilename)) { if (Utils::FileSystem::exists(mDownloadPackageFilename)) {
const std::string errorMessage { LOG(LogError) << "Couldn't delete temporary package file, permission problems?";
"Couldn't delete temporary package file, permission problems?"};
LOG(LogError) << errorMessage;
std::unique_lock<std::mutex> lock {mMutex}; std::unique_lock<std::mutex> lock {mMutex};
mMessage = "Error: " + errorMessage; mMessage = _("Error: Couldn't delete temporary package file, permission problems?");
return true; return true;
} }
} }
@ -334,7 +336,7 @@ bool GuiApplicationUpdater::downloadPackage()
LOG(LogError) << "Couldn't write package file \"" << mDownloadPackageFilename LOG(LogError) << "Couldn't write package file \"" << mDownloadPackageFilename
<< "\", permission problems?"; << "\", permission problems?";
std::unique_lock<std::mutex> lock {mMutex}; std::unique_lock<std::mutex> lock {mMutex};
mMessage = "Error: Couldn't write package file, permission problems?"; mMessage = _("Error: Couldn't write package file, permission problems?");
return true; return true;
} }
@ -353,10 +355,9 @@ bool GuiApplicationUpdater::downloadPackage()
(std::filesystem::perms::owner_all | std::filesystem::perms::group_all | (std::filesystem::perms::owner_all | std::filesystem::perms::group_all |
std::filesystem::perms::others_read | std::filesystem::perms::others_exec)) { std::filesystem::perms::others_read | std::filesystem::perms::others_exec)) {
Utils::FileSystem::removeFile(mDownloadPackageFilename); Utils::FileSystem::removeFile(mDownloadPackageFilename);
const std::string errorMessage {"Couldn't set permissions on AppImage file"}; LOG(LogError) << "Couldn't set permissions on AppImage file";
LOG(LogError) << errorMessage;
std::unique_lock<std::mutex> lock {mMutex}; std::unique_lock<std::mutex> lock {mMutex};
mMessage = "Error: " + errorMessage; mMessage = _("Error: Couldn't set permissions on AppImage file");
return true; return true;
} }
} }
@ -364,7 +365,8 @@ bool GuiApplicationUpdater::downloadPackage()
LOG(LogInfo) << "Successfully downloaded package file \"" << mDownloadPackageFilename << "\""; LOG(LogInfo) << "Successfully downloaded package file \"" << mDownloadPackageFilename << "\"";
std::unique_lock<std::mutex> lock {mMutex}; std::unique_lock<std::mutex> lock {mMutex};
mMessage = "Downloaded " + Utils::FileSystem::getFileName(mDownloadPackageFilename); mMessage = Utils::String::format(
_("Downloaded %s"), Utils::FileSystem::getFileName(mDownloadPackageFilename).c_str());
mDownloading = false; mDownloading = false;
mReadyToInstall = true; mReadyToInstall = true;
@ -398,9 +400,8 @@ bool GuiApplicationUpdater::installAppImage()
readFile.open(mDownloadPackageFilename.c_str(), std::ofstream::binary); readFile.open(mDownloadPackageFilename.c_str(), std::ofstream::binary);
if (readFile.fail()) { if (readFile.fail()) {
const std::string errorMessage {"Couldn't open AppImage update file for reading"}; LOG(LogError) << "Couldn't open AppImage update file for reading";
LOG(LogError) << errorMessage; mMessage = _("Error: Couldn't open AppImage update file for reading");
mMessage = "Error: " + errorMessage;
mHasDownloaded = false; mHasDownloaded = false;
return true; return true;
} }
@ -413,9 +414,8 @@ bool GuiApplicationUpdater::installAppImage()
readFile.close(); readFile.close();
if (Utils::Math::md5Hash(fileData, false) != mPackage.md5) { if (Utils::Math::md5Hash(fileData, false) != mPackage.md5) {
const std::string errorMessage {"Downloaded file does not match expected MD5 checksum"}; LOG(LogError) << "Downloaded file does not match expected MD5 checksum";
LOG(LogError) << errorMessage; mMessage = _("Error: Downloaded file does not match expected MD5 checksum");
mMessage = "Error: " + errorMessage;
mHasDownloaded = false; mHasDownloaded = false;
return true; return true;
} }
@ -423,10 +423,8 @@ bool GuiApplicationUpdater::installAppImage()
const std::string packageOldFile {packageTargetFile + "_" + PROGRAM_VERSION_STRING + ".OLD"}; const std::string packageOldFile {packageTargetFile + "_" + PROGRAM_VERSION_STRING + ".OLD"};
if (Utils::FileSystem::renameFile(packageTargetFile, packageOldFile, true)) { if (Utils::FileSystem::renameFile(packageTargetFile, packageOldFile, true)) {
const std::string errorMessage { LOG(LogError) << "Couldn't rename running AppImage file, permission problems?";
"Couldn't rename running AppImage file, permission problems?"}; mMessage = _("Error: Couldn't rename running AppImage file, permission problems?");
LOG(LogError) << errorMessage;
mMessage = "Error: " + errorMessage;
LOG(LogInfo) << "Attempting to rename \"" << packageOldFile LOG(LogInfo) << "Attempting to rename \"" << packageOldFile
<< "\" back to running AppImage"; << "\" back to running AppImage";
Utils::FileSystem::renameFile(packageOldFile, packageTargetFile, true); Utils::FileSystem::renameFile(packageOldFile, packageTargetFile, true);
@ -437,10 +435,8 @@ bool GuiApplicationUpdater::installAppImage()
LOG(LogInfo) << "Renamed running AppImage to \"" << packageOldFile << "\""; LOG(LogInfo) << "Renamed running AppImage to \"" << packageOldFile << "\"";
if (Utils::FileSystem::renameFile(mDownloadPackageFilename, packageTargetFile, true)) { if (Utils::FileSystem::renameFile(mDownloadPackageFilename, packageTargetFile, true)) {
const std::string errorMessage { LOG(LogError) << "Couldn't replace running AppImage file, permission problems?";
"Couldn't replace running AppImage file, permission problems?"}; mMessage = _("Error: Couldn't replace running AppImage file, permission problems?");
LOG(LogError) << errorMessage;
mMessage = "Error: " + errorMessage;
LOG(LogInfo) << "Attempting to rename \"" << packageOldFile LOG(LogInfo) << "Attempting to rename \"" << packageOldFile
<< "\" back to running AppImage"; << "\" back to running AppImage";
Utils::FileSystem::renameFile(packageOldFile, packageTargetFile, true); Utils::FileSystem::renameFile(packageOldFile, packageTargetFile, true);
@ -451,7 +447,8 @@ bool GuiApplicationUpdater::installAppImage()
LOG(LogInfo) << "Package was successfully installed as \"" << packageTargetFile << "\""; LOG(LogInfo) << "Package was successfully installed as \"" << packageTargetFile << "\"";
std::unique_lock<std::mutex> lock {mMutex}; std::unique_lock<std::mutex> lock {mMutex};
mMessage = "Successfully installed as " + Utils::FileSystem::getFileName(packageTargetFile); mMessage = Utils::String::format(_("Successfully installed as %s"),
Utils::FileSystem::getFileName(packageTargetFile).c_str());
mHasInstalled = true; mHasInstalled = true;
return false; return false;
@ -468,13 +465,13 @@ void GuiApplicationUpdater::update(int deltaTime)
} }
if (mDownloading) { if (mDownloading) {
mBusyAnim.setText("DOWNLOADING " + std::to_string(mDownloadPercentage) + "%"); mBusyAnim.setText(_("DOWNLOADING") + " " + std::to_string(mDownloadPercentage) + "%");
mBusyAnim.update(deltaTime); mBusyAnim.update(deltaTime);
} }
else if (mLinuxAppImage && mReadyToInstall) { else if (mLinuxAppImage && mReadyToInstall) {
mProcessStep1->setText(ViewController::TICKMARK_CHAR + " " + mProcessStep1->getValue()); mProcessStep1->setText(ViewController::TICKMARK_CHAR + " " + mProcessStep1->getValue());
mProcessStep1->setColor(mMenuColorGreen); mProcessStep1->setColor(mMenuColorGreen);
mButton1->setText("INSTALL", "install package", true, false); mButton1->setText(_("INSTALL"), _("install package"), true, false);
mButton1->setPressedFunc([this] { mButton1->setPressedFunc([this] {
if (!mInstalling) { if (!mInstalling) {
mMessage = ""; mMessage = "";
@ -494,10 +491,10 @@ void GuiApplicationUpdater::update(int deltaTime)
mProcessStep1->setText(ViewController::TICKMARK_CHAR + " " + mProcessStep1->getValue()); mProcessStep1->setText(ViewController::TICKMARK_CHAR + " " + mProcessStep1->getValue());
mProcessStep1->setColor(mMenuColorGreen); mProcessStep1->setColor(mMenuColorGreen);
} }
mChangelogMessage->setText("Find the detailed changelog at https://es-de.org"); mChangelogMessage->setText(_("Find the detailed changelog at") + " https://es-de.org");
mGrid.removeEntry(mButtons); mGrid.removeEntry(mButtons);
mGrid.setEntry(MenuComponent::makeButtonGrid(std::vector<std::shared_ptr<ButtonComponent>> { mGrid.setEntry(MenuComponent::makeButtonGrid(std::vector<std::shared_ptr<ButtonComponent>> {
std::make_shared<ButtonComponent>("QUIT", "quit application", std::make_shared<ButtonComponent>(_("QUIT"), _("quit application"),
[this]() { [this]() {
delete this; delete this;
Utils::Platform::quitES(); Utils::Platform::quitES();

View file

@ -31,6 +31,7 @@
#include "guis/GuiMenu.h" #include "guis/GuiMenu.h"
#include "guis/GuiTextEditKeyboardPopup.h" #include "guis/GuiTextEditKeyboardPopup.h"
#include "guis/GuiTextEditPopup.h" #include "guis/GuiTextEditPopup.h"
#include "utils/LocalizationUtil.h"
#include "views/GamelistView.h" #include "views/GamelistView.h"
#include "views/SystemView.h" #include "views/SystemView.h"
@ -186,15 +187,15 @@ void ViewController::migratedAppDataFilesDialog()
void ViewController::unsafeUpgradeDialog() void ViewController::unsafeUpgradeDialog()
{ {
const std::string upgradeMessage { const std::string upgradeMessage {
"IT SEEMS AS IF AN UNSAFE UPGRADE HAS BEEN MADE, POSSIBLY BY " _("IT SEEMS AS IF AN UNSAFE UPGRADE HAS BEEN MADE, POSSIBLY BY "
"UNPACKING THE NEW RELEASE ON TOP OF THE OLD ONE? THIS MAY CAUSE " "UNPACKING THE NEW RELEASE ON TOP OF THE OLD ONE? THIS MAY CAUSE "
"VARIOUS PROBLEMS, SOME OF WHICH MAY NOT BE APPARENT IMMEDIATELY. " "VARIOUS PROBLEMS, SOME OF WHICH MAY NOT BE APPARENT IMMEDIATELY. "
"MAKE SURE TO ALWAYS FOLLOW THE UPGRADE INSTRUCTIONS IN THE " "MAKE SURE TO ALWAYS FOLLOW THE UPGRADE INSTRUCTIONS IN THE "
"README.TXT FILE THAT CAN BE FOUND IN THE ES-DE DIRECTORY."}; "README.TXT FILE THAT CAN BE FOUND IN THE ES-DE DIRECTORY.")};
mWindow->pushGui(new GuiMsgBox( mWindow->pushGui(new GuiMsgBox(
HelpStyle(), upgradeMessage.c_str(), "OK", [] {}, "", nullptr, "", nullptr, nullptr, true, HelpStyle(), upgradeMessage.c_str(), _("OK"), [] {}, "", nullptr, "", nullptr, nullptr,
true, true, true,
(mRenderer->getIsVerticalOrientation() ? (mRenderer->getIsVerticalOrientation() ?
0.85f : 0.85f :
0.55f * (1.778f / mRenderer->getScreenAspectRatio())))); 0.55f * (1.778f / mRenderer->getScreenAspectRatio()))));
@ -202,15 +203,15 @@ void ViewController::unsafeUpgradeDialog()
void ViewController::invalidSystemsFileDialog() void ViewController::invalidSystemsFileDialog()
{ {
const std::string errorMessage {"COULDN'T PARSE THE SYSTEMS CONFIGURATION FILE. " const std::string errorMessage {_("COULDN'T PARSE THE SYSTEMS CONFIGURATION FILE. "
"IF YOU HAVE A CUSTOMIZED es_systems.xml FILE, THEN " "IF YOU HAVE A CUSTOMIZED es_systems.xml FILE, THEN "
"SOMETHING IS LIKELY WRONG WITH YOUR XML SYNTAX. " "SOMETHING IS LIKELY WRONG WITH YOUR XML SYNTAX. "
"IF YOU DON'T HAVE A CUSTOM SYSTEMS FILE, THEN THE " "IF YOU DON'T HAVE A CUSTOM SYSTEMS FILE, THEN THE "
"ES-DE INSTALLATION IS BROKEN. SEE THE APPLICATION " "ES-DE INSTALLATION IS BROKEN. SEE THE APPLICATION "
"LOG FILE es_log.txt FOR ADDITIONAL INFO"}; "LOG FILE es_log.txt FOR ADDITIONAL INFO")};
mWindow->pushGui(new GuiMsgBox( mWindow->pushGui(new GuiMsgBox(
HelpStyle(), errorMessage.c_str(), "QUIT", HelpStyle(), errorMessage.c_str(), _("QUIT"),
[] { [] {
SDL_Event quit {}; SDL_Event quit {};
quit.type = SDL_QUIT; quit.type = SDL_QUIT;
@ -225,20 +226,20 @@ void ViewController::invalidSystemsFileDialog()
void ViewController::noGamesDialog() void ViewController::noGamesDialog()
{ {
#if defined(__ANDROID__) #if defined(__ANDROID__)
mNoGamesErrorMessage = "NO GAME FILES WERE FOUND, PLEASE PLACE YOUR GAMES IN " mNoGamesErrorMessage = _("NO GAME FILES WERE FOUND, PLEASE PLACE YOUR GAMES IN "
"THE CONFIGURED ROM DIRECTORY. OPTIONALLY THE ROM " "THE CONFIGURED ROM DIRECTORY. OPTIONALLY THE ROM "
"DIRECTORY STRUCTURE CAN BE GENERATED WHICH WILL " "DIRECTORY STRUCTURE CAN BE GENERATED WHICH WILL "
"CREATE A TEXT FILE FOR EACH SYSTEM PROVIDING SOME " "CREATE A TEXT FILE FOR EACH SYSTEM PROVIDING SOME "
"INFORMATION SUCH AS THE SUPPORTED FILE EXTENSIONS.\n" "INFORMATION SUCH AS THE SUPPORTED FILE EXTENSIONS.\n"
"THIS IS THE CURRENTLY CONFIGURED ROM DIRECTORY:\n"; "THIS IS THE CURRENTLY CONFIGURED ROM DIRECTORY:\n");
#else #else
mNoGamesErrorMessage = "NO GAME FILES WERE FOUND. EITHER PLACE YOUR GAMES IN " mNoGamesErrorMessage = _("NO GAME FILES WERE FOUND. EITHER PLACE YOUR GAMES IN "
"THE CURRENTLY CONFIGURED ROM DIRECTORY OR CHANGE " "THE CURRENTLY CONFIGURED ROM DIRECTORY OR CHANGE "
"ITS PATH USING THE BUTTON BELOW. OPTIONALLY THE ROM " "ITS PATH USING THE BUTTON BELOW. OPTIONALLY THE ROM "
"DIRECTORY STRUCTURE CAN BE GENERATED WHICH WILL " "DIRECTORY STRUCTURE CAN BE GENERATED WHICH WILL "
"CREATE A TEXT FILE FOR EACH SYSTEM PROVIDING SOME " "CREATE A TEXT FILE FOR EACH SYSTEM PROVIDING SOME "
"INFORMATION SUCH AS THE SUPPORTED FILE EXTENSIONS.\n" "INFORMATION SUCH AS THE SUPPORTED FILE EXTENSIONS.\n"
"THIS IS THE CURRENTLY CONFIGURED ROM DIRECTORY:\n"; "THIS IS THE CURRENTLY CONFIGURED ROM DIRECTORY:\n");
#endif #endif
#if defined(_WIN64) #if defined(_WIN64)
@ -252,7 +253,7 @@ void ViewController::noGamesDialog()
HelpStyle(), mNoGamesErrorMessage + mRomDirectory, HelpStyle(), mNoGamesErrorMessage + mRomDirectory,
#else #else
mNoGamesMessageBox = new GuiMsgBox( mNoGamesMessageBox = new GuiMsgBox(
HelpStyle(), mNoGamesErrorMessage + mRomDirectory, "CHANGE ROM DIRECTORY", HelpStyle(), mNoGamesErrorMessage + mRomDirectory, _("CHANGE ROM DIRECTORY"),
[this] { [this] {
std::string currentROMDirectory; std::string currentROMDirectory;
#if defined(_WIN64) #if defined(_WIN64)
@ -262,7 +263,7 @@ void ViewController::noGamesDialog()
#endif #endif
if (Settings::getInstance()->getBool("VirtualKeyboard")) { if (Settings::getInstance()->getBool("VirtualKeyboard")) {
mWindow->pushGui(new GuiTextEditKeyboardPopup( mWindow->pushGui(new GuiTextEditKeyboardPopup(
HelpStyle(), 0.0f, "ENTER ROM DIRECTORY PATH", currentROMDirectory, HelpStyle(), 0.0f, _("ENTER ROM DIRECTORY PATH"), currentROMDirectory,
[this, currentROMDirectory](const std::string& newROMDirectory) { [this, currentROMDirectory](const std::string& newROMDirectory) {
if (currentROMDirectory != newROMDirectory) { if (currentROMDirectory != newROMDirectory) {
Settings::getInstance()->setString( Settings::getInstance()->setString(
@ -275,20 +276,23 @@ void ViewController::noGamesDialog()
mRomDirectory = FileData::getROMDirectory(); mRomDirectory = FileData::getROMDirectory();
#endif #endif
mNoGamesMessageBox->changeText(mNoGamesErrorMessage + mRomDirectory); mNoGamesMessageBox->changeText(mNoGamesErrorMessage + mRomDirectory);
mWindow->pushGui(new GuiMsgBox(HelpStyle(), mWindow->pushGui(new GuiMsgBox(
"ROM DIRECTORY SETTING SAVED, RESTART\n" HelpStyle(),
"THE APPLICATION TO RESCAN THE SYSTEMS", _("ROM DIRECTORY SETTING SAVED, RESTART "
"OK", nullptr, "", nullptr, "", nullptr, "THE APPLICATION TO RESCAN THE SYSTEMS"),
nullptr, true, true)); _("OK"), nullptr, "", nullptr, "", nullptr, nullptr, true, true,
(mRenderer->getIsVerticalOrientation() ?
0.66f :
0.42f * (1.778f / mRenderer->getScreenAspectRatio()))));
} }
}, },
false, "SAVE", "SAVE CHANGES?", "Currently configured path:", false, _("SAVE"), _("SAVE CHANGES?"), _("Currently configured path:"),
currentROMDirectory, "LOAD CURRENTLY CONFIGURED PATH", currentROMDirectory, _("LOAD CURRENTLY CONFIGURED PATH"),
"CLEAR (LEAVE BLANK TO RESET TO DEFAULT PATH)")); _("CLEAR (LEAVE BLANK TO RESET TO DEFAULT PATH)")));
} }
else { else {
mWindow->pushGui(new GuiTextEditPopup( mWindow->pushGui(new GuiTextEditPopup(
HelpStyle(), "ENTER ROM DIRECTORY PATH", currentROMDirectory, HelpStyle(), _("ENTER ROM DIRECTORY PATH"), currentROMDirectory,
[this](const std::string& newROMDirectory) { [this](const std::string& newROMDirectory) {
Settings::getInstance()->setString("ROMDirectory", Settings::getInstance()->setString("ROMDirectory",
Utils::String::trim(newROMDirectory)); Utils::String::trim(newROMDirectory));
@ -300,48 +304,60 @@ void ViewController::noGamesDialog()
mRomDirectory = FileData::getROMDirectory(); mRomDirectory = FileData::getROMDirectory();
#endif #endif
mNoGamesMessageBox->changeText(mNoGamesErrorMessage + mRomDirectory); mNoGamesMessageBox->changeText(mNoGamesErrorMessage + mRomDirectory);
mWindow->pushGui(new GuiMsgBox(HelpStyle(), mWindow->pushGui(new GuiMsgBox(
"ROM DIRECTORY SETTING SAVED, RESTART\n" HelpStyle(),
"THE APPLICATION TO RESCAN THE SYSTEMS", _("ROM DIRECTORY SETTING SAVED, RESTART "
"OK", nullptr, "", nullptr, "", nullptr, "THE APPLICATION TO RESCAN THE SYSTEMS"),
nullptr, true)); _("OK"), nullptr, "", nullptr, "", nullptr, nullptr, true, true,
(mRenderer->getIsVerticalOrientation() ?
0.66f :
0.42f * (1.778f / mRenderer->getScreenAspectRatio()))));
}, },
false, "SAVE", "SAVE CHANGES?", "Currently configured path:", false, _("SAVE"), _("SAVE CHANGES?"), _("Currently configured path:"),
currentROMDirectory, "LOAD CURRENTLY CONFIGURED PATH", currentROMDirectory, _("LOAD CURRENTLY CONFIGURED PATH"),
"CLEAR (LEAVE BLANK TO RESET TO DEFAULT PATH)")); _("CLEAR (LEAVE BLANK TO RESET TO DEFAULT PATH)")));
} }
}, },
#endif // __ANDROID__ #endif // __ANDROID__
"CREATE DIRECTORIES", _("CREATE DIRECTORIES"),
[this] { [this] {
mWindow->pushGui(new GuiMsgBox( mWindow->pushGui(new GuiMsgBox(
HelpStyle(), HelpStyle(),
"THIS WILL CREATE DIRECTORIES FOR ALL THE\n" _("THIS WILL CREATE DIRECTORIES FOR ALL THE "
"GAME SYSTEMS DEFINED IN es_systems.xml\n\n" "GAME SYSTEMS DEFINED IN es_systems.xml\n\n"
"THIS MAY CREATE A LOT OF FOLDERS SO IT'S\n" "THIS MAY CREATE A LOT OF FOLDERS SO IT'S "
"ADVICED TO REMOVE THE ONES YOU DON'T NEED", "ADVICED TO REMOVE THE ONES YOU DON'T NEED"),
"PROCEED", _("PROCEED"),
[this] { [this] {
if (!SystemData::createSystemDirectories()) { if (!SystemData::createSystemDirectories()) {
mWindow->pushGui(new GuiMsgBox(HelpStyle(), mWindow->pushGui(new GuiMsgBox(
"THE SYSTEM DIRECTORIES WERE SUCCESSFULLY\n" HelpStyle(),
"GENERATED, EXIT THE APPLICATION AND PLACE\n" _("THE SYSTEM DIRECTORIES WERE SUCCESSFULLY "
"YOUR GAMES IN THE NEWLY CREATED FOLDERS", "GENERATED, EXIT THE APPLICATION AND PLACE "
"OK", nullptr, "", nullptr, "", nullptr, "YOUR GAMES IN THE NEW FOLDERS"),
nullptr, true)); _("OK"), nullptr, "", nullptr, "", nullptr, nullptr, true, true,
(mRenderer->getIsVerticalOrientation() ?
0.74f :
0.46f * (1.778f / mRenderer->getScreenAspectRatio()))));
} }
else { else {
mWindow->pushGui(new GuiMsgBox(HelpStyle(), mWindow->pushGui(new GuiMsgBox(
"ERROR CREATING THE SYSTEM DIRECTORIES,\n" HelpStyle(),
"PERMISSION PROBLEMS OR DISK FULL?\n\n" _("ERROR CREATING THE SYSTEM DIRECTORIES, "
"SEE THE LOG FILE FOR MORE DETAILS", "PERMISSION PROBLEMS OR DISK FULL?\n\n"
"OK", nullptr, "", nullptr, "", nullptr, "SEE THE LOG FILE FOR MORE DETAILS"),
nullptr, true)); _("OK"), nullptr, "", nullptr, "", nullptr, nullptr, true, true,
(mRenderer->getIsVerticalOrientation() ?
0.75f :
0.47f * (1.778f / mRenderer->getScreenAspectRatio()))));
} }
}, },
"CANCEL", nullptr, "", nullptr, nullptr, false)); _("CANCEL"), nullptr, "", nullptr, nullptr, false, true,
(mRenderer->getIsVerticalOrientation() ?
0.78f :
0.50 * (1.778f / mRenderer->getScreenAspectRatio()))));
}, },
"QUIT", _("QUIT"),
[] { [] {
SDL_Event quit {}; SDL_Event quit {};
quit.type = SDL_QUIT; quit.type = SDL_QUIT;
@ -394,7 +410,7 @@ void ViewController::updateAvailableDialog()
<< "\""; << "\"";
mWindow->pushGui(new GuiMsgBox( mWindow->pushGui(new GuiMsgBox(
getHelpStyle(), results, "UPDATE", getHelpStyle(), results, _("UPDATE"),
[this, package] { [this, package] {
mWindow->pushGui(new GuiApplicationUpdater()); mWindow->pushGui(new GuiApplicationUpdater());
@ -402,36 +418,36 @@ void ViewController::updateAvailableDialog()
std::string upgradeMessage; std::string upgradeMessage;
if (package.name == "WindowsPortable") { if (package.name == "WindowsPortable") {
upgradeMessage = upgradeMessage =
"THE APPLICATION UPDATER WILL DOWNLOAD THE LATEST PORTABLE WINDOWS " _("THE APPLICATION UPDATER WILL DOWNLOAD THE LATEST PORTABLE WINDOWS "
"RELEASE FOR YOU, BUT YOU WILL NEED TO MANUALLY PERFORM THE UPGRADE. " "RELEASE FOR YOU, BUT YOU WILL NEED TO MANUALLY PERFORM THE UPGRADE. "
"SEE THE README.TXT FILE INSIDE THE DOWNLOADED ZIP FILE FOR " "SEE THE README.TXT FILE INSIDE THE DOWNLOADED ZIP FILE FOR "
"INSTRUCTIONS ON HOW THIS IS ACCOMPLISHED. AS IS ALSO DESCRIBED IN " "INSTRUCTIONS ON HOW THIS IS ACCOMPLISHED. AS IS ALSO DESCRIBED IN "
"THAT DOCUMENT, NEVER UNPACK A NEW RELEASE ON TOP OF AN OLD " "THAT DOCUMENT, NEVER UNPACK A NEW RELEASE ON TOP OF AN OLD "
"INSTALLATION AS THAT MAY COMPLETELY BREAK THE APPLICATION."; "INSTALLATION AS THAT MAY BREAK THE APPLICATION.");
} }
else if (package.name == "WindowsInstaller") { else if (package.name == "WindowsInstaller") {
upgradeMessage = upgradeMessage =
"THE APPLICATION UPDATER WILL DOWNLOAD THE LATEST WINDOWS INSTALLER " _("THE APPLICATION UPDATER WILL DOWNLOAD THE LATEST WINDOWS INSTALLER "
"RELEASE FOR YOU, BUT YOU WILL NEED TO MANUALLY RUN IT TO PERFORM " "RELEASE FOR YOU, BUT YOU WILL NEED TO MANUALLY RUN IT TO PERFORM "
"THE UPGRADE. WHEN DOING THIS, MAKE SURE THAT YOU ANSWER YES TO THE " "THE UPGRADE. WHEN DOING THIS, MAKE SURE THAT YOU ANSWER YES TO THE "
"QUESTION OF WHETHER TO UNINSTALL THE OLD VERSION, OR YOU MAY " "QUESTION OF WHETHER TO UNINSTALL THE OLD VERSION, OR YOU MAY "
"END UP WITH A BROKEN SETUP."; "END UP WITH A BROKEN SETUP.");
} }
else if (package.name == "macOSApple" || package.name == "macOSIntel") { else if (package.name == "macOSApple" || package.name == "macOSIntel") {
upgradeMessage = upgradeMessage =
"THE APPLICATION UPDATER WILL DOWNLOAD THE LATEST RELEASE FOR " _("THE APPLICATION UPDATER WILL DOWNLOAD THE LATEST RELEASE FOR "
"YOU, BUT YOU WILL NEED TO MANUALLY INSTALL THE DMG FILE TO PERFORM " "YOU, BUT YOU WILL NEED TO MANUALLY INSTALL THE DMG FILE TO PERFORM "
"THE UPGRADE."; "THE UPGRADE.");
} }
mWindow->pushGui(new GuiMsgBox( mWindow->pushGui(new GuiMsgBox(
getHelpStyle(), upgradeMessage.c_str(), "OK", [] {}, "", nullptr, "", getHelpStyle(), upgradeMessage.c_str(), _("OK"), [] {}, "", nullptr, "",
nullptr, nullptr, true, true, nullptr, nullptr, true, true,
(mRenderer->getIsVerticalOrientation() ? (mRenderer->getIsVerticalOrientation() ?
0.85f : 0.85f :
0.535f * (1.778f / mRenderer->getScreenAspectRatio())))); 0.535f * (1.778f / mRenderer->getScreenAspectRatio()))));
} }
}, },
"CANCEL", _("CANCEL"),
[] { [] {
HttpReq::cleanupCurlMulti(); HttpReq::cleanupCurlMulti();
return; return;
@ -442,7 +458,7 @@ void ViewController::updateAvailableDialog()
0.45f * (1.778f / mRenderer->getScreenAspectRatio())))); 0.45f * (1.778f / mRenderer->getScreenAspectRatio()))));
} }
else { else {
mWindow->pushGui(new GuiMsgBox(getHelpStyle(), results, "OK", nullptr, "", nullptr, "", mWindow->pushGui(new GuiMsgBox(getHelpStyle(), results, _("OK"), nullptr, "", nullptr, "",
nullptr, nullptr, true, true, nullptr, nullptr, true, true,
(mRenderer->getIsVerticalOrientation() ? (mRenderer->getIsVerticalOrientation() ?
0.70f : 0.70f :