10#include <QCoreApplication>
25using LanguageLabelFactory = QString (*)();
27struct LanguageDefinition {
29 LanguageLabelFactory labelFactory;
33QList<LanguageDefinition> supportedLanguages() {
42QVariantMap makeLanguageOption(
const QString& code,
const QString& label,
53QSettings openLanguageSettings() {
54 return QSettings(QSettings::NativeFormat, QSettings::UserScope,
63 : QObject(parent), application_(application), engine_(engine) {
64 refreshAvailableLanguages();
66 const QString preferredLanguage = normalizeLanguageCode(persistedLanguage());
67 applyCurrentLanguage(preferredLanguage);
70void LanguageService::refreshAvailableLanguages() {
71 availableLanguages_.clear();
72 for (
const auto& language : supportedLanguages()) {
73 availableLanguages_.append(
74 makeLanguageOption(language.code, language.labelFactory(),
75 isLanguageAvailable(language.code)));
80 const bool changed = applyCurrentLanguage(languageCode);
81 return changed || normalizeLanguageCode(languageCode) == currentLanguage_;
85 applyCurrentLanguage(languageCode);
88bool LanguageService::applyCurrentLanguage(
const QString& languageCode) {
89 const QString normalizedLanguage = normalizeLanguageCode(languageCode);
90 QString targetLanguage = normalizedLanguage;
91 if (!isLanguageAvailable(targetLanguage)) {
95 const bool isSameLanguage = currentLanguage_ == targetLanguage;
97 persistLanguage(targetLanguage);
98 refreshAvailableLanguages();
104 application_->removeTranslator(&translator_);
107 if (!loadTranslation(targetLanguage)) {
112 if (isSameLanguage && currentLanguage_ == targetLanguage) {
114 application_->installTranslator(&translator_);
115 persistLanguage(targetLanguage);
117 refreshAvailableLanguages();
122 currentLanguage_ = targetLanguage;
123 persistLanguage(currentLanguage_);
125 refreshAvailableLanguages();
131bool LanguageService::isLanguageAvailable(
const QString& languageCode)
const {
132 const QString normalizedLanguage = normalizeLanguageCode(languageCode);
135 return translationFileExists(normalizedLanguage);
139LanguageService::normalizeLanguageCode(
const QString& languageCode)
const {
140 const QString normalized = languageCode.trimmed().toLower().replace(
141 QLatin1Char(
'-'), QLatin1Char(
'_'));
143 for (
const auto& language : supportedLanguages()) {
144 if (normalized == language.code ||
145 normalized.startsWith(language.code + QLatin1Char(
'_'))) {
146 return language.code;
154LanguageService::translationFileName(
const QString& languageCode)
const {
155 return QStringLiteral(
"%1_%2.qm")
159bool LanguageService::translationFileExists(
const QString& languageCode)
const {
163 const QString fileName = translationFileName(languageCode);
164 const QString appTranslationPath =
165 QCoreApplication::applicationDirPath() + QLatin1Char(
'/') +
167 if (QFileInfo::exists(appTranslationPath))
170 const QString resourceTranslationPath =
172 return QFileInfo::exists(resourceTranslationPath);
175bool LanguageService::loadTranslation(
const QString& languageCode) {
176 const QString fileName = translationFileName(languageCode);
177 const QString appTranslationDir = QCoreApplication::applicationDirPath() +
181 if (translator_.load(fileName, appTranslationDir)) {
183 application_->installTranslator(&translator_);
189 application_->installTranslator(&translator_);
196void LanguageService::retranslateUi() {
198 engine_->retranslate();
201void LanguageService::persistLanguage(
const QString& languageCode) {
202 auto settings = openLanguageSettings();
207QString LanguageService::persistedLanguage()
const {
208 const QString defaultLanguage =
209 normalizeLanguageCode(QLocale::system().name());
210 auto settings = openLanguageSettings();
211 return normalizeLanguageCode(
Defines UI-specific runtime constants that are not shared with core.
Declares the UI service responsible for runtime language switching.
Declarations for the UI PayloadKeys component.
Provides translated C++ UI strings for shell, workflow, adapter and view model code.
void setCurrentLanguage(const QString &languageCode)
Switch the active UI language if the requested translation is available.
void availableLanguagesChanged()
Emitted when the available language list changes.
LanguageService(QApplication *application, QQmlEngine *engine, QObject *parent=nullptr)
Create a language service bound to the application and QML engine.
void currentLanguageChanged()
Emitted when the active language changes.
Q_INVOKABLE bool applyLanguage(const QString &languageCode)
Applies a language code from QML.
const auto kTranslationsDirName
Deployment directory containing compiled translation catalogs.
const auto kTranslationBaseName
Basename prefix for compiled translation catalogs such as fossredder_de.qm.
const auto kSettingsApplicationName
Application name used for the UI's QSettings store.
const auto kTranslationResourcePrefix
Resource prefix used when loading bundled translation catalogs from the Qt resource system.
const auto kSettingsOrganizationName
Organization name used for the UI's QSettings store.
QString frenchLabel()
Display label for French.
QString germanLabel()
Display label for German.
QString englishLabel()
Display label for English.