FOSSredder 0.5.0
Loading...
Searching...
No Matches
LanguageService.cpp
Go to the documentation of this file.
1
6
8
9#include <QApplication>
10#include <QCoreApplication>
11#include <QFileInfo>
12#include <QList>
13#include <QLocale>
14#include <QQmlEngine>
15#include <QSettings>
16
17#include "ui/i18n/Text.h"
19#include "ui/shell/Defaults.h"
20
21namespace ui {
22
23namespace {
24
25using LanguageLabelFactory = QString (*)();
26
27struct LanguageDefinition {
28 QString code;
29 LanguageLabelFactory labelFactory;
30};
31
33QList<LanguageDefinition> supportedLanguages() {
34 return {
38 };
39}
40
42QVariantMap makeLanguageOption(const QString& code, const QString& label,
43 bool available) {
44 QVariantMap option;
45 option.insert(payload::keys::language::kCode, code);
46 option.insert(payload::keys::language::kLabel, label);
47 option.insert(payload::keys::language::kAvailable, available);
48 return option;
49}
50
53QSettings openLanguageSettings() {
54 return QSettings(QSettings::NativeFormat, QSettings::UserScope,
57}
58
59} // namespace
60
61LanguageService::LanguageService(QApplication* application, QQmlEngine* engine,
62 QObject* parent)
63 : QObject(parent), application_(application), engine_(engine) {
64 refreshAvailableLanguages();
65
66 const QString preferredLanguage = normalizeLanguageCode(persistedLanguage());
67 applyCurrentLanguage(preferredLanguage);
68}
69
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)));
76 }
77}
78
79bool LanguageService::applyLanguage(const QString& languageCode) {
80 const bool changed = applyCurrentLanguage(languageCode);
81 return changed || normalizeLanguageCode(languageCode) == currentLanguage_;
82}
83
84void LanguageService::setCurrentLanguage(const QString& languageCode) {
85 applyCurrentLanguage(languageCode);
86}
87
88bool LanguageService::applyCurrentLanguage(const QString& languageCode) {
89 const QString normalizedLanguage = normalizeLanguageCode(languageCode);
90 QString targetLanguage = normalizedLanguage;
91 if (!isLanguageAvailable(targetLanguage)) {
92 targetLanguage = ui::config::languages::kEnglish;
93 }
94
95 const bool isSameLanguage = currentLanguage_ == targetLanguage;
96 if (isSameLanguage && targetLanguage == ui::config::languages::kEnglish) {
97 persistLanguage(targetLanguage);
98 refreshAvailableLanguages();
100 return false;
101 }
102
103 if (application_)
104 application_->removeTranslator(&translator_);
105
106 if (targetLanguage != ui::config::languages::kEnglish) {
107 if (!loadTranslation(targetLanguage)) {
108 targetLanguage = ui::config::languages::kEnglish;
109 }
110 }
111
112 if (isSameLanguage && currentLanguage_ == targetLanguage) {
113 if (application_)
114 application_->installTranslator(&translator_);
115 persistLanguage(targetLanguage);
116 retranslateUi();
117 refreshAvailableLanguages();
119 return false;
120 }
121
122 currentLanguage_ = targetLanguage;
123 persistLanguage(currentLanguage_);
124 retranslateUi();
125 refreshAvailableLanguages();
128 return true;
129}
130
131bool LanguageService::isLanguageAvailable(const QString& languageCode) const {
132 const QString normalizedLanguage = normalizeLanguageCode(languageCode);
133 if (normalizedLanguage == ui::config::languages::kEnglish)
134 return true;
135 return translationFileExists(normalizedLanguage);
136}
137
138QString
139LanguageService::normalizeLanguageCode(const QString& languageCode) const {
140 const QString normalized = languageCode.trimmed().toLower().replace(
141 QLatin1Char('-'), QLatin1Char('_'));
142
143 for (const auto& language : supportedLanguages()) {
144 if (normalized == language.code ||
145 normalized.startsWith(language.code + QLatin1Char('_'))) {
146 return language.code;
147 }
148 }
149
151}
152
153QString
154LanguageService::translationFileName(const QString& languageCode) const {
155 return QStringLiteral("%1_%2.qm")
156 .arg(ui::config::kTranslationBaseName, languageCode);
157}
158
159bool LanguageService::translationFileExists(const QString& languageCode) const {
160 if (languageCode == ui::config::languages::kEnglish)
161 return true;
162
163 const QString fileName = translationFileName(languageCode);
164 const QString appTranslationPath =
165 QCoreApplication::applicationDirPath() + QLatin1Char('/') +
166 ui::config::kTranslationsDirName + QLatin1Char('/') + fileName;
167 if (QFileInfo::exists(appTranslationPath))
168 return true;
169
170 const QString resourceTranslationPath =
172 return QFileInfo::exists(resourceTranslationPath);
173}
174
175bool LanguageService::loadTranslation(const QString& languageCode) {
176 const QString fileName = translationFileName(languageCode);
177 const QString appTranslationDir = QCoreApplication::applicationDirPath() +
178 QLatin1Char('/') +
180
181 if (translator_.load(fileName, appTranslationDir)) {
182 if (application_)
183 application_->installTranslator(&translator_);
184 return true;
185 }
186
187 if (translator_.load(ui::config::kTranslationResourcePrefix + fileName)) {
188 if (application_)
189 application_->installTranslator(&translator_);
190 return true;
191 }
192
193 return false;
194}
195
196void LanguageService::retranslateUi() {
197 if (engine_)
198 engine_->retranslate();
199}
200
201void LanguageService::persistLanguage(const QString& languageCode) {
202 auto settings = openLanguageSettings();
203 settings.setValue(ui::config::preferences::keys::kLanguage, languageCode);
204 settings.sync();
205}
206
207QString LanguageService::persistedLanguage() const {
208 const QString defaultLanguage =
209 normalizeLanguageCode(QLocale::system().name());
210 auto settings = openLanguageSettings();
211 return normalizeLanguageCode(
212 settings.value(ui::config::preferences::keys::kLanguage, defaultLanguage)
213 .toString());
214}
215
216} // namespace ui
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 kGerman
Definition Defaults.h:50
const auto kFrench
Definition Defaults.h:51
const auto kEnglish
Definition Defaults.h:49
const auto kTranslationsDirName
Deployment directory containing compiled translation catalogs.
Definition Defaults.h:32
const auto kTranslationBaseName
Basename prefix for compiled translation catalogs such as fossredder_de.qm.
Definition Defaults.h:38
const auto kSettingsApplicationName
Application name used for the UI's QSettings store.
Definition Defaults.h:45
const auto kTranslationResourcePrefix
Resource prefix used when loading bundled translation catalogs from the Qt resource system.
Definition Defaults.h:35
const auto kSettingsOrganizationName
Organization name used for the UI's QSettings store.
Definition Defaults.h:43
QString frenchLabel()
Display label for French.
Definition Text.h:594
QString germanLabel()
Display label for German.
Definition Text.h:590
QString englishLabel()
Display label for English.
Definition Text.h:586