diff --git a/CMakeLists.txt b/CMakeLists.txt
index 42a5d402..4f3883c1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -647,7 +647,7 @@ if(NOT BUILD_HYDRA_CORE AND NOT BUILD_LIBRETRO_CORE)
set(FRONTEND_SOURCE_FILES src/panda_qt/main.cpp src/panda_qt/screen.cpp src/panda_qt/main_window.cpp src/panda_qt/about_window.cpp
src/panda_qt/config_window.cpp src/panda_qt/zep.cpp src/panda_qt/text_editor.cpp src/panda_qt/cheats_window.cpp src/panda_qt/mappings.cpp
- src/panda_qt/patch_window.cpp src/panda_qt/elided_label.cpp src/panda_qt/shader_editor.cpp
+ src/panda_qt/patch_window.cpp src/panda_qt/elided_label.cpp src/panda_qt/shader_editor.cpp src/panda_qt/translations.cpp
)
set(FRONTEND_HEADER_FILES include/panda_qt/screen.hpp include/panda_qt/main_window.hpp include/panda_qt/about_window.hpp
include/panda_qt/config_window.hpp include/panda_qt/text_editor.hpp include/panda_qt/cheats_window.hpp
@@ -701,8 +701,8 @@ if(NOT BUILD_HYDRA_CORE AND NOT BUILD_LIBRETRO_CORE)
docs/img/rnap_icon.png docs/img/rcow_icon.png docs/img/skyemu_icon.png
)
- set(QT_TRANSLATIONS "${PROJECT_SOURCE_DIR}/docs/translations")
- file(GLOB_RECURSE TRANSLATIONS_TS ${QT_TRANSLATIONS}/*.ts)
+ # Translation files in Qt's .ts format. Will be converted into binary files and embedded into the executable
+ set(TRANSLATIONS_TS docs/translations/en.ts docs/translations/el.ts)
set_source_files_properties(${TRANSLATIONS_TS} PROPERTIES OUTPUT_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/translations")
qt_add_translation(TRANSLATIONS_QM ${TRANSLATIONS_TS})
diff --git a/docs/translations/el.ts b/docs/translations/el.ts
index 6473258b..0368d8bd 100644
--- a/docs/translations/el.ts
+++ b/docs/translations/el.ts
@@ -134,371 +134,396 @@
Εικονίδιο Παραθύρου
-
+
+ Language
+ Γλώσσα
+
+
+
Show version on window title
Εμφάνιση έκδοσης στον τίτλο του παραθύρου
-
+
Alber v%1
Αλβέρτος v%1
-
+
Alber
Αλβέρτος
-
+
Remember window position
Αποθήκευση θέσης παραθύρου
-
+
General Settings
Γενικές Ρυθμίσεις
-
+
Browse...
Περιήγηση
-
+
Select Directory
Επιλογή φακέλου
-
+
Default ROMs path
Προεπιλεγμένος φάκελος ROM
-
+
Enable Discord RPC
Ενεργοποίηση Discord RPC
-
+
Use portable build
Ενεργοποίηση φορητής εγκατάστασης
-
+
Print version in console output
Εκτύπωση έκδοσης στην κονσόλα
-
+
Graphics Settings
Ρυθμίσεις Γραφικών
-
-
+
+
Null
Κανένα
-
+
OpenGL
-
+
Vulkan
-
+
GPU renderer
Πυρήνας GPU
-
+
Enable Renderdoc
Ενεργοποίηση Renderdoc
-
+
Enable shader JIT
Ενεργοποίηση μεταγλωττιστή shaders
-
+
Enable VSync
Ενεργοποίηση VSync
-
+
Use ubershaders (No stutter, maybe slower)
Χρήση ubershaders (Χωρίς stutter, ίσως πιο αργό)
-
+
Accurate shader multiplication
Ακριβής πολλαπλασιασμός στα shaders
-
+
Accelerate shaders
Επιτάχυνση shaders
-
+
Force shadergen when rendering lights
Εξαναγκασμός shadergen όταν υπάρχουν φώτα
-
+
Light threshold for forcing shadergen
Αριθμός φωτών για εξαναγκασμό shadergen
-
+
Audio Settings
Ρυθμίσεις Ήχου
-
+
LLE
-
+
HLE
-
+
DSP emulation
Εξομοίωση DSP
-
+
Enable audio
Ενεργοποίηση ήχου
-
+
Enable AAC audio
Ενεργοποίηση ήχου AAC
-
+
Print DSP firmware
Εκτύπωση λογισμικού DSP
-
+
Mute audio device
Σίγαση συσκευής ήχου
-
+
Cubic
Κυβική
-
+
Linear
Γραμμική
-
+
Volume curve
Κλίμακα ήχου
-
+
Audio device volume
Ένταση ήχου
-
+
Battery Settings
Ρυθμίσεις μπαταρίας
-
+
Battery percentage
Ποσοστό μπαταρίας
-
+
Charger plugged
Φορτιστής
-
+
SD Card Settings
Ρυθμίσης κάρτας SD
-
+
Enable virtual SD card
Ενεργοποίηση εικονικής SD
-
+
Write protect virtual SD card
Προστασία της SD από εγγραφή
-
+
Interface
Διεπαφή
-
+
User Interface settings
Ρυθμίσεις διεπαφής
-
+
General
Γενικά
-
+
General emulator settings
Γενικές ρυθμίσεις εξομοιωτή
-
+
Graphics
Γραφικά
-
+
Graphics emulation and output settings
Ρυθμίσεις εξομοίωσης γραφικών
-
+
Audio
Ήχος
-
+
Audio emulation and output settings
Ρυθμίσεις εξομοίωσης ήχου
-
+
Battery
Μπαταρία
-
+
Battery emulation settings
Ρυθμίσεις εξομοίωσης μπαταρίας
-
+
SD Card
Κάρτα SD
-
+
SD Card emulation settings
Ρυθμίσεις εξομοίωσης κάρτας SD
+
+
+ Language change successful
+ Επιτυχία αλλαγής γλώσσας
+
+
+
+ Restart Panda3DS for the new language to be used.
+ Επανεκκινήστε το Panda3DS για να εφαρμοστεί η νέα γλώσσα.
+
+
+
+ Language change failed
+ Αποτυχία αλλαγής γλώσσας
+
+
+
+ The language you selected is not included in Panda3DS. If you're seeing this, someone messed up the language UI code...
+ Το Panda3DS δεν υποστηρίζει τον γλώσσα που επιλέξατε. Αν το βλέπετε αυτό, κάποιος έκανε λάθος στον κώδικα, κατηγορήστε τον Πάρη...
+
MainWindow
-
+
Alber
Αλβέρτος
-
+
File
- Αρχείο
+ Αρχεία
-
+
Emulation
Εξομοίωση
-
+
Tools
Εργαλεία
-
+
About
Σχετικά
-
+
Load game
Φόρτωση παιχνιδιού
-
+
Load Lua script
Φόρτωση αρχείου Lua
-
+
Open Panda3DS folder
Άνοιγμα φακέλου Panda3DS
-
+
Pause
Παύση
-
+
Resume
Συνέχεια
-
+
Reset
Επανέναρξη
-
+
Configure
Ρύθμιση
-
+
Dump RomFS
-
+
Open Lua Editor
Άνοιγμα Lua Editor
-
+
Open Cheats Editor
Άνοιγμα Editor κωδικών
-
+
Open Patch Window
Άνοιγμα παραθύρου για patching
-
+
Open Shader Editor
-
+
Dump loaded DSP firmware
-
+
About Panda3DS
Σχετικά με το Panda3DS
@@ -552,7 +577,7 @@
No RomFS partition was found in the loaded app
-
+ Δεν βρέθηκε RomFS στην εφαρμογή που έχει φορτωθεί
@@ -567,7 +592,7 @@
No DSP firmware loaded
-
+ Δεν έχει φορτωθεί DSP firmware
@@ -577,7 +602,7 @@
Failed to open output file
-
+ Αποτυχία ανοίγματος του αρχείου εξόδου
@@ -638,7 +663,7 @@
Please provide paths for both the input file and the patch file
-
+ Παρακαλούμε διαλέξτε και αρχείο εισόδου και αρχείο patch
@@ -648,32 +673,32 @@
No output path
-
+ Δεν επιλέχθηκε φάκελος εξόδου
No path was provided for the output file, no patching was done
-
+ Δεν επιλέχθηκε αρχείο εξόδου. Δεν έγινε patching
Unknown patch format
-
+ Άγνωστο είδος patch
Unknown format for patch file. Currently IPS, UPS and BPS are supported
-
+ Άγνωστο είδος αρχείου patch. Υποστηρίζονται αρχεία IPS, UPS και BPS
Failed to open input files
-
+ Αποτυχία ανοίγματος των αρχείων εισόδου
Make sure they're in a directory Panda3DS has access to
-
+ Βεβαιωθείτε ότι είναι σε φάκελο που έχει πρόσβαση το Panda3DS
@@ -693,17 +718,17 @@
Patch was applied successfully but a checksum mismatch was detected. The input or output files might not be correct
-
+ Το patch εφαρμόστηκε με επιτυχία αλλά ανιχνεύτηκε σφάλμα στο checksum. Ενδέχεται τα αρχεία εισόδου η εξόδου να είναι λανθασμένα
Patching error
-
+ Σφάλμα στο patching
An error occured while patching
-
+ Προέκυψε σφάλμα στο patching
@@ -719,7 +744,7 @@
Reload shader
-
+ Επαναφόρτωση shader
diff --git a/docs/translations/en.ts b/docs/translations/en.ts
index 258089ab..4a70fabb 100644
--- a/docs/translations/en.ts
+++ b/docs/translations/en.ts
@@ -136,371 +136,397 @@
-
+
+ Language
+
+
+
+
Show version on window title
-
+
+
Alber v%1
-
+
Alber
-
+
Remember window position
-
+
General Settings
-
+
Browse...
-
+
Select Directory
-
+
Default ROMs path
-
+
Enable Discord RPC
-
+
Use portable build
-
+
Print version in console output
-
+
Graphics Settings
-
-
+
+
Null
-
+
OpenGL
-
+
Vulkan
-
+
GPU renderer
-
+
Enable Renderdoc
-
+
Enable shader JIT
-
+
Enable VSync
-
+
Use ubershaders (No stutter, maybe slower)
-
+
Accurate shader multiplication
-
+
Accelerate shaders
-
+
Force shadergen when rendering lights
-
+
Light threshold for forcing shadergen
-
+
Audio Settings
-
+
LLE
-
+
HLE
-
+
DSP emulation
-
+
Enable audio
-
+
Enable AAC audio
-
+
Print DSP firmware
-
+
Mute audio device
-
+
Cubic
-
+
Linear
-
+
Volume curve
-
+
Audio device volume
-
+
Battery Settings
-
+
Battery percentage
-
+
Charger plugged
-
+
SD Card Settings
-
+
Enable virtual SD card
-
+
Write protect virtual SD card
-
+
Interface
-
+
User Interface settings
-
+
General
-
+
General emulator settings
-
+
Graphics
-
+
Graphics emulation and output settings
-
+
Audio
-
+
Audio emulation and output settings
-
+
Battery
-
+
Battery emulation settings
-
+
SD Card
-
+
SD Card emulation settings
+
+
+ Language change successful
+
+
+
+
+ Restart Panda3DS for the new language to be used.
+
+
+
+
+ Language change failed
+
+
+
+
+ The language you selected is not included in Panda3DS. If you're seeing this, someone messed up the language UI code...
+
+
MainWindow
-
+
Alber
-
+
File
-
+
Emulation
-
+
Tools
-
+
About
-
+
Load game
-
+
Load Lua script
-
+
Open Panda3DS folder
-
+
Pause
-
+
Resume
-
+
Reset
-
+
Configure
-
+
Dump RomFS
-
+
Open Lua Editor
-
+
Open Cheats Editor
-
+
Open Patch Window
-
+
Open Shader Editor
-
+
Dump loaded DSP firmware
-
+
About Panda3DS
diff --git a/include/frontend_settings.hpp b/include/frontend_settings.hpp
index 1a78ab66..ae967879 100644
--- a/include/frontend_settings.hpp
+++ b/include/frontend_settings.hpp
@@ -24,6 +24,7 @@ struct FrontendSettings {
Theme theme = Theme::Dark;
WindowIcon icon = WindowIcon::Rpog;
+ std::string language = "en";
static Theme themeFromString(std::string inString);
static const char* themeToString(Theme theme);
diff --git a/include/panda_qt/config_window.hpp b/include/panda_qt/config_window.hpp
index 9c003753..1d37a8ca 100644
--- a/include/panda_qt/config_window.hpp
+++ b/include/panda_qt/config_window.hpp
@@ -45,6 +45,8 @@ class ConfigWindow : public QDialog {
void setTheme(FrontendSettings::Theme theme);
void setIcon(FrontendSettings::WindowIcon icon);
+ QComboBox* createLanguageSelect();
+
public:
ConfigWindow(ConfigCallback configCallback, MainWindowCallback windowCallback, const EmulatorConfig& config, QWidget* parent = nullptr);
~ConfigWindow();
diff --git a/src/config.cpp b/src/config.cpp
index fd4d969d..73b5d664 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -141,6 +141,7 @@ void EmulatorConfig::load() {
frontendSettings.theme = FrontendSettings::themeFromString(toml::find_or(ui, "Theme", "dark"));
frontendSettings.icon = FrontendSettings::iconFromString(toml::find_or(ui, "WindowIcon", "rpog"));
+ frontendSettings.language = toml::find_or(ui, "Language", "en");
}
}
}
@@ -202,6 +203,7 @@ void EmulatorConfig::save() {
data["UI"]["Theme"] = std::string(FrontendSettings::themeToString(frontendSettings.theme));
data["UI"]["WindowIcon"] = std::string(FrontendSettings::iconToString(frontendSettings.icon));
+ data["UI"]["Language"] = frontendSettings.language;
std::ofstream file(path, std::ios::out);
file << data;
diff --git a/src/panda_qt/config_window.cpp b/src/panda_qt/config_window.cpp
index 549f8990..519a4a22 100644
--- a/src/panda_qt/config_window.cpp
+++ b/src/panda_qt/config_window.cpp
@@ -12,7 +12,7 @@ ConfigWindow::ConfigWindow(ConfigCallback configCallback, MainWindowCallback win
// Set the window title of the main window appropriately if we enable showing the app version on the window
if (config.windowSettings.showAppVersion) {
- getMainWindow()->setWindowTitle("Alber v" PANDA3DS_VERSION);
+ getMainWindow()->setWindowTitle(tr("Alber v%1").arg(PANDA3DS_VERSION));
}
// Initialize the widget list and the widget container widgets
@@ -96,6 +96,9 @@ ConfigWindow::ConfigWindow(ConfigCallback configCallback, MainWindowCallback win
});
guiLayout->addRow(tr("Window icon"), iconSelect);
+ QComboBox* languageSelect = createLanguageSelect();
+ guiLayout->addRow(tr("Language"), languageSelect);
+
QCheckBox* showAppVersion = new QCheckBox(tr("Show version on window title"));
showAppVersion->setChecked(config.windowSettings.showAppVersion);
connect(showAppVersion, &QCheckBox::toggled, this, [&](bool checked) {
diff --git a/src/panda_qt/main_window.cpp b/src/panda_qt/main_window.cpp
index c3a04f88..c4d53697 100644
--- a/src/panda_qt/main_window.cpp
+++ b/src/panda_qt/main_window.cpp
@@ -3,7 +3,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -15,6 +14,8 @@
#include "version.hpp"
MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent), keyboardMappings(InputMappings::defaultKeyboardMappings()) {
+ emu = new Emulator();
+
loadTranslation();
setWindowTitle(tr("Alber"));
@@ -77,7 +78,6 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
auto aboutAction = aboutMenu->addAction(tr("About Panda3DS"));
connect(aboutAction, &QAction::triggered, this, &MainWindow::showAboutMenu);
- emu = new Emulator();
emu->setOutputSize(screen->surfaceWidth, screen->surfaceHeight);
// Set up misc objects
@@ -680,32 +680,4 @@ void MainWindow::setupControllerSensors(SDL_GameController* controller) {
if (haveAccelerometer) {
SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE);
}
-}
-
-void MainWindow::loadTranslation() {
- // TODO: This should become a member variable when we allow changing language at runtime.
- QTranslator* translator = nullptr;
-
- auto language = QString::fromStdString("el");
- const QString baseDir = QStringLiteral(":/translations");
- QString basePath = QStringLiteral("%1/%2.qm").arg(baseDir).arg(language);
-
- if (QFile::exists(basePath)) {
- if (translator != nullptr) {
- qApp->removeTranslator(translator);
- }
-
- translator = new QTranslator(qApp);
- if (!translator->load(basePath)) {
- QMessageBox::warning(
- nullptr, QStringLiteral("Translation Error"),
- QStringLiteral("Failed to find load translation file for '%1':\n%2").arg(language).arg(basePath)
- );
- delete translator;
- } else {
- qApp->installTranslator(translator);
- }
- } else {
- printf("Language file %s does not exist\n", basePath.toStdString().c_str());
- }
}
\ No newline at end of file
diff --git a/src/panda_qt/translations.cpp b/src/panda_qt/translations.cpp
new file mode 100644
index 00000000..5054a0d4
--- /dev/null
+++ b/src/panda_qt/translations.cpp
@@ -0,0 +1,91 @@
+#include
+#include
+#include
+#include
+
+#include "panda_qt/config_window.hpp"
+#include "panda_qt/main_window.hpp"
+
+void MainWindow::loadTranslation() {
+ // TODO: This should become a member variable when we allow changing language at runtime.
+ QTranslator* translator = nullptr;
+
+ // Fetch the .qm file for our language and load it
+ auto language = QString::fromStdString(emu->getConfig().frontendSettings.language);
+ const QString baseDir = QStringLiteral(":/translations");
+ const QString basePath = QStringLiteral("%1/%2.qm").arg(baseDir).arg(language);
+
+ if (QFile::exists(basePath)) {
+ if (translator != nullptr) {
+ qApp->removeTranslator(translator);
+ }
+
+ translator = new QTranslator(qApp);
+ if (!translator->load(basePath)) {
+ QMessageBox::warning(
+ nullptr, QStringLiteral("Translation Error"),
+ QStringLiteral("Failed to find load translation file for '%1':\n%2").arg(language).arg(basePath)
+ );
+ delete translator;
+ } else {
+ qApp->installTranslator(translator);
+ }
+ } else {
+ printf("Language file %s does not exist. Defaulting to English\n", basePath.toStdString().c_str());
+ }
+}
+
+struct LanguageInfo {
+ QString name; // Full name of the language (for example "English (US)")
+ const char* code; // ISO 639 language code (for example "en_us")
+
+ explicit LanguageInfo(const QString& name, const char* code) : name(name), code(code) {}
+};
+
+// List of languages in the order they should appear in the menu
+// Please keep this list mostly in alphabetical order.
+// Also, for Unicode characters in language names, use Unicode keycodes instead of writing out the name,
+// as some compilers/toolchains may not enjoy Unicode in source files.
+static std::array languages = {
+ LanguageInfo(QStringLiteral(u"English"), "en"), // English
+ LanguageInfo(QStringLiteral(u"\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC"), "el"), // Greek
+};
+
+QComboBox* ConfigWindow::createLanguageSelect() {
+ QComboBox* select = new QComboBox();
+
+ for (usize i = 0; i < languages.size(); i++) {
+ const auto& lang = languages[i];
+ select->addItem(lang.name);
+
+ if (config.frontendSettings.language == lang.code) {
+ select->setCurrentIndex(i);
+ }
+ }
+
+ connect(select, &QComboBox::currentIndexChanged, this, [&](int index) {
+ const QString baseDir = QStringLiteral(":/translations");
+ const QString basePath = QStringLiteral("%1/%2.qm").arg(baseDir).arg(languages[index].code);
+
+ if (QFile::exists(basePath)) {
+ config.frontendSettings.language = languages[index].code;
+ updateConfig();
+
+ QMessageBox messageBox(
+ QMessageBox::Icon::Information, tr("Language change successful"),
+ tr("Restart Panda3DS for the new language to be used.")
+ );
+
+ messageBox.exec();
+ } else {
+ QMessageBox messageBox(
+ QMessageBox::Icon::Warning, tr("Language change failed"),
+ tr("The language you selected is not included in Panda3DS. If you're seeing this, someone messed up the language UI code...")
+ );
+
+ messageBox.exec();
+ }
+ });
+
+ return select;
+}
\ No newline at end of file