From c09ff382a41cfc631efa9392bdb3143bd4c713a5 Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Wed, 5 Jun 2019 18:39:46 -0400
Subject: [PATCH] yuzu/configuration: Make all widgets and dialogs aware of
 language changes

To prepare for translation support, this makes all of the widgets
cognizant of the language change event that occurs whenever
installTranslator() is called and automatically retranslates their text
where necessary.

This is important as calling the backing UI's retranslateUi() is often
not enough, particularly in cases where we add our own strings that
aren't controlled by it. In that case we need to manually refresh the
strings ourselves.
---
 src/yuzu/configuration/configure_audio.cpp    | 33 +++++++---
 src/yuzu/configuration/configure_audio.h      |  7 ++-
 src/yuzu/configuration/configure_debug.cpp    | 12 ++++
 src/yuzu/configuration/configure_debug.h      |  3 +
 src/yuzu/configuration/configure_dialog.cpp   | 60 ++++++++++++++-----
 src/yuzu/configuration/configure_dialog.h     |  4 ++
 src/yuzu/configuration/configure_gamelist.cpp |  1 -
 src/yuzu/configuration/configure_general.cpp  | 12 ++++
 src/yuzu/configuration/configure_general.h    |  3 +
 src/yuzu/configuration/configure_graphics.cpp | 12 ++++
 src/yuzu/configuration/configure_graphics.h   |  3 +
 src/yuzu/configuration/configure_hotkeys.cpp  | 21 +++++--
 src/yuzu/configuration/configure_hotkeys.h    |  4 +-
 src/yuzu/configuration/configure_input.cpp    | 46 ++++++++++----
 src/yuzu/configuration/configure_input.h      |  6 ++
 .../configuration/configure_input_player.cpp  | 13 ++++
 .../configuration/configure_input_player.h    |  3 +
 .../configuration/configure_input_simple.cpp  | 12 ++++
 .../configuration/configure_input_simple.h    |  3 +
 .../configure_mouse_advanced.cpp              | 12 ++++
 .../configuration/configure_mouse_advanced.h  |  3 +
 .../configuration/configure_per_general.cpp   | 12 ++++
 .../configuration/configure_per_general.h     |  3 +
 .../configure_profile_manager.cpp             | 21 +++++--
 .../configuration/configure_profile_manager.h |  3 +
 src/yuzu/configuration/configure_system.cpp   | 12 ++++
 src/yuzu/configuration/configure_system.h     |  3 +
 .../configure_touchscreen_advanced.cpp        | 12 ++++
 .../configure_touchscreen_advanced.h          |  3 +
 src/yuzu/configuration/configure_web.cpp      | 38 ++++++++----
 src/yuzu/configuration/configure_web.h        |  4 +-
 31 files changed, 326 insertions(+), 58 deletions(-)

diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp
index 110842eb2..f370c690f 100644
--- a/src/yuzu/configuration/configure_audio.cpp
+++ b/src/yuzu/configuration/configure_audio.cpp
@@ -4,6 +4,8 @@
 
 #include <memory>
 
+#include <QSignalBlocker>
+
 #include "audio_core/sink.h"
 #include "audio_core/sink_details.h"
 #include "core/core.h"
