diff --git a/.github/workflows/Qt_Build.yml b/.github/workflows/Qt_Build.yml
index 3b846a275..cc8055e51 100644
--- a/.github/workflows/Qt_Build.yml
+++ b/.github/workflows/Qt_Build.yml
@@ -107,7 +107,7 @@ jobs:
run: |
sudo apt-get update && sudo apt install libx11-dev libgl1 libglx-mesa0 mesa-common-dev libfuse2 libwayland-dev libgl1-mesa-dev
sudo apt update
- sudo apt install qt6-base-dev qt6-base-private-dev
+ sudo apt install qt6-base-dev qt6-base-private-dev qt6-tools-dev
- name: Install newer Clang
run: |
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 224fea7c0..4f3883c1e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -637,7 +637,7 @@ if(NOT BUILD_HYDRA_CORE AND NOT BUILD_LIBRETRO_CORE)
add_executable(Alber)
if(ENABLE_QT_GUI)
- find_package(Qt6 REQUIRED COMPONENTS Widgets)
+ find_package(Qt6 REQUIRED COMPONENTS Widgets LinguistTools)
if(NOT ENABLE_OPENGL)
message(FATAL_ERROR "Qt frontend requires OpenGL")
endif()
@@ -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
@@ -700,6 +700,24 @@ if(NOT BUILD_HYDRA_CORE AND NOT BUILD_LIBRETRO_CORE)
docs/img/sparkling_icon.png docs/img/battery_icon.png docs/img/sdcard_icon.png
docs/img/rnap_icon.png docs/img/rcow_icon.png docs/img/skyemu_icon.png
)
+
+ # 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})
+
+ set(TRANSLATIONS_QRC ${CMAKE_CURRENT_BINARY_DIR}/translations/translations.qrc)
+ file(WRITE ${TRANSLATIONS_QRC} "\n")
+ foreach (QM ${TRANSLATIONS_QM})
+ message("${QM}")
+ get_filename_component(QM_FILE ${QM} NAME)
+ file(APPEND ${TRANSLATIONS_QRC} "${QM_FILE}\n")
+ endforeach (QM)
+ file(APPEND ${TRANSLATIONS_QRC} "")
+
+ qt_add_resources(TRANSLATIONS ${TRANSLATIONS_QRC})
+ set(APP_RESOURCES ${APP_RESOURCES} ${TRANSLATIONS})
else()
set(FRONTEND_SOURCE_FILES src/panda_sdl/main.cpp src/panda_sdl/frontend_sdl.cpp src/panda_sdl/mappings.cpp)
set(FRONTEND_HEADER_FILES "include/panda_sdl/frontend_sdl.hpp")
diff --git a/docs/translations/el.ts b/docs/translations/el.ts
new file mode 100644
index 000000000..0368d8bda
--- /dev/null
+++ b/docs/translations/el.ts
@@ -0,0 +1,763 @@
+
+
+ AboutWindow
+
+
+
+ Σχετικά με το Panda3DS
+
+
+
+
+ Τo Panda3DS είναι ένας δωρεάν και open source εξομοιωτής του Nintendo 3DS, για Windows, MacOS και Linux
+
+
+
+
+ Επισκεφτείται το panda3ds.com για βοήθεια με το Panda3DS και συνδέσμους στις επίσημες σελίδες υποστήριξης μας.
+
+
+
+
+
+
+
+
+ CheatEditDialog
+
+
+
+ Επεξεργασία Κωδικού
+
+
+
+
+ Όνομα κωδικού
+
+
+
+ CheatEntryWidget
+
+
+
+ Επεξεργασία
+
+
+
+ CheatsWindow
+
+
+
+ Κωδικοί
+
+
+
+
+ Προσθήκη
+
+
+
+
+ Αφαίρεση
+
+
+
+ ConfigWindow
+
+
+
+ Ρυθμίσεις
+
+
+
+
+ Ρυθμίσεις Διεπαφής
+
+
+
+
+ Σύστημα
+
+
+
+
+ Φωτεινό
+
+
+
+
+ Σκοτεινό
+
+
+
+
+ Γεια Σου Γάτα
+
+
+
+
+ Κρέμα
+
+
+
+
+ Χρώματα
+
+
+
+
+ Χαρούμενο Πάντα
+
+
+
+
+ Χαρούμενο Πάντα (χρωματιστό)
+
+
+
+
+ Πάντα που νυστάζει
+
+
+
+
+ Αγελάδα πάντα
+
+
+
+
+ Ο πιγκουίνος από το SkyEmu
+
+
+
+
+ Εικονίδιο Παραθύρου
+
+
+
+
+ Γλώσσα
+
+
+
+
+ Εμφάνιση έκδοσης στον τίτλο του παραθύρου
+
+
+
+
+ Αλβέρτος v%1
+
+
+
+
+ Αλβέρτος
+
+
+
+
+ Αποθήκευση θέσης παραθύρου
+
+
+
+
+ Γενικές Ρυθμίσεις
+
+
+
+
+ Περιήγηση
+
+
+
+
+ Επιλογή φακέλου
+
+
+
+
+ Προεπιλεγμένος φάκελος ROM
+
+
+
+
+ Ενεργοποίηση Discord RPC
+
+
+
+
+ Ενεργοποίηση φορητής εγκατάστασης
+
+
+
+
+ Εκτύπωση έκδοσης στην κονσόλα
+
+
+
+
+ Ρυθμίσεις Γραφικών
+
+
+
+
+
+ Κανένα
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Πυρήνας GPU
+
+
+
+
+ Ενεργοποίηση Renderdoc
+
+
+
+
+ Ενεργοποίηση μεταγλωττιστή shaders
+
+
+
+
+ Ενεργοποίηση VSync
+
+
+
+
+ Χρήση ubershaders (Χωρίς stutter, ίσως πιο αργό)
+
+
+
+
+ Ακριβής πολλαπλασιασμός στα shaders
+
+
+
+
+ Επιτάχυνση shaders
+
+
+
+
+ Εξαναγκασμός shadergen όταν υπάρχουν φώτα
+
+
+
+
+ Αριθμός φωτών για εξαναγκασμό shadergen
+
+
+
+
+ Ρυθμίσεις Ήχου
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Εξομοίωση DSP
+
+
+
+
+ Ενεργοποίηση ήχου
+
+
+
+
+ Ενεργοποίηση ήχου AAC
+
+
+
+
+ Εκτύπωση λογισμικού DSP
+
+
+
+
+ Σίγαση συσκευής ήχου
+
+
+
+
+ Κυβική
+
+
+
+
+ Γραμμική
+
+
+
+
+ Κλίμακα ήχου
+
+
+
+
+ Ένταση ήχου
+
+
+
+
+ Ρυθμίσεις μπαταρίας
+
+
+
+
+ Ποσοστό μπαταρίας
+
+
+
+
+ Φορτιστής
+
+
+
+
+ Ρυθμίσης κάρτας SD
+
+
+
+
+ Ενεργοποίηση εικονικής SD
+
+
+
+
+ Προστασία της SD από εγγραφή
+
+
+
+
+ Διεπαφή
+
+
+
+
+ Ρυθμίσεις διεπαφής
+
+
+
+
+ Γενικά
+
+
+
+
+ Γενικές ρυθμίσεις εξομοιωτή
+
+
+
+
+ Γραφικά
+
+
+
+
+ Ρυθμίσεις εξομοίωσης γραφικών
+
+
+
+
+ Ήχος
+
+
+
+
+ Ρυθμίσεις εξομοίωσης ήχου
+
+
+
+
+ Μπαταρία
+
+
+
+
+ Ρυθμίσεις εξομοίωσης μπαταρίας
+
+
+
+
+ Κάρτα SD
+
+
+
+
+ Ρυθμίσεις εξομοίωσης κάρτας SD
+
+
+
+
+ Επιτυχία αλλαγής γλώσσας
+
+
+
+
+ Επανεκκινήστε το Panda3DS για να εφαρμοστεί η νέα γλώσσα.
+
+
+
+
+ Αποτυχία αλλαγής γλώσσας
+
+
+
+
+ Το Panda3DS δεν υποστηρίζει τον γλώσσα που επιλέξατε. Αν το βλέπετε αυτό, κάποιος έκανε λάθος στον κώδικα, κατηγορήστε τον Πάρη...
+
+
+
+ MainWindow
+
+
+
+ Αλβέρτος
+
+
+
+
+ Αρχεία
+
+
+
+
+ Εξομοίωση
+
+
+
+
+ Εργαλεία
+
+
+
+
+ Σχετικά
+
+
+
+
+ Φόρτωση παιχνιδιού
+
+
+
+
+ Φόρτωση αρχείου Lua
+
+
+
+
+ Άνοιγμα φακέλου Panda3DS
+
+
+
+
+ Παύση
+
+
+
+
+ Συνέχεια
+
+
+
+
+ Επανέναρξη
+
+
+
+
+ Ρύθμιση
+
+
+
+
+
+
+
+
+
+ Άνοιγμα Lua Editor
+
+
+
+
+ Άνοιγμα Editor κωδικών
+
+
+
+
+ Άνοιγμα παραθύρου για patching
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Σχετικά με το Panda3DS
+
+
+
+
+ Επιλέξτε 3DS ROM για να φορτώσετε
+
+
+
+
+
+
+
+
+
+ Επιλέξτε αρχείο Lua για να φορτώσετε
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ΟΚ
+
+
+
+
+ Δεν βρέθηκε RomFS
+
+
+
+
+ Δεν βρέθηκε RomFS στην εφαρμογή που έχει φορτωθεί
+
+
+
+
+ Επιλέξτε αρχείο
+
+
+
+
+
+
+
+
+
+ Δεν έχει φορτωθεί DSP firmware
+
+
+
+
+
+
+
+
+
+ Αποτυχία ανοίγματος του αρχείου εξόδου
+
+
+
+
+
+
+
+
+ PatchWindow
+
+
+
+
+
+
+
+
+ Επιλογή αρχείου εισόδου
+
+
+
+
+
+ Επιλέξτε
+
+
+
+
+
+ Επιλογή αρχείου patch
+
+
+
+
+ Εφαρμογή patch
+
+
+
+
+ Επιλέξτε αρχείο να κάνετε patch
+
+
+
+
+
+ Όλα τα αρχεία (*.*)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Παρακαλούμε διαλέξτε και αρχείο εισόδου και αρχείο patch
+
+
+
+
+ Επιλογή αρχείου
+
+
+
+
+ Δεν επιλέχθηκε φάκελος εξόδου
+
+
+
+
+ Δεν επιλέχθηκε αρχείο εξόδου. Δεν έγινε patching
+
+
+
+
+ Άγνωστο είδος patch
+
+
+
+
+ Άγνωστο είδος αρχείου patch. Υποστηρίζονται αρχεία IPS, UPS και BPS
+
+
+
+
+ Αποτυχία ανοίγματος των αρχείων εισόδου
+
+
+
+
+ Βεβαιωθείτε ότι είναι σε φάκελο που έχει πρόσβαση το Panda3DS
+
+
+
+
+ Επιτυχής Εφαρμογή Patch
+
+
+
+
+ To αρχείο σας έγινε patch με επιτυχία
+
+
+
+
+
+
+
+
+
+ Το patch εφαρμόστηκε με επιτυχία αλλά ανιχνεύτηκε σφάλμα στο checksum. Ενδέχεται τα αρχεία εισόδου η εξόδου να είναι λανθασμένα
+
+
+
+
+ Σφάλμα στο patching
+
+
+
+
+ Προέκυψε σφάλμα στο patching
+
+
+
+ PatchWindow::PatchWindow
+
+
+
+ ΟΚ
+
+
+
+ ShaderEditorWindow
+
+
+
+ Επαναφόρτωση shader
+
+
+
+ TextEditorWindow
+
+
+
+
+
+
+
+
+ Φόρτωση αρχείου
+
+
+
\ No newline at end of file
diff --git a/docs/translations/en.ts b/docs/translations/en.ts
new file mode 100644
index 000000000..4a70fabb3
--- /dev/null
+++ b/docs/translations/en.ts
@@ -0,0 +1,766 @@
+
+
+
+
+ AboutWindow
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ CheatEditDialog
+
+
+
+
+
+
+
+
+
+
+
+
+ CheatEntryWidget
+
+
+
+
+
+
+
+ CheatsWindow
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ConfigWindow
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MainWindow
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PatchWindow
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PatchWindow::PatchWindow
+
+
+
+
+
+
+
+ ShaderEditorWindow
+
+
+
+
+
+
+
+ TextEditorWindow
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/include/frontend_settings.hpp b/include/frontend_settings.hpp
index 1a78ab66f..ae9678792 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 9c0037534..1d37a8caa 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/include/panda_qt/main_window.hpp b/include/panda_qt/main_window.hpp
index eb1cfb16f..ed54ad84d 100644
--- a/include/panda_qt/main_window.hpp
+++ b/include/panda_qt/main_window.hpp
@@ -126,6 +126,7 @@ class MainWindow : public QMainWindow {
void setupControllerSensors(SDL_GameController* controller);
void sendMessage(const EmulatorMessage& message);
void dispatchMessage(const EmulatorMessage& message);
+ void loadTranslation();
// Tracks whether we are using an OpenGL-backed renderer or a Vulkan-backed renderer
bool usingGL = false;
diff --git a/src/config.cpp b/src/config.cpp
index fd4d969d4..73b5d6644 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 7f42acab9..519a4a227 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) {
@@ -103,7 +106,7 @@ ConfigWindow::ConfigWindow(ConfigCallback configCallback, MainWindowCallback win
updateConfig();
// Update main window title
- getMainWindow()->setWindowTitle(checked ? "Alber v" PANDA3DS_VERSION : "Alber");
+ getMainWindow()->setWindowTitle(checked ? tr("Alber v%1").arg(PANDA3DS_VERSION) : tr("Alber"));
});
connectCheckbox(showAppVersion, config.windowSettings.showAppVersion);
guiLayout->addRow(showAppVersion);
diff --git a/src/panda_qt/main_window.cpp b/src/panda_qt/main_window.cpp
index 5af31d737..c4d536975 100644
--- a/src/panda_qt/main_window.cpp
+++ b/src/panda_qt/main_window.cpp
@@ -14,6 +14,9 @@
#include "version.hpp"
MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent), keyboardMappings(InputMappings::defaultKeyboardMappings()) {
+ emu = new Emulator();
+
+ loadTranslation();
setWindowTitle(tr("Alber"));
// Enable drop events for loading ROMs
@@ -75,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
@@ -678,4 +680,4 @@ void MainWindow::setupControllerSensors(SDL_GameController* controller) {
if (haveAccelerometer) {
SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE);
}
-}
+}
\ 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 000000000..5054a0d4c
--- /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