diff --git a/.ci/deploy-windows-clang.sh b/.ci/deploy-windows-clang.sh
index c95f82e7b8..0bf731e7c8 100644
--- a/.ci/deploy-windows-clang.sh
+++ b/.ci/deploy-windows-clang.sh
@@ -38,7 +38,7 @@ else
echo "Failed to download translations.zip. Continuing without translations."
exit 0
}
- unzip -o translations.zip -d "./bin/share/qt6/translations" >/dev/null 2>&1 || \
+ 7z x translations.zip -o"./bin/share/qt6/translations" >/dev/null 2>&1 || \
echo "Failed to extract translations.zip. Continuing without translations."
rm -f translations.zip
fi
diff --git a/.ci/setup-windows.sh b/.ci/setup-windows.sh
index f637cec9ad..d874c7a7f0 100755
--- a/.ci/setup-windows.sh
+++ b/.ci/setup-windows.sh
@@ -14,6 +14,7 @@ QT_DECL_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qtdeclarative${QT_SUFFIX}"
QT_TOOL_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qttools${QT_SUFFIX}"
QT_MM_URL="${QT_HOST}${QT_PREFIX}addons.qtmultimedia.${QT_PREFIX_2}qtmultimedia${QT_SUFFIX}"
QT_SVG_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qtsvg${QT_SUFFIX}"
+QT_TRANSLATIONS_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qttranslations${QT_SUFFIX}"
LLVMLIBS_URL="https://github.com/RPCS3/llvm-mirror/releases/download/custom-build-win-${LLVM_VER}/llvmlibs_mt.7z"
VULKAN_SDK_URL="https://www.dropbox.com/scl/fi/sjjh0fc4ld281pjbl2xzu/VulkanSDK-${VULKAN_VER}-Installer.exe?rlkey=f6wzc0lvms5vwkt2z3qabfv9d&dl=1"
CCACHE_URL="https://github.com/ccache/ccache/releases/download/v4.11.2/ccache-4.11.2-windows-x86_64.zip"
@@ -24,6 +25,7 @@ DEP_URLS=" \
$QT_TOOL_URL \
$QT_MM_URL \
$QT_SVG_URL \
+ $QT_TRANSLATIONS_URL \
$LLVMLIBS_URL \
$VULKAN_SDK_URL\
$CCACHE_URL"
diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj
index b38aa78567..83de843746 100644
--- a/rpcs3/rpcs3.vcxproj
+++ b/rpcs3/rpcs3.vcxproj
@@ -110,7 +110,7 @@
- $(QTDIR)\bin\windeployqt6 --no-compiler-runtime --no-opengl-sw --no-patchqt --no-translations --no-quick --no-system-d3d-compiler --no-system-dxc-compiler --no-quick-import --plugindir "$(TargetDir)qt6\plugins" --release "$(TargetPath)"
+ $(QTDIR)\bin\windeployqt6 --no-compiler-runtime --no-opengl-sw --no-patchqt --no-quick --no-system-d3d-compiler --no-system-dxc-compiler --no-quick-import --plugindir "$(TargetDir)qt6\plugins" --translationdir "$(TargetDir)qt6\translations" --release "$(TargetPath)"
xcopy /y /d "$(SolutionDir)3rdparty\opencv\opencv\opencv412\build\x64\bin\opencv_world4120.dll" "$(OutDir)"
@@ -169,7 +169,7 @@
- $(QTDIR)\bin\windeployqt6 --no-compiler-runtime --no-opengl-sw --no-patchqt --no-translations --no-quick --no-system-d3d-compiler --no-system-dxc-compiler --no-quick-import --plugindir "$(TargetDir)qt6\plugins" --debug "$(TargetPath)"
+ $(QTDIR)\bin\windeployqt6 --no-compiler-runtime --no-opengl-sw --no-patchqt --no-quick --no-system-d3d-compiler --no-system-dxc-compiler --no-quick-import --plugindir "$(TargetDir)qt6\plugins" --translationdir "$(TargetDir)qt6\translations" --debug "$(TargetPath)"
xcopy /y /d "$(SolutionDir)3rdparty\opencv\opencv\opencv412\build\x64\bin\opencv_world4120.dll" "$(OutDir)"
diff --git a/rpcs3/rpcs3qt/gui_application.cpp b/rpcs3/rpcs3qt/gui_application.cpp
index e028aaefa8..443dcb4e0c 100644
--- a/rpcs3/rpcs3qt/gui_application.cpp
+++ b/rpcs3/rpcs3qt/gui_application.cpp
@@ -216,29 +216,74 @@ bool gui_application::Init()
return true;
}
-void gui_application::SwitchTranslator(QTranslator& translator, const QString& filename, const QString& language_code)
+void gui_application::SwitchTranslator(const QString& language_code)
{
// remove the old translator
- removeTranslator(&translator);
+ removeTranslator(&m_translator);
+ for (QTranslator* qt_translator : m_qt_translators)
+ {
+ removeTranslator(qt_translator);
+ qt_translator->deleteLater();
+ }
+ m_qt_translators.clear();
+ const QString default_code = QLocale(QLocale::English).bcp47Name();
const QString lang_path = QLibraryInfo::path(QLibraryInfo::TranslationsPath) + QStringLiteral("/");
- const QString file_path = lang_path + filename;
+ // Load qt translation files
+ const QDir dir(lang_path);
+ if (dir.exists())
+ {
+ QStringList qm_files = dir.entryList(QStringList() << QStringLiteral("qt*_%1.qm").arg(language_code), QDir::Files | QDir::Readable);
+ if (qm_files.empty())
+ {
+ qm_files = dir.entryList(QStringList() << QStringLiteral("qt*_%1.qm").arg(QLocale::languageToCode(QLocale(language_code).language())), QDir::Files | QDir::Readable);
+ }
+
+ for (const QString& qm_file : qm_files)
+ {
+ const QString file_path = lang_path + qm_file;
+ QTranslator* qt_translator = new QTranslator(this);
+
+ if (qt_translator->load(file_path))
+ {
+ gui_log.notice("Installing translation: '%s'", file_path);
+ installTranslator(qt_translator);
+ m_qt_translators.push_back(std::move(qt_translator));
+ }
+ else
+ {
+ gui_log.error("Failed to load translation: '%s'", file_path);
+ qt_translator->deleteLater();
+ }
+ }
+ }
+ else
+ {
+ gui_log.error("Qt translation dir '%s' does not exist", lang_path);
+ }
+
+ const QString file_path = lang_path + QStringLiteral("rpcs3_%1.qm").arg(language_code);
if (QFileInfo(file_path).isFile())
{
// load the new translator
- if (translator.load(file_path))
+ if (m_translator.load(file_path))
{
- installTranslator(&translator);
+ gui_log.notice("Installing translation: '%s'", file_path);
+ installTranslator(&m_translator);
+ }
+ else
+ {
+ gui_log.error("Failed to load translation: '%s'", file_path);
}
}
- else if (QString default_code = QLocale(QLocale::English).bcp47Name(); language_code != default_code)
+ else if (language_code != default_code)
{
// show error, but ignore default case "en", since it is handled in source code
- gui_log.error("No translation file found in: %s", file_path);
+ gui_log.error("No translation file found in: '%s'", file_path);
// reset current language to default "en"
- set_language_code(std::move(default_code));
+ set_language_code(default_code);
}
}
@@ -260,7 +305,7 @@ void gui_application::LoadLanguage(const QString& language_code)
// As per QT recommendations to avoid conflicts for POSIX functions
std::setlocale(LC_NUMERIC, "C");
- SwitchTranslator(m_translator, QStringLiteral("rpcs3_%1.qm").arg(language_code), language_code);
+ SwitchTranslator(language_code);
if (m_main_window)
{
@@ -285,6 +330,7 @@ QStringList gui_application::GetAvailableLanguageCodes()
QStringList language_codes;
const QString language_path = QLibraryInfo::path(QLibraryInfo::TranslationsPath);
+ gui_log.notice("Checking languages in '%s'", language_path);
if (QFileInfo(language_path).isDir())
{
@@ -303,10 +349,15 @@ QStringList gui_application::GetAvailableLanguageCodes()
}
else
{
+ gui_log.notice("Found language '%s' (%s)", language_code, filename);
language_codes << language_code;
}
}
}
+ else
+ {
+ gui_log.error("Language dir not found: '%s'", language_path);
+ }
return language_codes;
}
diff --git a/rpcs3/rpcs3qt/gui_application.h b/rpcs3/rpcs3qt/gui_application.h
index bec8424da4..948965ef47 100644
--- a/rpcs3/rpcs3qt/gui_application.h
+++ b/rpcs3/rpcs3qt/gui_application.h
@@ -81,7 +81,7 @@ private:
return thread();
}
- void SwitchTranslator(QTranslator& translator, const QString& filename, const QString& language_code);
+ void SwitchTranslator(const QString& language_code);
void LoadLanguage(const QString& language_code);
static QStringList GetAvailableLanguageCodes();
@@ -101,6 +101,7 @@ private:
} m_native_event_filter;
+ std::vector m_qt_translators;
QTranslator m_translator;
QString m_language_code;
static s32 m_language_id;