yuzu: Port translation support from Citra
Co-Authored-By: Weiyi Wang <wwylele@gmail.com>
This commit is contained in:
parent
4a8cb9a706
commit
347b50ad43
17 changed files with 261 additions and 92 deletions
|
@ -133,12 +133,45 @@ file(GLOB COMPAT_LIST
|
|||
file(GLOB_RECURSE ICONS ${PROJECT_SOURCE_DIR}/dist/icons/*)
|
||||
file(GLOB_RECURSE THEMES ${PROJECT_SOURCE_DIR}/dist/qt_themes/*)
|
||||
|
||||
if (ENABLE_QT_TRANSLATION)
|
||||
set(YUZU_QT_LANGUAGES "${PROJECT_SOURCE_DIR}/dist/languages" CACHE PATH "Path to the translation bundle for the Qt frontend")
|
||||
option(GENERATE_QT_TRANSLATION "Generate en.ts as the translation source file" OFF)
|
||||
|
||||
# Update source TS file if enabled
|
||||
if (GENERATE_QT_TRANSLATION)
|
||||
get_target_property(SRCS yuzu SOURCES)
|
||||
qt5_create_translation(QM_FILES ${SRCS} ${UIS} ${YUZU_QT_LANGUAGES}/en.ts)
|
||||
add_custom_target(translation ALL DEPENDS ${YUZU_QT_LANGUAGES}/en.ts)
|
||||
endif()
|
||||
|
||||
# Find all TS files except en.ts
|
||||
file(GLOB_RECURSE LANGUAGES_TS ${YUZU_QT_LANGUAGES}/*.ts)
|
||||
list(REMOVE_ITEM LANGUAGES_TS ${YUZU_QT_LANGUAGES}/en.ts)
|
||||
|
||||
# Compile TS files to QM files
|
||||
qt5_add_translation(LANGUAGES_QM ${LANGUAGES_TS})
|
||||
|
||||
# Build a QRC file from the QM file list
|
||||
set(LANGUAGES_QRC ${CMAKE_CURRENT_BINARY_DIR}/languages.qrc)
|
||||
file(WRITE ${LANGUAGES_QRC} "<RCC><qresource prefix=\"languages\">\n")
|
||||
foreach (QM ${LANGUAGES_QM})
|
||||
get_filename_component(QM_FILE ${QM} NAME)
|
||||
file(APPEND ${LANGUAGES_QRC} "<file>${QM_FILE}</file>\n")
|
||||
endforeach (QM)
|
||||
file(APPEND ${LANGUAGES_QRC} "</qresource></RCC>")
|
||||
|
||||
# Add the QRC file to package in all QM files
|
||||
qt5_add_resources(LANGUAGES ${LANGUAGES_QRC})
|
||||
else()
|
||||
set(LANGUAGES)
|
||||
endif()
|
||||
|
||||
target_sources(yuzu
|
||||
PRIVATE
|
||||
${COMPAT_LIST}
|
||||
${ICONS}
|
||||
${THEMES}
|
||||
${LANGUAGES}
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
|
|
|
@ -611,6 +611,7 @@ void Config::ReadPathValues() {
|
|||
}
|
||||
}
|
||||
UISettings::values.recent_files = ReadSetting(QStringLiteral("recentFiles")).toStringList();
|
||||
UISettings::values.language = ReadSetting(QStringLiteral("language"), QString{}).toString();
|
||||
|
||||
qt_config->endGroup();
|
||||
}
|
||||
|
@ -1095,6 +1096,7 @@ void Config::SavePathValues() {
|
|||
}
|
||||
qt_config->endArray();
|
||||
WriteSetting(QStringLiteral("recentFiles"), UISettings::values.recent_files);
|
||||
WriteSetting(QStringLiteral("language"), UISettings::values.language, QString{});
|
||||
|
||||
qt_config->endGroup();
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry)
|
|||
SetConfiguration();
|
||||
PopulateSelectionList();
|
||||
|
||||
connect(ui->uiTab, &ConfigureUi::LanguageChanged, this, &ConfigureDialog::OnLanguageChanged);
|
||||
connect(ui->selectorList, &QListWidget::itemSelectionChanged, this,
|
||||
&ConfigureDialog::UpdateVisibleTabs);
|
||||
|
||||
|
@ -98,6 +99,14 @@ void ConfigureDialog::PopulateSelectionList() {
|
|||
}
|
||||
}
|
||||
|
||||
void ConfigureDialog::OnLanguageChanged(const QString& locale) {
|
||||
emit LanguageChanged(locale);
|
||||
// first apply the configuration, and then restore the display
|
||||
ApplyConfiguration();
|
||||
RetranslateUI();
|
||||
SetConfiguration();
|
||||
}
|
||||
|
||||
void ConfigureDialog::UpdateVisibleTabs() {
|
||||
const auto items = ui->selectorList->selectedItems();
|
||||
if (items.isEmpty()) {
|
||||
|
|
|
@ -22,6 +22,12 @@ public:
|
|||
|
||||
void ApplyConfiguration();
|
||||
|
||||
private slots:
|
||||
void OnLanguageChanged(const QString& locale);
|
||||
|
||||
signals:
|
||||
void LanguageChanged(const QString& locale);
|
||||
|
||||
private:
|
||||
void changeEvent(QEvent* event) override;
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <array>
|
||||
#include <utility>
|
||||
|
||||
#include <QDirIterator>
|
||||
#include "common/common_types.h"
|
||||
#include "core/settings.h"
|
||||
#include "ui_configure_ui.h"
|
||||
|
@ -28,6 +29,23 @@ constexpr std::array row_text_names{
|
|||
|
||||
ConfigureUi::ConfigureUi(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureUi) {
|
||||
ui->setupUi(this);
|
||||
ui->language_combobox->addItem(tr("<System>"), QString{});
|
||||
ui->language_combobox->addItem(tr("English"), QStringLiteral("en"));
|
||||
QDirIterator it(QStringLiteral(":/languages"), QDirIterator::NoIteratorFlags);
|
||||
while (it.hasNext()) {
|
||||
QString locale = it.next();
|
||||
locale.truncate(locale.lastIndexOf(QLatin1Char{'.'}));
|
||||
locale.remove(0, locale.lastIndexOf(QLatin1Char{'/'}) + 1);
|
||||
QString lang = QLocale::languageToString(QLocale(locale).language());
|
||||
ui->language_combobox->addItem(lang, locale);
|
||||
}
|
||||
|
||||
// Unlike other configuration changes, interface language changes need to be reflected on the
|
||||
// interface immediately. This is done by passing a signal to the main window, and then
|
||||
// retranslating when passing back.
|
||||
connect(ui->language_combobox,
|
||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
|
||||
&ConfigureUi::OnLanguageChanged);
|
||||
|
||||
for (const auto& theme : UISettings::themes) {
|
||||
ui->theme_combobox->addItem(QString::fromUtf8(theme.first),
|
||||
|
@ -72,6 +90,8 @@ void ConfigureUi::RequestGameListUpdate() {
|
|||
|
||||
void ConfigureUi::SetConfiguration() {
|
||||
ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme));
|
||||
ui->language_combobox->setCurrentIndex(
|
||||
ui->language_combobox->findData(UISettings::values.language));
|
||||
ui->show_add_ons->setChecked(UISettings::values.show_add_ons);
|
||||
ui->icon_size_combobox->setCurrentIndex(
|
||||
ui->icon_size_combobox->findData(UISettings::values.icon_size));
|
||||
|
@ -147,3 +167,10 @@ void ConfigureUi::UpdateSecondRowComboBox(bool init) {
|
|||
ui->row_2_text_combobox->removeItem(
|
||||
ui->row_2_text_combobox->findData(ui->row_1_text_combobox->currentData()));
|
||||
}
|
||||
|
||||
void ConfigureUi::OnLanguageChanged(int index) {
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
emit LanguageChanged(ui->language_combobox->itemData(index).toString());
|
||||
}
|
||||
|
|
|
@ -20,6 +20,12 @@ public:
|
|||
|
||||
void ApplyConfiguration();
|
||||
|
||||
private slots:
|
||||
void OnLanguageChanged(int index);
|
||||
|
||||
signals:
|
||||
void LanguageChanged(const QString& locale);
|
||||
|
||||
private:
|
||||
void RequestGameListUpdate();
|
||||
|
||||
|
|
|
@ -13,112 +13,132 @@
|
|||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="HorizontalLayout">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="VerticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="GeneralGroupBox">
|
||||
<property name="title">
|
||||
<string>General</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<widget class="QGroupBox" name="general_groupBox">
|
||||
<property name="title">
|
||||
<string>General</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="theme_label">
|
||||
<property name="text">
|
||||
<string>Theme:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="theme_combobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QLabel" name="label_change_language_info">
|
||||
<property name="text">
|
||||
<string>Note: Changing language will apply your configuration.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="GameListGroupBox">
|
||||
<property name="title">
|
||||
<string>Game List</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="GameListHorizontalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="GeneralVerticalLayout">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="show_add_ons">
|
||||
<widget class="QLabel" name="language_label">
|
||||
<property name="text">
|
||||
<string>Show Add-Ons Column</string>
|
||||
<string>Interface language:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="icon_size_qhbox_layout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="icon_size_label">
|
||||
<property name="text">
|
||||
<string>Icon Size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="icon_size_combobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QComboBox" name="language_combobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="theme_label">
|
||||
<property name="text">
|
||||
<string>Theme:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="row_1_qhbox_layout">
|
||||
<item>
|
||||
<widget class="QLabel" name="row_1_label">
|
||||
<property name="text">
|
||||
<string>Row 1 Text:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="row_1_text_combobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="row_2_qhbox_layout">
|
||||
<item>
|
||||
<widget class="QLabel" name="row_2_label">
|
||||
<property name="text">
|
||||
<string>Row 2 Text:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="row_2_text_combobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QComboBox" name="theme_combobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="GameListGroupBox">
|
||||
<property name="title">
|
||||
<string>Game List</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="GameListHorizontalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="GeneralVerticalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="show_add_ons">
|
||||
<property name="text">
|
||||
<string>Show Add-Ons Column</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="icon_size_qhbox_layout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="icon_size_label">
|
||||
<property name="text">
|
||||
<string>Icon Size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="icon_size_combobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="row_1_qhbox_layout">
|
||||
<item>
|
||||
<widget class="QLabel" name="row_1_label">
|
||||
<property name="text">
|
||||
<string>Row 1 Text:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="row_1_text_combobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="row_2_qhbox_layout">
|
||||
<item>
|
||||
<widget class="QLabel" name="row_2_label">
|
||||
<property name="text">
|
||||
<string>Row 2 Text:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="row_2_text_combobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
|
|
@ -191,6 +191,8 @@ GMainWindow::GMainWindow()
|
|||
provider(std::make_unique<FileSys::ManualContentProvider>()) {
|
||||
InitializeLogging();
|
||||
|
||||
LoadTranslation();
|
||||
|
||||
setAcceptDrops(true);
|
||||
ui.setupUi(this);
|
||||
statusBar()->hide();
|
||||
|
@ -2048,6 +2050,9 @@ void GMainWindow::OnConfigure() {
|
|||
const bool old_discord_presence = UISettings::values.enable_discord_presence;
|
||||
|
||||
ConfigureDialog configure_dialog(this, hotkey_registry);
|
||||
connect(&configure_dialog, &ConfigureDialog::LanguageChanged, this,
|
||||
&GMainWindow::OnLanguageChanged);
|
||||
|
||||
const auto result = configure_dialog.exec();
|
||||
if (result != QDialog::Accepted) {
|
||||
return;
|
||||
|
@ -2620,6 +2625,43 @@ void GMainWindow::UpdateUITheme() {
|
|||
QIcon::setThemeSearchPaths(theme_paths);
|
||||
}
|
||||
|
||||
void GMainWindow::LoadTranslation() {
|
||||
// If the selected language is English, no need to install any translation
|
||||
if (UISettings::values.language == QStringLiteral("en")) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool loaded;
|
||||
|
||||
if (UISettings::values.language.isEmpty()) {
|
||||
// If the selected language is empty, use system locale
|
||||
loaded = translator.load(QLocale(), {}, {}, QStringLiteral(":/languages/"));
|
||||
} else {
|
||||
// Otherwise load from the specified file
|
||||
loaded = translator.load(UISettings::values.language, QStringLiteral(":/languages/"));
|
||||
}
|
||||
|
||||
if (loaded) {
|
||||
qApp->installTranslator(&translator);
|
||||
} else {
|
||||
UISettings::values.language = QStringLiteral("en");
|
||||
}
|
||||
}
|
||||
|
||||
void GMainWindow::OnLanguageChanged(const QString& locale) {
|
||||
if (UISettings::values.language != QStringLiteral("en")) {
|
||||
qApp->removeTranslator(&translator);
|
||||
}
|
||||
|
||||
UISettings::values.language = locale;
|
||||
LoadTranslation();
|
||||
ui.retranslateUi(this);
|
||||
UpdateWindowTitle();
|
||||
|
||||
if (emulation_running)
|
||||
ui.action_Start->setText(tr("Continue"));
|
||||
}
|
||||
|
||||
void GMainWindow::SetDiscordEnabled([[maybe_unused]] bool state) {
|
||||
#ifdef USE_DISCORD_PRESENCE
|
||||
if (state) {
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <QMainWindow>
|
||||
#include <QTimer>
|
||||
#include <QTranslator>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/core.h"
|
||||
|
@ -225,6 +226,7 @@ private slots:
|
|||
void OnCaptureScreenshot();
|
||||
void OnCoreError(Core::System::ResultStatus, std::string);
|
||||
void OnReinitializeKeys(ReinitializeKeyBehavior behavior);
|
||||
void OnLanguageChanged(const QString& locale);
|
||||
|
||||
private:
|
||||
std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id);
|
||||
|
@ -237,6 +239,7 @@ private:
|
|||
void HideMouseCursor();
|
||||
void ShowMouseCursor();
|
||||
void OpenURL(const QUrl& url);
|
||||
void LoadTranslation();
|
||||
|
||||
Ui::MainWindow ui;
|
||||
|
||||
|
@ -285,6 +288,8 @@ private:
|
|||
|
||||
HotkeyRegistry hotkey_registry;
|
||||
|
||||
QTranslator translator;
|
||||
|
||||
// Install progress dialog
|
||||
QProgressDialog* install_progress;
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ struct Values {
|
|||
bool game_dir_deprecated_deepscan;
|
||||
QVector<UISettings::GameDir> game_dirs;
|
||||
QStringList recent_files;
|
||||
QString language;
|
||||
|
||||
QString theme;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue