21 #include "qtlocalizer.h"
23 #include <QtCore/QCoreApplication>
24 #include <QtCore/QDateTime>
25 #include <QtCore/QLibraryInfo>
26 #include <QtCore/QTranslator>
27 #include <QtCore/QVector>
29 #include <QtCore/QLoggingCategory>
31 Q_LOGGING_CATEGORY(CUTELEE_LOCALIZER,
"cutelee.localizer")
34 explicit Locale(
const QLocale &_locale) : locale(_locale) {}
38 qDeleteAll(systemTranslators);
39 qDeleteAll(themeTranslators);
43 QVector<QTranslator *> externalSystemTranslators;
44 QVector<QTranslator *> systemTranslators;
45 QVector<QTranslator *> themeTranslators;
55 auto localeStruct =
new Locale(locale);
56 m_availableLocales.insert(locale.name(), localeStruct);
57 m_locales.push_back(localeStruct);
63 qDeleteAll(m_availableLocales);
66 QLocale currentLocale()
const
68 Q_ASSERT(!m_locales.isEmpty());
69 if (m_locales.isEmpty()) {
70 qCWarning(CUTELEE_LOCALIZER) <<
"Invalid Locale";
73 return m_locales.last()->locale;
80 int count = -1)
const;
82 QHash<QString, Locale *> m_availableLocales;
84 QList<Locale *> m_locales;
92 static void replacePercentN(
QString *result,
int n)
97 while ((percentPos = result->indexOf(QLatin1Char(
'%'), percentPos + len))
101 if (result->at(percentPos + len) == QLatin1Char(
'L')) {
103 fmt = QStringLiteral(
"%L1");
105 fmt = QStringLiteral(
"%1");
107 if (result->at(percentPos + len) == QLatin1Char(
'n')) {
110 result->replace(percentPos, len, fmt);
118 const QString &context,
int count)
const
122 if (m_locales.isEmpty()) {
124 replacePercentN(&result, count);
128 auto locale = m_locales.last();
129 Q_FOREACH (QTranslator *translator, locale->themeTranslators) {
130 result = translator->translate(
"GR_FILENAME", input.toUtf8().constData(),
131 context.toUtf8().constData(), count);
133 if (result.isEmpty()) {
135 = locale->externalSystemTranslators + locale->systemTranslators;
136 if (translators.isEmpty())
137 return QCoreApplication::translate(
"GR_FILENAME",
138 input.toUtf8().constData(),
139 context.toUtf8().constData(), count);
140 Q_FOREACH (QTranslator *translator, translators) {
141 result = translator->translate(
"GR_FILENAME", input.toUtf8().constData(),
142 context.toUtf8().constData(), count);
143 if (!result.isEmpty())
147 if (!result.isEmpty()) {
148 replacePercentN(&result, count);
151 auto fallback = input;
152 replacePercentN(&fallback, count);
166 d->m_appTranslatorPath = path;
172 d->m_appTranslatorPrefix = prefix;
179 if (!d->m_availableLocales.contains(localeName)) {
180 const QLocale namedLocale(localeName);
181 d->m_availableLocales.insert(localeName,
new Locale(namedLocale));
183 d->m_availableLocales[localeName]->externalSystemTranslators.prepend(
188 QLocale::FormatType formatType)
const
191 return d->currentLocale().toString(date, formatType);
195 QLocale::FormatType formatType)
const
198 return d->currentLocale().toString(time, formatType);
202 QLocale::FormatType formatType)
const
205 return d->currentLocale().toString(dateTime, formatType);
211 return d->currentLocale().toString(number);
217 return d->currentLocale().toString(number,
'f', 2);
221 const QString ¤cyCode)
const
224 auto currencySymbol = QStringLiteral(
"$");
225 if (currencyCode == QStringLiteral(
"EUR")) {
226 currencySymbol = QChar(0x20AC);
227 }
else if (currencyCode == QStringLiteral(
"GBP")) {
228 currencySymbol = QStringLiteral(
"£");
230 currencySymbol = currencyCode;
232 return currencySymbol + QLatin1Char(
' ')
233 + d->currentLocale().toString(value,
'f', 2);
237 const QVariantList &arguments)
240 Q_FOREACH (
const QVariant &arg, arguments) {
241 if (arg.userType() == qMetaTypeId<int>())
242 string =
string.arg(arg.value<
int>());
243 else if (arg.userType() == qMetaTypeId<double>())
244 string =
string.arg(arg.value<
double>());
245 else if (arg.userType() == qMetaTypeId<QDateTime>())
246 string =
string.arg(arg.toDateTime().toString());
248 string =
string.arg(arg.toString());
255 const QVariantList &arguments)
const
258 const auto translated = d->translate(
string, context);
259 return substituteArguments(translated, arguments);
263 const QVariantList &arguments)
const
266 const auto translated = d->translate(
string,
QString());
267 return substituteArguments(translated, arguments);
272 const QVariantList &_arguments)
const
276 auto arguments = _arguments;
277 const auto N = arguments.takeFirst().toInt();
278 const auto translated = d->translate(
string, context, N);
279 return substituteArguments(translated, arguments);
284 const QVariantList &_arguments)
const
288 auto arguments = _arguments;
289 const auto N = arguments.takeFirst().toInt();
290 const auto translated = d->translate(
string,
QString(), N);
291 return substituteArguments(translated, arguments);
297 return d->currentLocale().name();
304 if (!d->m_availableLocales.contains(localeName)) {
305 localeStruct =
new Locale(QLocale(localeName));
306 auto qtTranslator =
new QTranslator;
307 qtTranslator->load(QStringLiteral(
"qt_") + localeName,
308 #
if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
309 QLibraryInfo::location(QLibraryInfo::TranslationsPath));
311 QLibraryInfo::path(QLibraryInfo::TranslationsPath));
313 localeStruct->systemTranslators.append(qtTranslator);
314 auto appTranslator =
new QTranslator;
315 appTranslator->load(d->m_appTranslatorPrefix + localeName,
316 d->m_appTranslatorPath);
317 localeStruct->systemTranslators.append(appTranslator);
318 d->m_availableLocales.insert(localeName, localeStruct);
320 localeStruct = d->m_availableLocales[localeName];
322 Q_ASSERT(localeStruct);
323 d->m_locales.push_back(localeStruct);
329 Q_ASSERT(!d->m_locales.isEmpty());
330 d->m_locales.takeLast();
336 auto it = d->m_availableLocales.constBegin();
337 const auto end = d->m_availableLocales.constEnd();
338 for (; it != end; ++it) {
339 auto translator =
new QTranslator();
341 = translator->load(it.key() + QLatin1Char(
'/') + catalog, path);
345 translator->setObjectName(catalog);
347 it.value()->themeTranslators.prepend(translator);
354 auto it = d->m_availableLocales.constBegin();
355 const auto end = d->m_availableLocales.constEnd();
356 for (; it != end; ++it) {
357 auto tranIt = (*it)->themeTranslators.begin();
358 while (tranIt != (*it)->themeTranslators.end()) {
359 if ((*tranIt)->objectName() == catalog) {
361 tranIt = (*it)->themeTranslators.erase(tranIt);
Interface for implementing an internationalization system.
Provides internationalization based on QLocale and QTranslator.
QString localizePluralString(const QString &string, const QString &pluralForm, const QVariantList &arguments={}) const override
QString localizeDate(const QDate &date, QLocale::FormatType formatType=QLocale::ShortFormat) const override
void installTranslator(QTranslator *translator, const QString &localeName=QLocale::system().name())
QString localizeContextString(const QString &string, const QString &context, const QVariantList &arguments={}) const override
QString currentLocale() const override
void setAppTranslatorPath(const QString &path)
QString localizeNumber(int number) const override
QString localizeMonetaryValue(qreal value, const QString ¤cyCode={}) const override
void popLocale() override
void loadCatalog(const QString &path, const QString &catalog) override
QString localizeTime(const QTime &time, QLocale::FormatType formatType=QLocale::ShortFormat) const override
QString localizeDateTime(const QDateTime &dateTime, QLocale::FormatType formatType=QLocale::ShortFormat) const override
QtLocalizer(const QLocale &locale=QLocale::system())
QString localizePluralContextString(const QString &string, const QString &pluralForm, const QString &context, const QVariantList &arguments={}) const override
void pushLocale(const QString &localeName) override
QString localizeString(const QString &string, const QVariantList &arguments={}) const override
void setAppTranslatorPrefix(const QString &prefix)
void unloadCatalog(const QString &catalog) override
The Cutelee namespace holds all public Cutelee API.