@@ -15,19 +17,15 @@ ConfigureAudio::ConfigureAudio(QWidget* parent)
     : QWidget(parent), ui(std::make_unique<Ui::ConfigureAudio>()) {
     ui->setupUi(this);
 
-    ui->output_sink_combo_box->clear();
-    ui->output_sink_combo_box->addItem(QString::fromUtf8(AudioCore::auto_device_name));
-    for (const char* id : AudioCore::GetSinkIDs()) {
-        ui->output_sink_combo_box->addItem(QString::fromUtf8(id));
-    }
+    InitializeAudioOutputSinkComboBox();
 
     connect(ui->volume_slider, &QSlider::valueChanged, this,
             &ConfigureAudio::SetVolumeIndicatorText);
-
-    SetConfiguration();
     connect(ui->output_sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this,
             &ConfigureAudio::UpdateAudioDevices);
 
+    SetConfiguration();
+
     const bool is_powered_on = Core::System::GetInstance().IsPoweredOn();
     ui->output_sink_combo_box->setEnabled(!is_powered_on);
     ui->audio_device_combo_box->setEnabled(!is_powered_on);
@@ -49,8 +47,9 @@ void ConfigureAudio::SetConfiguration() {
 }
 
 void ConfigureAudio::SetOutputSinkFromSinkID() {
-    int new_sink_index = 0;
+    [[maybe_unused]] const QSignalBlocker blocker(ui->output_sink_combo_box);
 
+    int new_sink_index = 0;
     const QString sink_id = QString::fromStdString(Settings::values.sink_id);
     for (int index = 0; index < ui->output_sink_combo_box->count(); index++) {
         if (ui->output_sink_combo_box->itemText(index) == sink_id) {
@@ -92,6 +91,14 @@ void ConfigureAudio::ApplyConfiguration() {
         static_cast<float>(ui->volume_slider->sliderPosition()) / ui->volume_slider->maximum();
 }
 
+void ConfigureAudio::changeEvent(QEvent* event) {
+    if (event->type() == QEvent::LanguageChange) {
+        RetranslateUI();
+    }
+
+    QWidget::changeEvent(event);
+}
+
 void ConfigureAudio::UpdateAudioDevices(int sink_index) {
     ui->audio_device_combo_box->clear();
     ui->audio_device_combo_box->addItem(QString::fromUtf8(AudioCore::auto_device_name));
@@ -102,6 +109,16 @@ void ConfigureAudio::UpdateAudioDevices(int sink_index) {
     }
 }
 
+void ConfigureAudio::InitializeAudioOutputSinkComboBox() {
+    ui->output_sink_combo_box->clear();
+    ui->output_sink_combo_box->addItem(QString::fromUtf8(AudioCore::auto_device_name));
+
+    for (const char* id : AudioCore::GetSinkIDs()) {
+        ui->output_sink_combo_box->addItem(QString::fromUtf8(id));
+    }
+}
+
 void ConfigureAudio::RetranslateUI() {
     ui->retranslateUi(this);
+    SetVolumeIndicatorText(ui->volume_slider->sliderPosition());
 }
diff --git a/src/yuzu/configuration/configure_audio.h b/src/yuzu/configuration/configure_audio.h
index 2bb92d9b5..ea83bd72d 100644
--- a/src/yuzu/configuration/configure_audio.h
+++ b/src/yuzu/configuration/configure_audio.h
@@ -19,9 +19,14 @@ public:
     ~ConfigureAudio() override;
 
     void ApplyConfiguration();
-    void RetranslateUI();
 
 private:
+    void changeEvent(QEvent* event) override;
+
+    void InitializeAudioOutputSinkComboBox();
+
+    void RetranslateUI();
+
     void UpdateAudioDevices(int sink_index);
 
     void SetConfiguration();
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp
index afc2e3b38..efc2bedfd 100644
--- a/src/yuzu/configuration/configure_debug.cpp
+++ b/src/yuzu/configuration/configure_debug.cpp
@@ -51,3 +51,15 @@ void ConfigureDebug::ApplyConfiguration() {
     filter.ParseFilterString(Settings::values.log_filter);
     Log::SetGlobalFilter(filter);
 }
+
+void ConfigureDebug::changeEvent(QEvent* event) {
+    if (event->type() == QEvent::LanguageChange) {
+        RetranslateUI();
+    }
+
+    QWidget::changeEvent(event);
+}
+
+void ConfigureDebug::RetranslateUI() {
+    ui->retranslateUi(this);
+}
diff --git a/src/yuzu/configuration/configure_debug.h b/src/yuzu/configuration/configure_debug.h
index 06b89026c..f4805a1d8 100644
--- a/src/yuzu/configuration/configure_debug.h
+++ b/src/yuzu/configuration/configure_debug.h
@@ -21,6 +21,9 @@ public:
     void ApplyConfiguration();
 
 private:
+    void changeEvent(QEvent* event) override;
+
+    void RetranslateUI();
     void SetConfiguration();
 
     std::unique_ptr<Ui::ConfigureDebug> ui;
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index a1b1e00bc..e636964e3 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -4,6 +4,7 @@
 
 #include <QHash>
 #include <QListWidgetItem>
+#include <QSignalBlocker>
 #include "core/settings.h"
 #include "ui_configure.h"
 #include "yuzu/configuration/config.h"
@@ -46,13 +47,38 @@ void ConfigureDialog::ApplyConfiguration() {
     Settings::LogSettings();
 }
 
+void ConfigureDialog::changeEvent(QEvent* event) {
+    if (event->type() == QEvent::LanguageChange) {
+        RetranslateUI();
+    }
+
+    QDialog::changeEvent(event);
+}
+
+void ConfigureDialog::RetranslateUI() {
+    const int old_row = ui->selectorList->currentRow();
+    const int old_index = ui->tabWidget->currentIndex();
+
+    ui->retranslateUi(this);
+
+    PopulateSelectionList();
+    ui->selectorList->setCurrentRow(old_row);
+
+    UpdateVisibleTabs();
+    ui->tabWidget->setCurrentIndex(old_index);
+}
+
 void ConfigureDialog::PopulateSelectionList() {
     const std::array<std::pair<QString, QStringList>, 4> items{
         {{tr("General"), {tr("General"), tr("Web"), tr("Debug"), tr("Game List")}},
          {tr("System"), {tr("System"), tr("Profiles"), tr("Audio")}},
          {tr("Graphics"), {tr("Graphics")}},
-         {tr("Controls"), {tr("Input"), tr("Hotkeys")}}}};
+         {tr("Controls"), {tr("Input"), tr("Hotkeys")}}},
+    };
 
+    [[maybe_unused]] const QSignalBlocker blocker(ui->selectorList);
+
+    ui->selectorList->clear();
     for (const auto& entry : items) {
         auto* const item = new QListWidgetItem(entry.first);
         item->setData(Qt::UserRole, entry.second);
@@ -63,24 +89,28 @@ void ConfigureDialog::PopulateSelectionList() {
 
 void ConfigureDialog::UpdateVisibleTabs() {
     const auto items = ui->selectorList->selectedItems();
-    if (items.isEmpty())
+    if (items.isEmpty()) {
         return;
+    }
 
-    const std::map<QString, QWidget*> widgets = {{tr("General"), ui->generalTab},
-                                                 {tr("System"), ui->systemTab},
-                                                 {tr("Profiles"), ui->profileManagerTab},
-                                                 {tr("Input"), ui->inputTab},
-                                                 {tr("Hotkeys"), ui->hotkeysTab},
-                                                 {tr("Graphics"), ui->graphicsTab},
-                                                 {tr("Audio"), ui->audioTab},
-                                                 {tr("Debug"), ui->debugTab},
-                                                 {tr("Web"), ui->webTab},
-                                                 {tr("Game List"), ui->gameListTab}};
+    const std::map<QString, QWidget*> widgets = {
+        {tr("General"), ui->generalTab},
+        {tr("System"), ui->systemTab},
+        {tr("Profiles"), ui->profileManagerTab},
+        {tr("Input"), ui->inputTab},
+        {tr("Hotkeys"), ui->hotkeysTab},
+        {tr("Graphics"), ui->graphicsTab},
+        {tr("Audio"), ui->audioTab},
+        {tr("Debug"), ui->debugTab},
+        {tr("Web"), ui->webTab},
+        {tr("Game List"), ui->gameListTab},
+    };
+
+    [[maybe_unused]] const QSignalBlocker blocker(ui->tabWidget);
 
     ui->tabWidget->clear();
-
     const QStringList tabs = items[0]->data(Qt::UserRole).toStringList();
-
-    for (const auto& tab : tabs)
+    for (const auto& tab : tabs) {
         ui->tabWidget->addTab(widgets.find(tab)->second, tab);
+    }
 }
diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h
index 7e7d90f59..2d3bfc2da 100644
--- a/src/yuzu/configuration/configure_dialog.h
+++ b/src/yuzu/configuration/configure_dialog.h
@@ -23,6 +23,10 @@ public:
     void ApplyConfiguration();
 
 private:
+    void changeEvent(QEvent* event) override;
+
+    void RetranslateUI();
+
     void SetConfiguration();
     void UpdateVisibleTabs();
     void PopulateSelectionList();
diff --git a/src/yuzu/configuration/configure_gamelist.cpp b/src/yuzu/configuration/configure_gamelist.cpp
index 4b5b0ee48..d1724ba89 100644
--- a/src/yuzu/configuration/configure_gamelist.cpp
+++ b/src/yuzu/configuration/configure_gamelist.cpp
@@ -77,7 +77,6 @@ void ConfigureGameList::SetConfiguration() {
 void ConfigureGameList::changeEvent(QEvent* event) {
     if (event->type() == QEvent::LanguageChange) {
         RetranslateUI();
-        return;
     }
 
     QWidget::changeEvent(event);
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp
index 8bdc1787a..06d368dfc 100644
--- a/src/yuzu/configuration/configure_general.cpp
+++ b/src/yuzu/configuration/configure_general.cpp
@@ -45,3 +45,15 @@ void ConfigureGeneral::ApplyConfiguration() {
 
     Settings::values.use_cpu_jit = ui->use_cpu_jit->isChecked();
 }
+
+void ConfigureGeneral::changeEvent(QEvent* event) {
+    if (event->type() == QEvent::LanguageChange) {
+        RetranslateUI();
+    }
+
+    QWidget::changeEvent(event);
+}
+
+void ConfigureGeneral::RetranslateUI() {
+    ui->retranslateUi(this);
+}
diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h
index fd5fd2a91..ef05ce065 100644
--- a/src/yuzu/configuration/configure_general.h
+++ b/src/yuzu/configuration/configure_general.h
@@ -23,6 +23,9 @@ public:
     void ApplyConfiguration();
 
 private:
+    void changeEvent(QEvent* event) override;
+    void RetranslateUI();
+
     void SetConfiguration();
 
     std::unique_ptr<Ui::ConfigureGeneral> ui;
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index 02e91701a..45e87248c 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -104,6 +104,18 @@ void ConfigureGraphics::ApplyConfiguration() {
     Settings::values.bg_blue = static_cast<float>(bg_color.blueF());
 }
 
+void ConfigureGraphics::changeEvent(QEvent* event) {
+    if (event->type() == QEvent::LanguageChange) {
+        RetranslateUI();
+    }
+
+    QWidget::changeEvent(event);
+}
+
+void ConfigureGraphics::RetranslateUI() {
+    ui->retranslateUi(this);
+}
+
 void ConfigureGraphics::UpdateBackgroundColorButton(QColor color) {
     bg_color = color;
 
diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h
index 6b3c39705..fae28d98e 100644
--- a/src/yuzu/configuration/configure_graphics.h
+++ b/src/yuzu/configuration/configure_graphics.h
@@ -21,6 +21,9 @@ public:
     void ApplyConfiguration();
 
 private:
+    void changeEvent(QEvent* event) override;
+    void RetranslateUI();
+
     void SetConfiguration();
 
     void UpdateBackgroundColorButton(QColor color);
diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp
index 04119e9d7..3ea0b8d67 100644
--- a/src/yuzu/configuration/configure_hotkeys.cpp
+++ b/src/yuzu/configuration/configure_hotkeys.cpp
@@ -17,7 +17,6 @@ ConfigureHotkeys::ConfigureHotkeys(QWidget* parent)
 
     model = new QStandardItemModel(this);
     model->setColumnCount(3);
-    model->setHorizontalHeaderLabels({tr("Action"), tr("Hotkey"), tr("Context")});
 
     connect(ui->hotkey_list, &QTreeView::doubleClicked, this, &ConfigureHotkeys::Configure);
     ui->hotkey_list->setModel(model);
@@ -27,6 +26,8 @@ ConfigureHotkeys::ConfigureHotkeys(QWidget* parent)
 
     ui->hotkey_list->setColumnWidth(0, 200);
     ui->hotkey_list->resizeColumnToContents(1);
+
+    RetranslateUI();
 }
 
 ConfigureHotkeys::~ConfigureHotkeys() = default;
@@ -49,6 +50,20 @@ void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) {
     ui->hotkey_list->expandAll();
 }
 
+void ConfigureHotkeys::changeEvent(QEvent* event) {
+    if (event->type() == QEvent::LanguageChange) {
+        RetranslateUI();
+    }
+
+    QWidget::changeEvent(event);
+}
+
+void ConfigureHotkeys::RetranslateUI() {
+    ui->retranslateUi(this);
+
+    model->setHorizontalHeaderLabels({tr("Action"), tr("Hotkey"), tr("Context")});
+}
+
 void ConfigureHotkeys::Configure(QModelIndex index) {
     if (!index.parent().isValid()) {
         return;
@@ -112,7 +127,3 @@ void ConfigureHotkeys::ApplyConfiguration(HotkeyRegistry& registry) {
 
     registry.SaveHotkeys();
 }
-
-void ConfigureHotkeys::RetranslateUI() {
-    ui->retranslateUi(this);
-}
diff --git a/src/yuzu/configuration/configure_hotkeys.h b/src/yuzu/configuration/configure_hotkeys.h
index a1f4c7134..8f8c6173b 100644
--- a/src/yuzu/configuration/configure_hotkeys.h
+++ b/src/yuzu/configuration/configure_hotkeys.h
@@ -22,7 +22,6 @@ public:
     ~ConfigureHotkeys() override;
 
     void ApplyConfiguration(HotkeyRegistry& registry);
-    void RetranslateUI();
 
     /**
      * Populates the hotkey list widget using data from the provided registry.
@@ -32,6 +31,9 @@ public:
     void Populate(const HotkeyRegistry& registry);
 
 private:
+    void changeEvent(QEvent* event) override;
+    void RetranslateUI();
+
     void Configure(QModelIndex index);
     bool IsUsedKey(QKeySequence key_sequence) const;
 
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index fb1210bcb..4dd775aab 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -5,6 +5,7 @@
 #include <algorithm>
 #include <memory>
 
+#include <QSignalBlocker>
 #include <QTimer>
 
 #include "configuration/configure_touchscreen_advanced.h"
@@ -74,11 +75,7 @@ ConfigureInput::ConfigureInput(QWidget* parent)
         ui->player5_configure, ui->player6_configure, ui->player7_configure, ui->player8_configure,
     };
 
-    for (auto* controller_box : players_controller) {
-        controller_box->addItems({tr("None"), tr("Pro Controller"), tr("Dual Joycons"),
-                                  tr("Single Right Joycon"), tr("Single Left Joycon")});
-    }
-
+    RetranslateUI();
     LoadConfiguration();
     UpdateUIEnabled();
 
@@ -144,6 +141,31 @@ void ConfigureInput::ApplyConfiguration() {
     Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked();
 }
 
+void ConfigureInput::changeEvent(QEvent* event) {
+    if (event->type() == QEvent::LanguageChange) {
+        RetranslateUI();
+    }
+
+    QDialog::changeEvent(event);
+}
+
+void ConfigureInput::RetranslateUI() {
+    ui->retranslateUi(this);
+    RetranslateControllerComboBoxes();
+}
+
+void ConfigureInput::RetranslateControllerComboBoxes() {
+    for (auto* controller_box : players_controller) {
+        [[maybe_unused]] const QSignalBlocker blocker(controller_box);
+
+        controller_box->clear();
+        controller_box->addItems({tr("None"), tr("Pro Controller"), tr("Dual Joycons"),
+                                  tr("Single Right Joycon"), tr("Single Left Joycon")});
+    }
+
+    LoadPlayerControllerIndices();
+}
+
 void ConfigureInput::UpdateUIEnabled() {
     bool hit_disabled = false;
     for (auto* player : players_controller) {
@@ -175,11 +197,7 @@ void ConfigureInput::LoadConfiguration() {
             Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD),
         [](const auto& player) { return player.connected; });
 
-    for (std::size_t i = 0; i < players_controller.size(); ++i) {
-        const auto connected = Settings::values.players[i].connected;
-        players_controller[i]->setCurrentIndex(
-            connected ? static_cast<u8>(Settings::values.players[i].type) + 1 : 0);
-    }
+    LoadPlayerControllerIndices();
 
     ui->use_docked_mode->setChecked(Settings::values.use_docked_mode);
     ui->handheld_connected->setChecked(
@@ -194,6 +212,14 @@ void ConfigureInput::LoadConfiguration() {
     UpdateUIEnabled();
 }
 
+void ConfigureInput::LoadPlayerControllerIndices() {
+    for (std::size_t i = 0; i < players_controller.size(); ++i) {
+        const auto connected = Settings::values.players[i].connected;
+        players_controller[i]->setCurrentIndex(
+            connected ? static_cast<u8>(Settings::values.players[i].type) + 1 : 0);
+    }
+}
+
 void ConfigureInput::RestoreDefaults() {
     players_controller[0]->setCurrentIndex(2);
 
diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h
index 6a2125215..2f70cb3ca 100644
--- a/src/yuzu/configuration/configure_input.h
+++ b/src/yuzu/configuration/configure_input.h
@@ -33,10 +33,16 @@ public:
     void ApplyConfiguration();
 
 private:
+    void changeEvent(QEvent* event) override;
+    void RetranslateUI();
+    void RetranslateControllerComboBoxes();
+
     void UpdateUIEnabled();
 
     /// Load configuration settings.
     void LoadConfiguration();
+    void LoadPlayerControllerIndices();
+
     /// Restore all buttons to their default values.
     void RestoreDefaults();
 
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 32d2a6815..916baccc1 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -373,6 +373,19 @@ void ConfigureInputPlayer::ApplyConfiguration() {
     Settings::values.players[player_index].button_color_right = colors[3];
 }
 
+void ConfigureInputPlayer::changeEvent(QEvent* event) {
+    if (event->type() == QEvent::LanguageChange) {
+        RetranslateUI();
+    }
+
+    QDialog::changeEvent(event);
+}
+
+void ConfigureInputPlayer::RetranslateUI() {
+    ui->retranslateUi(this);
+    UpdateButtonLabels();
+}
+
 void ConfigureInputPlayer::OnControllerButtonClick(int i) {
     const QColor new_bg_color = QColorDialog::getColor(controller_colors[i]);
     if (!new_bg_color.isValid())
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h
index 27924fcce..c66027651 100644
--- a/src/yuzu/configuration/configure_input_player.h
+++ b/src/yuzu/configuration/configure_input_player.h
@@ -41,6 +41,9 @@ public:
     void ApplyConfiguration();
 
 private:
+    void changeEvent(QEvent* event) override;
+    void RetranslateUI();
+
     void OnControllerButtonClick(int i);
 
     /// Load configuration settings.
diff --git a/src/yuzu/configuration/configure_input_simple.cpp b/src/yuzu/configuration/configure_input_simple.cpp
index 6140a5573..864803ea3 100644
--- a/src/yuzu/configuration/configure_input_simple.cpp
+++ b/src/yuzu/configuration/configure_input_simple.cpp
@@ -119,6 +119,18 @@ void ConfigureInputSimple::ApplyConfiguration() {
     UISettings::values.profile_index = index;
 }
 
+void ConfigureInputSimple::changeEvent(QEvent* event) {
+    if (event->type() == QEvent::LanguageChange) {
+        RetranslateUI();
+    }
+
+    QWidget::changeEvent(event);
+}
+
+void ConfigureInputSimple::RetranslateUI() {
+    ui->retranslateUi(this);
+}
+
 void ConfigureInputSimple::LoadConfiguration() {
     const auto index = UISettings::values.profile_index;
     if (index >= static_cast<int>(INPUT_PROFILES.size()) || index < 0) {
diff --git a/src/yuzu/configuration/configure_input_simple.h b/src/yuzu/configuration/configure_input_simple.h
index 573c2db2b..bb5050224 100644
--- a/src/yuzu/configuration/configure_input_simple.h
+++ b/src/yuzu/configuration/configure_input_simple.h
@@ -30,6 +30,9 @@ public:
     void ApplyConfiguration();
 
 private:
+    void changeEvent(QEvent* event) override;
+    void RetranslateUI();
+
     /// Load configuration settings.
     void LoadConfiguration();
 
diff --git a/src/yuzu/configuration/configure_mouse_advanced.cpp b/src/yuzu/configuration/configure_mouse_advanced.cpp
index 26f53128f..b7305e653 100644
--- a/src/yuzu/configuration/configure_mouse_advanced.cpp
+++ b/src/yuzu/configuration/configure_mouse_advanced.cpp
@@ -140,6 +140,18 @@ void ConfigureMouseAdvanced::LoadConfiguration() {
     UpdateButtonLabels();
 }
 
+void ConfigureMouseAdvanced::changeEvent(QEvent* event) {
+    if (event->type() == QEvent::LanguageChange) {
+        RetranslateUI();
+    }
+
+    QDialog::changeEvent(event);
+}
+
+void ConfigureMouseAdvanced::RetranslateUI() {
+    ui->retranslateUi(this);
+}
+
 void ConfigureMouseAdvanced::RestoreDefaults() {
     for (int button_id = 0; button_id < Settings::NativeMouseButton::NumMouseButtons; button_id++) {
         buttons_param[button_id] = Common::ParamPackage{
diff --git a/src/yuzu/configuration/configure_mouse_advanced.h b/src/yuzu/configuration/configure_mouse_advanced.h
index 373f992c9..342b82412 100644
--- a/src/yuzu/configuration/configure_mouse_advanced.h
+++ b/src/yuzu/configuration/configure_mouse_advanced.h
@@ -28,6 +28,9 @@ public:
     void ApplyConfiguration();
 
 private:
+    void changeEvent(QEvent* event) override;
+    void RetranslateUI();
+
     /// Load configuration settings.
     void LoadConfiguration();
     /// Restore all buttons to their default values.
diff --git a/src/yuzu/configuration/configure_per_general.cpp b/src/yuzu/configuration/configure_per_general.cpp
index 275519c7b..90336e235 100644
--- a/src/yuzu/configuration/configure_per_general.cpp
+++ b/src/yuzu/configuration/configure_per_general.cpp
@@ -92,6 +92,18 @@ void ConfigurePerGameGeneral::ApplyConfiguration() {
     Settings::values.disabled_addons[title_id] = disabled_addons;
 }
 
+void ConfigurePerGameGeneral::changeEvent(QEvent* event) {
+    if (event->type() == QEvent::LanguageChange) {
+        RetranslateUI();
+    }
+
+    QDialog::changeEvent(event);
+}
+
+void ConfigurePerGameGeneral::RetranslateUI() {
+    ui->retranslateUi(this);
+}
+
 void ConfigurePerGameGeneral::LoadFromFile(FileSys::VirtualFile file) {
     this->file = std::move(file);
     LoadConfiguration();
diff --git a/src/yuzu/configuration/configure_per_general.h b/src/yuzu/configuration/configure_per_general.h
index b95e07079..a3b2cdeff 100644
--- a/src/yuzu/configuration/configure_per_general.h
+++ b/src/yuzu/configuration/configure_per_general.h
@@ -35,6 +35,9 @@ public:
     void LoadFromFile(FileSys::VirtualFile file);
 
 private:
+    void changeEvent(QEvent* event) override;
+    void RetranslateUI();
+
     void LoadConfiguration();
 
     std::unique_ptr<Ui::ConfigurePerGameGeneral> ui;
diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp
index 7c1597488..c90f4cdd8 100644
--- a/src/yuzu/configuration/configure_profile_manager.cpp
+++ b/src/yuzu/configuration/configure_profile_manager.cpp
@@ -80,11 +80,10 @@ ConfigureProfileManager ::ConfigureProfileManager(QWidget* parent)
       profile_manager(std::make_unique<Service::Account::ProfileManager>()) {
     ui->setupUi(this);
 
-    layout = new QVBoxLayout;
     tree_view = new QTreeView;
     item_model = new QStandardItemModel(tree_view);
+    item_model->insertColumns(0, 1);
     tree_view->setModel(item_model);
-
     tree_view->setAlternatingRowColors(true);
     tree_view->setSelectionMode(QHeaderView::SingleSelection);
     tree_view->setSelectionBehavior(QHeaderView::SelectRows);
@@ -96,13 +95,11 @@ ConfigureProfileManager ::ConfigureProfileManager(QWidget* parent)
     tree_view->setIconSize({64, 64});
     tree_view->setContextMenuPolicy(Qt::NoContextMenu);
 
-    item_model->insertColumns(0, 1);
-    item_model->setHeaderData(0, Qt::Horizontal, tr("Users"));
-
     // We must register all custom types with the Qt Automoc system so that we are able to use it
     // with signals/slots. In this case, QList falls under the umbrells of custom types.
     qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>");
 
+    layout = new QVBoxLayout;
     layout->setContentsMargins(0, 0, 0, 0);
     layout->setSpacing(0);
     layout->addWidget(tree_view);
@@ -120,10 +117,24 @@ ConfigureProfileManager ::ConfigureProfileManager(QWidget* parent)
     ui->current_user_icon->setScene(scene);
 
     SetConfiguration();
+    RetranslateUI();
 }
 
 ConfigureProfileManager::~ConfigureProfileManager() = default;
 
+void ConfigureProfileManager::changeEvent(QEvent* event) {
+    if (event->type() == QEvent::LanguageChange) {
+        RetranslateUI();
+    }
+
+    QWidget::changeEvent(event);
+}
+
+void ConfigureProfileManager::RetranslateUI() {
+    ui->retranslateUi(this);
+    item_model->setHeaderData(0, Qt::Horizontal, tr("Users"));
+}
+
 void ConfigureProfileManager::SetConfiguration() {
     enabled = !Core::System::GetInstance().IsPoweredOn();
     item_model->removeRows(0, item_model->rowCount());
diff --git a/src/yuzu/configuration/configure_profile_manager.h b/src/yuzu/configuration/configure_profile_manager.h
index 4e9b4e8ea..0a9bca2a6 100644
--- a/src/yuzu/configuration/configure_profile_manager.h
+++ b/src/yuzu/configuration/configure_profile_manager.h
@@ -33,6 +33,9 @@ public:
     void ApplyConfiguration();
 
 private:
+    void changeEvent(QEvent* event) override;
+    void RetranslateUI();
+
     void SetConfiguration();
 
     void PopulateUserList();
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp
index 5f0ed2f61..e1b52f8d9 100644
--- a/src/yuzu/configuration/configure_system.cpp
+++ b/src/yuzu/configuration/configure_system.cpp
@@ -40,6 +40,18 @@ ConfigureSystem::ConfigureSystem(QWidget* parent) : QWidget(parent), ui(new Ui::
 
 ConfigureSystem::~ConfigureSystem() = default;
 
+void ConfigureSystem::changeEvent(QEvent* event) {
+    if (event->type() == QEvent::LanguageChange) {
+        RetranslateUI();
+    }
+
+    QWidget::changeEvent(event);
+}
+
+void ConfigureSystem::RetranslateUI() {
+    ui->retranslateUi(this);
+}
+
 void ConfigureSystem::SetConfiguration() {
     enabled = !Core::System::GetInstance().IsPoweredOn();
 
diff --git a/src/yuzu/configuration/configure_system.h b/src/yuzu/configuration/configure_system.h
index 4c0329d57..1eab3781d 100644
--- a/src/yuzu/configuration/configure_system.h
+++ b/src/yuzu/configuration/configure_system.h
@@ -23,6 +23,9 @@ public:
     void ApplyConfiguration();
 
 private:
+    void changeEvent(QEvent* event) override;
+    void RetranslateUI();
+
     void SetConfiguration();
 
     void ReadSystemSettings();
diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.cpp b/src/yuzu/configuration/configure_touchscreen_advanced.cpp
index bad224239..8ced28c75 100644
--- a/src/yuzu/configuration/configure_touchscreen_advanced.cpp
+++ b/src/yuzu/configuration/configure_touchscreen_advanced.cpp
@@ -20,6 +20,18 @@ ConfigureTouchscreenAdvanced::ConfigureTouchscreenAdvanced(QWidget* parent)
 
 ConfigureTouchscreenAdvanced::~ConfigureTouchscreenAdvanced() = default;
 
+void ConfigureTouchscreenAdvanced::changeEvent(QEvent* event) {
+    if (event->type() == QEvent::LanguageChange) {
+        RetranslateUI();
+    }
+
+    QDialog::changeEvent(event);
+}
+
+void ConfigureTouchscreenAdvanced::RetranslateUI() {
+    ui->retranslateUi(this);
+}
+
 void ConfigureTouchscreenAdvanced::ApplyConfiguration() {
     Settings::values.touchscreen.finger = ui->finger_box->value();
     Settings::values.touchscreen.diameter_x = ui->diameter_x_box->value();
diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.h b/src/yuzu/configuration/configure_touchscreen_advanced.h
index 94edd85b1..72061492c 100644
--- a/src/yuzu/configuration/configure_touchscreen_advanced.h
+++ b/src/yuzu/configuration/configure_touchscreen_advanced.h
@@ -21,6 +21,9 @@ public:
     void ApplyConfiguration();
 
 private:
+    void changeEvent(QEvent* event) override;
+    void RetranslateUI();
+
     /// Load configuration settings.
     void LoadConfiguration();
     /// Restore all buttons to their default values.
diff --git a/src/yuzu/configuration/configure_web.cpp b/src/yuzu/configuration/configure_web.cpp
index 8cacb75f3..5a70ef168 100644
--- a/src/yuzu/configuration/configure_web.cpp
+++ b/src/yuzu/configuration/configure_web.cpp
@@ -22,35 +22,55 @@ ConfigureWeb::ConfigureWeb(QWidget* parent)
 #ifndef USE_DISCORD_PRESENCE
     ui->discord_group->setVisible(false);
 #endif
+
     SetConfiguration();
+    RetranslateUI();
 }
 
 ConfigureWeb::~ConfigureWeb() = default;
 
-void ConfigureWeb::SetConfiguration() {
-    ui->web_credentials_disclaimer->setWordWrap(true);
-    ui->telemetry_learn_more->setOpenExternalLinks(true);
+void ConfigureWeb::changeEvent(QEvent* event) {
+    if (event->type() == QEvent::LanguageChange) {
+        RetranslateUI();
+    }
+
+    QWidget::changeEvent(event);
+}
+
+void ConfigureWeb::RetranslateUI() {
+    ui->retranslateUi(this);
+
     ui->telemetry_learn_more->setText(
         tr("<a href='https://yuzu-emu.org/help/feature/telemetry/'><span style=\"text-decoration: "
            "underline; color:#039be5;\">Learn more</span></a>"));
 
-    ui->web_signup_link->setOpenExternalLinks(true);
     ui->web_signup_link->setText(
         tr("<a href='https://profile.yuzu-emu.org/'><span style=\"text-decoration: underline; "
            "color:#039be5;\">Sign up</span></a>"));
-    ui->web_token_info_link->setOpenExternalLinks(true);
+
     ui->web_token_info_link->setText(
         tr("<a href='https://yuzu-emu.org/wiki/yuzu-web-service/'><span style=\"text-decoration: "
            "underline; color:#039be5;\">What is my token?</span></a>"));
 
+    ui->label_telemetry_id->setText(
+        tr("Telemetry ID: 0x%1").arg(QString::number(Core::GetTelemetryId(), 16).toUpper()));
+}
+
+void ConfigureWeb::SetConfiguration() {
+    ui->web_credentials_disclaimer->setWordWrap(true);
+
+    ui->telemetry_learn_more->setOpenExternalLinks(true);
+    ui->web_signup_link->setOpenExternalLinks(true);
+    ui->web_token_info_link->setOpenExternalLinks(true);
+
     ui->toggle_telemetry->setChecked(Settings::values.enable_telemetry);
     ui->edit_username->setText(QString::fromStdString(Settings::values.yuzu_username));
     ui->edit_token->setText(QString::fromStdString(Settings::values.yuzu_token));
+
     // Connect after setting the values, to avoid calling OnLoginChanged now
     connect(ui->edit_token, &QLineEdit::textChanged, this, &ConfigureWeb::OnLoginChanged);
     connect(ui->edit_username, &QLineEdit::textChanged, this, &ConfigureWeb::OnLoginChanged);
-    ui->label_telemetry_id->setText(
-        tr("Telemetry ID: 0x%1").arg(QString::number(Core::GetTelemetryId(), 16).toUpper()));
+
     user_verified = true;
 
     ui->toggle_discordrpc->setChecked(UISettings::values.enable_discord_presence);
@@ -120,7 +140,3 @@ void ConfigureWeb::OnLoginVerified() {
                "correctly, and that your internet connection is working."));
     }
 }
-
-void ConfigureWeb::RetranslateUI() {
-    ui->retranslateUi(this);
-}
diff --git a/src/yuzu/configuration/configure_web.h b/src/yuzu/configuration/configure_web.h
index 49bee171b..9054711ea 100644
--- a/src/yuzu/configuration/configure_web.h
+++ b/src/yuzu/configuration/configure_web.h
@@ -20,9 +20,11 @@ public:
     ~ConfigureWeb() override;
 
     void ApplyConfiguration();
-    void RetranslateUI();
 
 private:
+    void changeEvent(QEvent* event) override;
+    void RetranslateUI();
+
     void RefreshTelemetryID();
     void OnLoginChanged();
     void VerifyLogin();