summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-x.ci/scripts/linux/docker.sh2
-rwxr-xr-x.ci/scripts/windows/docker.sh2
-rw-r--r--CMakeLists.txt5
-rw-r--r--README.md2
-rw-r--r--dist/languages/.gitignore2
-rw-r--r--dist/languages/.tx/config8
-rw-r--r--dist/languages/README.md1
-rw-r--r--src/yuzu/CMakeLists.txt33
-rw-r--r--src/yuzu/configuration/config.cpp2
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp9
-rw-r--r--src/yuzu/configuration/configure_dialog.h6
-rw-r--r--src/yuzu/configuration/configure_ui.cpp31
-rw-r--r--src/yuzu/configuration/configure_ui.h7
-rw-r--r--src/yuzu/configuration/configure_ui.ui188
-rw-r--r--src/yuzu/main.cpp42
-rw-r--r--src/yuzu/main.h5
-rw-r--r--src/yuzu/uisettings.h1
17 files changed, 260 insertions, 86 deletions
diff --git a/.ci/scripts/linux/docker.sh b/.ci/scripts/linux/docker.sh
index 5559a527c..277775ef6 100755
--- a/.ci/scripts/linux/docker.sh
+++ b/.ci/scripts/linux/docker.sh
@@ -5,7 +5,7 @@ cd /yuzu
5ccache -s 5ccache -s
6 6
7mkdir build || true && cd build 7mkdir build || true && cd build
8cmake .. -G Ninja -DDISPLAY_VERSION=$1 -DYUZU_USE_BUNDLED_UNICORN=ON -DYUZU_USE_QT_WEB_ENGINE=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON 8cmake .. -G Ninja -DDISPLAY_VERSION=$1 -DYUZU_USE_BUNDLED_UNICORN=ON -DYUZU_USE_QT_WEB_ENGINE=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON
9 9
10ninja 10ninja
11 11
diff --git a/.ci/scripts/windows/docker.sh b/.ci/scripts/windows/docker.sh
index d53281741..adfd636fa 100755
--- a/.ci/scripts/windows/docker.sh
+++ b/.ci/scripts/windows/docker.sh
@@ -5,7 +5,7 @@ cd /yuzu
5ccache -s 5ccache -s
6 6
7mkdir build || true && cd build 7mkdir build || true && cd build
8cmake .. -G Ninja -DDISPLAY_VERSION=$1 -DCMAKE_TOOLCHAIN_FILE="$(pwd)/../CMakeModules/MinGWCross.cmake" -DUSE_CCACHE=ON -DYUZU_USE_BUNDLED_UNICORN=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DCMAKE_BUILD_TYPE=Release 8cmake .. -G Ninja -DDISPLAY_VERSION=$1 -DCMAKE_TOOLCHAIN_FILE="$(pwd)/../CMakeModules/MinGWCross.cmake" -DUSE_CCACHE=ON -DYUZU_USE_BUNDLED_UNICORN=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_QT_TRANSLATION=ON
9ninja 9ninja
10 10
11ccache -s 11ccache -s
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ce46a2c2b..7a49318aa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,6 +13,7 @@ project(yuzu)
13option(ENABLE_SDL2 "Enable the SDL2 frontend" ON) 13option(ENABLE_SDL2 "Enable the SDL2 frontend" ON)
14 14
15option(ENABLE_QT "Enable the Qt frontend" ON) 15option(ENABLE_QT "Enable the Qt frontend" ON)
16option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF)
16CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" ON "ENABLE_QT;MSVC" OFF) 17CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" ON "ENABLE_QT;MSVC" OFF)
17 18
18option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON) 19option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
@@ -224,6 +225,10 @@ if(ENABLE_QT)
224 if (YUZU_USE_QT_WEB_ENGINE) 225 if (YUZU_USE_QT_WEB_ENGINE)
225 find_package(Qt5 COMPONENTS WebEngineCore WebEngineWidgets) 226 find_package(Qt5 COMPONENTS WebEngineCore WebEngineWidgets)
226 endif() 227 endif()
228
229 if (ENABLE_QT_TRANSLATION)
230 find_package(Qt5 REQUIRED COMPONENTS LinguistTools ${QT_PREFIX_HINT})
231 endif()
227 if (NOT Qt5_FOUND) 232 if (NOT Qt5_FOUND)
228 list(APPEND CONAN_REQUIRED_LIBS "qt/5.14.1@bincrafters/stable") 233 list(APPEND CONAN_REQUIRED_LIBS "qt/5.14.1@bincrafters/stable")
229 endif() 234 endif()
diff --git a/README.md b/README.md
index e4ecb531d..981c8ef24 100644
--- a/README.md
+++ b/README.md
@@ -24,6 +24,8 @@ Most of the development happens on GitHub. It's also where [our central reposito
24 24
25If you want to contribute please take a look at the [Contributor's Guide](https://github.com/yuzu-emu/yuzu/wiki/Contributing) and [Developer Information](https://github.com/yuzu-emu/yuzu/wiki/Developer-Information). You should also contact any of the developers on Discord in order to know about the current state of the emulator. 25If you want to contribute please take a look at the [Contributor's Guide](https://github.com/yuzu-emu/yuzu/wiki/Contributing) and [Developer Information](https://github.com/yuzu-emu/yuzu/wiki/Developer-Information). You should also contact any of the developers on Discord in order to know about the current state of the emulator.
26 26
27If you want to contribute to the user interface translation, please check out the [yuzu project on transifex](https://www.transifex.com/yuzu-emulator/yuzu). We centralize translation work there, and periodically upstream translations.
28
27### Building 29### Building
28 30
29* __Windows__: [Windows Build](https://github.com/yuzu-emu/yuzu/wiki/Building-For-Windows) 31* __Windows__: [Windows Build](https://github.com/yuzu-emu/yuzu/wiki/Building-For-Windows)
diff --git a/dist/languages/.gitignore b/dist/languages/.gitignore
new file mode 100644
index 000000000..27e5a0158
--- /dev/null
+++ b/dist/languages/.gitignore
@@ -0,0 +1,2 @@
1# Ignore the source language file
2en.ts
diff --git a/dist/languages/.tx/config b/dist/languages/.tx/config
new file mode 100644
index 000000000..0d9b512ea
--- /dev/null
+++ b/dist/languages/.tx/config
@@ -0,0 +1,8 @@
1[main]
2host = https://www.transifex.com
3
4[yuzu.emulator]
5file_filter = <lang>.ts
6source_file = en.ts
7source_lang = en
8type = QT
diff --git a/dist/languages/README.md b/dist/languages/README.md
new file mode 100644
index 000000000..61981ab1d
--- /dev/null
+++ b/dist/languages/README.md
@@ -0,0 +1 @@
This directory stores translation patches (TS files) for yuzu Qt frontend. This directory is linked with [yuzu project on transifex](https://www.transifex.com/yuzu-emulator/yuzu), so you can update the translation by executing `tx pull -a`. If you want to contribute to the translation, please go the transifex link and submit your translation there. This directory on the main repo will be synchronized with transifex periodically. Do not directly open PRs on github to modify the translation.
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index a862b2610..656096c9f 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -133,11 +133,44 @@ file(GLOB COMPAT_LIST
133file(GLOB_RECURSE ICONS ${PROJECT_SOURCE_DIR}/dist/icons/*) 133file(GLOB_RECURSE ICONS ${PROJECT_SOURCE_DIR}/dist/icons/*)
134file(GLOB_RECURSE THEMES ${PROJECT_SOURCE_DIR}/dist/qt_themes/*) 134file(GLOB_RECURSE THEMES ${PROJECT_SOURCE_DIR}/dist/qt_themes/*)
135 135
136if (ENABLE_QT_TRANSLATION)
137 set(YUZU_QT_LANGUAGES "${PROJECT_SOURCE_DIR}/dist/languages" CACHE PATH "Path to the translation bundle for the Qt frontend")
138 option(GENERATE_QT_TRANSLATION "Generate en.ts as the translation source file" OFF)
139
140 # Update source TS file if enabled
141 if (GENERATE_QT_TRANSLATION)
142 get_target_property(SRCS yuzu SOURCES)
143 qt5_create_translation(QM_FILES ${SRCS} ${UIS} ${YUZU_QT_LANGUAGES}/en.ts)
144 add_custom_target(translation ALL DEPENDS ${YUZU_QT_LANGUAGES}/en.ts)
145 endif()
146
147 # Find all TS files except en.ts
148 file(GLOB_RECURSE LANGUAGES_TS ${YUZU_QT_LANGUAGES}/*.ts)
149 list(REMOVE_ITEM LANGUAGES_TS ${YUZU_QT_LANGUAGES}/en.ts)
150
151 # Compile TS files to QM files
152 qt5_add_translation(LANGUAGES_QM ${LANGUAGES_TS})
153
154 # Build a QRC file from the QM file list
155 set(LANGUAGES_QRC ${CMAKE_CURRENT_BINARY_DIR}/languages.qrc)
156 file(WRITE ${LANGUAGES_QRC} "<RCC><qresource prefix=\"languages\">\n")
157 foreach (QM ${LANGUAGES_QM})
158 get_filename_component(QM_FILE ${QM} NAME)
159 file(APPEND ${LANGUAGES_QRC} "<file>${QM_FILE}</file>\n")
160 endforeach (QM)
161 file(APPEND ${LANGUAGES_QRC} "</qresource></RCC>")
162
163 # Add the QRC file to package in all QM files
164 qt5_add_resources(LANGUAGES ${LANGUAGES_QRC})
165else()
166 set(LANGUAGES)
167endif()
136 168
137target_sources(yuzu 169target_sources(yuzu
138 PRIVATE 170 PRIVATE
139 ${COMPAT_LIST} 171 ${COMPAT_LIST}
140 ${ICONS} 172 ${ICONS}
173 ${LANGUAGES}
141 ${THEMES} 174 ${THEMES}
142) 175)
143 176
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 805bb954b..59a193edd 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -611,6 +611,7 @@ void Config::ReadPathValues() {
611 } 611 }
612 } 612 }
613 UISettings::values.recent_files = ReadSetting(QStringLiteral("recentFiles")).toStringList(); 613 UISettings::values.recent_files = ReadSetting(QStringLiteral("recentFiles")).toStringList();
614 UISettings::values.language = ReadSetting(QStringLiteral("language"), QString{}).toString();
614 615
615 qt_config->endGroup(); 616 qt_config->endGroup();
616} 617}
@@ -1095,6 +1096,7 @@ void Config::SavePathValues() {
1095 } 1096 }
1096 qt_config->endArray(); 1097 qt_config->endArray();
1097 WriteSetting(QStringLiteral("recentFiles"), UISettings::values.recent_files); 1098 WriteSetting(QStringLiteral("recentFiles"), UISettings::values.recent_files);
1099 WriteSetting(QStringLiteral("language"), UISettings::values.language, QString{});
1098 1100
1099 qt_config->endGroup(); 1101 qt_config->endGroup();
1100} 1102}
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index a5afb354f..4e30dc51e 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -23,6 +23,7 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry)
23 SetConfiguration(); 23 SetConfiguration();
24 PopulateSelectionList(); 24 PopulateSelectionList();
25 25
26 connect(ui->uiTab, &ConfigureUi::LanguageChanged, this, &ConfigureDialog::OnLanguageChanged);
26 connect(ui->selectorList, &QListWidget::itemSelectionChanged, this, 27 connect(ui->selectorList, &QListWidget::itemSelectionChanged, this,
27 &ConfigureDialog::UpdateVisibleTabs); 28 &ConfigureDialog::UpdateVisibleTabs);
28 29
@@ -98,6 +99,14 @@ void ConfigureDialog::PopulateSelectionList() {
98 } 99 }
99} 100}
100 101
102void ConfigureDialog::OnLanguageChanged(const QString& locale) {
103 emit LanguageChanged(locale);
104 // first apply the configuration, and then restore the display
105 ApplyConfiguration();
106 RetranslateUI();
107 SetConfiguration();
108}
109
101void ConfigureDialog::UpdateVisibleTabs() { 110void ConfigureDialog::UpdateVisibleTabs() {
102 const auto items = ui->selectorList->selectedItems(); 111 const auto items = ui->selectorList->selectedItems();
103 if (items.isEmpty()) { 112 if (items.isEmpty()) {
diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h
index 2d3bfc2da..4289bc225 100644
--- a/src/yuzu/configuration/configure_dialog.h
+++ b/src/yuzu/configuration/configure_dialog.h
@@ -22,6 +22,12 @@ public:
22 22
23 void ApplyConfiguration(); 23 void ApplyConfiguration();
24 24
25private slots:
26 void OnLanguageChanged(const QString& locale);
27
28signals:
29 void LanguageChanged(const QString& locale);
30
25private: 31private:
26 void changeEvent(QEvent* event) override; 32 void changeEvent(QEvent* event) override;
27 33
diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp
index 94424ee44..24b6c5b72 100644
--- a/src/yuzu/configuration/configure_ui.cpp
+++ b/src/yuzu/configuration/configure_ui.cpp
@@ -5,6 +5,7 @@
5#include <array> 5#include <array>
6#include <utility> 6#include <utility>
7 7
8#include <QDirIterator>
8#include "common/common_types.h" 9#include "common/common_types.h"
9#include "core/settings.h" 10#include "core/settings.h"
10#include "ui_configure_ui.h" 11#include "ui_configure_ui.h"
@@ -29,6 +30,8 @@ constexpr std::array row_text_names{
29ConfigureUi::ConfigureUi(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureUi) { 30ConfigureUi::ConfigureUi(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureUi) {
30 ui->setupUi(this); 31 ui->setupUi(this);
31 32
33 InitializeLanguageComboBox();
34
32 for (const auto& theme : UISettings::themes) { 35 for (const auto& theme : UISettings::themes) {
33 ui->theme_combobox->addItem(QString::fromUtf8(theme.first), 36 ui->theme_combobox->addItem(QString::fromUtf8(theme.first),
34 QString::fromUtf8(theme.second)); 37 QString::fromUtf8(theme.second));
@@ -72,6 +75,8 @@ void ConfigureUi::RequestGameListUpdate() {
72 75
73void ConfigureUi::SetConfiguration() { 76void ConfigureUi::SetConfiguration() {
74 ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme)); 77 ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme));
78 ui->language_combobox->setCurrentIndex(
79 ui->language_combobox->findData(UISettings::values.language));
75 ui->show_add_ons->setChecked(UISettings::values.show_add_ons); 80 ui->show_add_ons->setChecked(UISettings::values.show_add_ons);
76 ui->icon_size_combobox->setCurrentIndex( 81 ui->icon_size_combobox->setCurrentIndex(
77 ui->icon_size_combobox->findData(UISettings::values.icon_size)); 82 ui->icon_size_combobox->findData(UISettings::values.icon_size));
@@ -100,6 +105,25 @@ void ConfigureUi::RetranslateUI() {
100 } 105 }
101} 106}
102 107
108void ConfigureUi::InitializeLanguageComboBox() {
109 ui->language_combobox->addItem(tr("<System>"), QString{});
110 ui->language_combobox->addItem(tr("English"), QStringLiteral("en"));
111 QDirIterator it(QStringLiteral(":/languages"), QDirIterator::NoIteratorFlags);
112 while (it.hasNext()) {
113 QString locale = it.next();
114 locale.truncate(locale.lastIndexOf(QLatin1Char{'.'}));
115 locale.remove(0, locale.lastIndexOf(QLatin1Char{'/'}) + 1);
116 const QString lang = QLocale::languageToString(QLocale(locale).language());
117 ui->language_combobox->addItem(lang, locale);
118 }
119
120 // Unlike other configuration changes, interface language changes need to be reflected on the
121 // interface immediately. This is done by passing a signal to the main window, and then
122 // retranslating when passing back.
123 connect(ui->language_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
124 &ConfigureUi::OnLanguageChanged);
125}
126
103void ConfigureUi::InitializeIconSizeComboBox() { 127void ConfigureUi::InitializeIconSizeComboBox() {
104 for (const auto& size : default_icon_sizes) { 128 for (const auto& size : default_icon_sizes) {
105 ui->icon_size_combobox->addItem(QString::fromUtf8(size.second), size.first); 129 ui->icon_size_combobox->addItem(QString::fromUtf8(size.second), size.first);
@@ -147,3 +171,10 @@ void ConfigureUi::UpdateSecondRowComboBox(bool init) {
147 ui->row_2_text_combobox->removeItem( 171 ui->row_2_text_combobox->removeItem(
148 ui->row_2_text_combobox->findData(ui->row_1_text_combobox->currentData())); 172 ui->row_2_text_combobox->findData(ui->row_1_text_combobox->currentData()));
149} 173}
174
175void ConfigureUi::OnLanguageChanged(int index) {
176 if (index == -1)
177 return;
178
179 emit LanguageChanged(ui->language_combobox->itemData(index).toString());
180}
diff --git a/src/yuzu/configuration/configure_ui.h b/src/yuzu/configuration/configure_ui.h
index d471afe99..c30bcf6ff 100644
--- a/src/yuzu/configuration/configure_ui.h
+++ b/src/yuzu/configuration/configure_ui.h
@@ -20,6 +20,12 @@ public:
20 20
21 void ApplyConfiguration(); 21 void ApplyConfiguration();
22 22
23private slots:
24 void OnLanguageChanged(int index);
25
26signals:
27 void LanguageChanged(const QString& locale);
28
23private: 29private:
24 void RequestGameListUpdate(); 30 void RequestGameListUpdate();
25 31
@@ -28,6 +34,7 @@ private:
28 void changeEvent(QEvent*) override; 34 void changeEvent(QEvent*) override;
29 void RetranslateUI(); 35 void RetranslateUI();
30 36
37 void InitializeLanguageComboBox();
31 void InitializeIconSizeComboBox(); 38 void InitializeIconSizeComboBox();
32 void InitializeRowComboBoxes(); 39 void InitializeRowComboBoxes();
33 40
diff --git a/src/yuzu/configuration/configure_ui.ui b/src/yuzu/configuration/configure_ui.ui
index bd5c5d3c2..0b81747d7 100644
--- a/src/yuzu/configuration/configure_ui.ui
+++ b/src/yuzu/configuration/configure_ui.ui
@@ -13,112 +13,132 @@
13 <property name="windowTitle"> 13 <property name="windowTitle">
14 <string>Form</string> 14 <string>Form</string>
15 </property> 15 </property>
16 <layout class="QHBoxLayout" name="HorizontalLayout"> 16 <layout class="QVBoxLayout" name="verticalLayout">
17 <item> 17 <item>
18 <layout class="QVBoxLayout" name="VerticalLayout"> 18 <widget class="QGroupBox" name="general_groupBox">
19 <item> 19 <property name="title">
20 <widget class="QGroupBox" name="GeneralGroupBox"> 20 <string>General</string>
21 <property name="title"> 21 </property>
22 <string>General</string> 22 <layout class="QHBoxLayout" name="horizontalLayout">
23 </property> 23 <item>
24 <layout class="QHBoxLayout" name="horizontalLayout"> 24 <layout class="QVBoxLayout" name="verticalLayout_2">
25 <item> 25 <item>
26 <layout class="QVBoxLayout" name="verticalLayout"> 26 <widget class="QLabel" name="label_change_language_info">
27 <property name="text">
28 <string>Note: Changing language will apply your configuration.</string>
29 </property>
30 <property name="wordWrap">
31 <bool>true</bool>
32 </property>
33 </widget>
34 </item>
35 <item>
36 <layout class="QHBoxLayout" name="horizontalLayout_2">
37 <item>
38 <widget class="QLabel" name="language_label">
39 <property name="text">
40 <string>Interface language:</string>
41 </property>
42 </widget>
43 </item>
44 <item>
45 <widget class="QComboBox" name="language_combobox"/>
46 </item>
47 </layout>
48 </item>
49 <item>
50 <layout class="QHBoxLayout" name="horizontalLayout_3">
51 <item>
52 <widget class="QLabel" name="theme_label">
53 <property name="text">
54 <string>Theme:</string>
55 </property>
56 </widget>
57 </item>
27 <item> 58 <item>
28 <layout class="QHBoxLayout" name="horizontalLayout_3"> 59 <widget class="QComboBox" name="theme_combobox"/>
29 <item>
30 <widget class="QLabel" name="theme_label">
31 <property name="text">
32 <string>Theme:</string>
33 </property>
34 </widget>
35 </item>
36 <item>
37 <widget class="QComboBox" name="theme_combobox"/>
38 </item>
39 </layout>
40 </item> 60 </item>
41 </layout> 61 </layout>
42 </item> 62 </item>
43 </layout> 63 </layout>
44 </widget> 64 </item>
45 </item> 65 </layout>
46 <item> 66 </widget>
47 <widget class="QGroupBox" name="GameListGroupBox"> 67 </item>
48 <property name="title"> 68 <item>
49 <string>Game List</string> 69 <widget class="QGroupBox" name="GameListGroupBox">
50 </property> 70 <property name="title">
51 <layout class="QHBoxLayout" name="GameListHorizontalLayout"> 71 <string>Game List</string>
72 </property>
73 <layout class="QHBoxLayout" name="GameListHorizontalLayout">
74 <item>
75 <layout class="QVBoxLayout" name="GeneralVerticalLayout">
52 <item> 76 <item>
53 <layout class="QVBoxLayout" name="GeneralVerticalLayout"> 77 <widget class="QCheckBox" name="show_add_ons">
78 <property name="text">
79 <string>Show Add-Ons Column</string>
80 </property>
81 </widget>
82 </item>
83 <item>
84 <layout class="QHBoxLayout" name="icon_size_qhbox_layout_2">
54 <item> 85 <item>
55 <widget class="QCheckBox" name="show_add_ons"> 86 <widget class="QLabel" name="icon_size_label">
56 <property name="text"> 87 <property name="text">
57 <string>Show Add-Ons Column</string> 88 <string>Icon Size:</string>
58 </property> 89 </property>
59 </widget> 90 </widget>
60 </item> 91 </item>
61 <item> 92 <item>
62 <layout class="QHBoxLayout" name="icon_size_qhbox_layout_2"> 93 <widget class="QComboBox" name="icon_size_combobox"/>
63 <item>
64 <widget class="QLabel" name="icon_size_label">
65 <property name="text">
66 <string>Icon Size:</string>
67 </property>
68 </widget>
69 </item>
70 <item>
71 <widget class="QComboBox" name="icon_size_combobox"/>
72 </item>
73 </layout>
74 </item> 94 </item>
95 </layout>
96 </item>
97 <item>
98 <layout class="QHBoxLayout" name="row_1_qhbox_layout">
75 <item> 99 <item>
76 <layout class="QHBoxLayout" name="row_1_qhbox_layout"> 100 <widget class="QLabel" name="row_1_label">
77 <item> 101 <property name="text">
78 <widget class="QLabel" name="row_1_label"> 102 <string>Row 1 Text:</string>
79 <property name="text"> 103 </property>
80 <string>Row 1 Text:</string> 104 </widget>
81 </property>
82 </widget>
83 </item>
84 <item>
85 <widget class="QComboBox" name="row_1_text_combobox"/>
86 </item>
87 </layout>
88 </item> 105 </item>
89 <item> 106 <item>
90 <layout class="QHBoxLayout" name="row_2_qhbox_layout"> 107 <widget class="QComboBox" name="row_1_text_combobox"/>
91 <item> 108 </item>
92 <widget class="QLabel" name="row_2_label"> 109 </layout>
93 <property name="text"> 110 </item>
94 <string>Row 2 Text:</string> 111 <item>
95 </property> 112 <layout class="QHBoxLayout" name="row_2_qhbox_layout">
96 </widget> 113 <item>
97 </item> 114 <widget class="QLabel" name="row_2_label">
98 <item> 115 <property name="text">
99 <widget class="QComboBox" name="row_2_text_combobox"/> 116 <string>Row 2 Text:</string>
100 </item> 117 </property>
101 </layout> 118 </widget>
119 </item>
120 <item>
121 <widget class="QComboBox" name="row_2_text_combobox"/>
102 </item> 122 </item>
103 </layout> 123 </layout>
104 </item> 124 </item>
105 </layout> 125 </layout>
106 </widget> 126 </item>
107 </item> 127 </layout>
108 <item> 128 </widget>
109 <spacer name="verticalSpacer"> 129 </item>
110 <property name="orientation"> 130 <item>
111 <enum>Qt::Vertical</enum> 131 <spacer name="verticalSpacer">
112 </property> 132 <property name="orientation">
113 <property name="sizeHint" stdset="0"> 133 <enum>Qt::Vertical</enum>
114 <size> 134 </property>
115 <width>20</width> 135 <property name="sizeHint" stdset="0">
116 <height>40</height> 136 <size>
117 </size> 137 <width>20</width>
118 </property> 138 <height>40</height>
119 </spacer> 139 </size>
120 </item> 140 </property>
121 </layout> 141 </spacer>
122 </item> 142 </item>
123 </layout> 143 </layout>
124 </widget> 144 </widget>
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 6909d65d0..31a635176 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -191,6 +191,8 @@ GMainWindow::GMainWindow()
191 provider(std::make_unique<FileSys::ManualContentProvider>()) { 191 provider(std::make_unique<FileSys::ManualContentProvider>()) {
192 InitializeLogging(); 192 InitializeLogging();
193 193
194 LoadTranslation();
195
194 setAcceptDrops(true); 196 setAcceptDrops(true);
195 ui.setupUi(this); 197 ui.setupUi(this);
196 statusBar()->hide(); 198 statusBar()->hide();
@@ -2048,6 +2050,9 @@ void GMainWindow::OnConfigure() {
2048 const bool old_discord_presence = UISettings::values.enable_discord_presence; 2050 const bool old_discord_presence = UISettings::values.enable_discord_presence;
2049 2051
2050 ConfigureDialog configure_dialog(this, hotkey_registry); 2052 ConfigureDialog configure_dialog(this, hotkey_registry);
2053 connect(&configure_dialog, &ConfigureDialog::LanguageChanged, this,
2054 &GMainWindow::OnLanguageChanged);
2055
2051 const auto result = configure_dialog.exec(); 2056 const auto result = configure_dialog.exec();
2052 if (result != QDialog::Accepted) { 2057 if (result != QDialog::Accepted) {
2053 return; 2058 return;
@@ -2620,6 +2625,43 @@ void GMainWindow::UpdateUITheme() {
2620 QIcon::setThemeSearchPaths(theme_paths); 2625 QIcon::setThemeSearchPaths(theme_paths);
2621} 2626}
2622 2627
2628void GMainWindow::LoadTranslation() {
2629 // If the selected language is English, no need to install any translation
2630 if (UISettings::values.language == QStringLiteral("en")) {
2631 return;
2632 }
2633
2634 bool loaded;
2635
2636 if (UISettings::values.language.isEmpty()) {
2637 // If the selected language is empty, use system locale
2638 loaded = translator.load(QLocale(), {}, {}, QStringLiteral(":/languages/"));
2639 } else {
2640 // Otherwise load from the specified file
2641 loaded = translator.load(UISettings::values.language, QStringLiteral(":/languages/"));
2642 }
2643
2644 if (loaded) {
2645 qApp->installTranslator(&translator);
2646 } else {
2647 UISettings::values.language = QStringLiteral("en");
2648 }
2649}
2650
2651void GMainWindow::OnLanguageChanged(const QString& locale) {
2652 if (UISettings::values.language != QStringLiteral("en")) {
2653 qApp->removeTranslator(&translator);
2654 }
2655
2656 UISettings::values.language = locale;
2657 LoadTranslation();
2658 ui.retranslateUi(this);
2659 UpdateWindowTitle();
2660
2661 if (emulation_running)
2662 ui.action_Start->setText(tr("Continue"));
2663}
2664
2623void GMainWindow::SetDiscordEnabled([[maybe_unused]] bool state) { 2665void GMainWindow::SetDiscordEnabled([[maybe_unused]] bool state) {
2624#ifdef USE_DISCORD_PRESENCE 2666#ifdef USE_DISCORD_PRESENCE
2625 if (state) { 2667 if (state) {
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 59d9073ae..db573d606 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -10,6 +10,7 @@
10 10
11#include <QMainWindow> 11#include <QMainWindow>
12#include <QTimer> 12#include <QTimer>
13#include <QTranslator>
13 14
14#include "common/common_types.h" 15#include "common/common_types.h"
15#include "core/core.h" 16#include "core/core.h"
@@ -225,6 +226,7 @@ private slots:
225 void OnCaptureScreenshot(); 226 void OnCaptureScreenshot();
226 void OnCoreError(Core::System::ResultStatus, std::string); 227 void OnCoreError(Core::System::ResultStatus, std::string);
227 void OnReinitializeKeys(ReinitializeKeyBehavior behavior); 228 void OnReinitializeKeys(ReinitializeKeyBehavior behavior);
229 void OnLanguageChanged(const QString& locale);
228 230
229private: 231private:
230 std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id); 232 std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id);
@@ -237,6 +239,7 @@ private:
237 void HideMouseCursor(); 239 void HideMouseCursor();
238 void ShowMouseCursor(); 240 void ShowMouseCursor();
239 void OpenURL(const QUrl& url); 241 void OpenURL(const QUrl& url);
242 void LoadTranslation();
240 243
241 Ui::MainWindow ui; 244 Ui::MainWindow ui;
242 245
@@ -285,6 +288,8 @@ private:
285 288
286 HotkeyRegistry hotkey_registry; 289 HotkeyRegistry hotkey_registry;
287 290
291 QTranslator translator;
292
288 // Install progress dialog 293 // Install progress dialog
289 QProgressDialog* install_progress; 294 QProgressDialog* install_progress;
290 295
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index 830932d45..6cc65736d 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -75,6 +75,7 @@ struct Values {
75 bool game_dir_deprecated_deepscan; 75 bool game_dir_deprecated_deepscan;
76 QVector<UISettings::GameDir> game_dirs; 76 QVector<UISettings::GameDir> game_dirs;
77 QStringList recent_files; 77 QStringList recent_files;
78 QString language;
78 79
79 QString theme; 80 QString theme;
80 81