aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Gräßlin <mgraesslin@kde.org>2014-06-12 11:30:24 +0200
committerMartin Gräßlin <mgraesslin@kde.org>2014-06-21 07:41:18 +0200
commita52b00f31eb5df1cd603975bdd31794233898a59 (patch)
tree4f302c61a3f77216b9cf29208b4c7cd79eb60edf
parent9aeacb07b1169fa3dc9b7653e8f30070a91569d5 (diff)
downloadkconfig-a52b00f31eb5df1cd603975bdd31794233898a59.tar.gz
kconfig-a52b00f31eb5df1cd603975bdd31794233898a59.tar.bz2
Fix reading of entries for language/country combinations
This fixes a regression introduced in 988f09bb051dca0437ecec431ee44ed5b4a560d8. The mentioned commit ensures that if the locale is e.g. "de_DE" the entry "de" will be used. But this breaks if there is a translation for another country. E.g. for "de_CH" it would also pick the "de" entry. This change now operates on both just the language code and the locale. If an entry with the language code is present it will be picked. If another entry with the exact locale is found it will be overwritten. Modifiers are not supported as this is currently missing in QLocale. REVIEW: 118692
-rw-r--r--autotests/kdesktopfiletest.cpp37
-rw-r--r--autotests/kdesktopfiletest.h1
-rw-r--r--src/core/kconfig.cpp2
-rw-r--r--src/core/kconfigdata.cpp13
-rw-r--r--src/core/kconfigdata.h9
-rw-r--r--src/core/kconfigini.cpp7
6 files changed, 59 insertions, 10 deletions
diff --git a/autotests/kdesktopfiletest.cpp b/autotests/kdesktopfiletest.cpp
index 6c3af4c2..12277331 100644
--- a/autotests/kdesktopfiletest.cpp
+++ b/autotests/kdesktopfiletest.cpp
@@ -50,6 +50,29 @@ void KDesktopFileTest::testRead()
QCOMPARE(df.fileName(), QFileInfo(fileName).canonicalFilePath());
}
+void KDesktopFileTest::testReadLocalized_data()
+{
+ QTest::addColumn<QLocale>("locale");
+ QTest::addColumn<QString>("translation");
+
+ const QString german = QStringLiteral("Meine Anwendung");
+ const QString swiss = QStringLiteral("Mein Anwendungsli");
+
+ QTest::newRow("de") << QLocale(QLocale::German) << german;
+ QTest::newRow("de_DE") << QLocale(QStringLiteral("de_DE")) << german;
+ QTest::newRow("de_DE@bayern") << QLocale(QStringLiteral("de_DE@bayern")) << german;
+ QTest::newRow("de@bayern") << QLocale(QStringLiteral("de@bayern")) << german;
+ QTest::newRow("de@freiburg") << QLocale(QStringLiteral("de@freiburg")) << QStringLiteral("Mein Anwendungsle");
+ // For CH we have a special translation
+ QTest::newRow("de_CH") << QLocale(QLocale::German, QLocale::Switzerland) << swiss;
+ QTest::newRow("de_CH@bern") << QLocale(QStringLiteral("de_CH@bern")) << swiss;
+ // Austria should fall back to "de"
+ QTest::newRow("de_AT") << QLocale(QLocale::German, QLocale::QLocale::Austria) << german;
+ QTest::newRow("de_AT@tirol") << QLocale(QStringLiteral("de_AT@tirol")) << german;
+ // no translation for French
+ QTest::newRow("fr") << QLocale(QLocale::French) << QStringLiteral("My Application");
+}
+
void KDesktopFileTest::testReadLocalized()
{
QTemporaryFile file("testReadLocalizedXXXXXX.desktop");
@@ -61,6 +84,8 @@ void KDesktopFileTest::testReadLocalized()
"Type=Application\n"
"Name=My Application\n"
"Name[de]=Meine Anwendung\n"
+ "Name[de@freiburg]=Mein Anwendungsle\n"
+ "Name[de_CH]=Mein Anwendungsli\n"
"Icon=foo\n"
"\n";
file.close();
@@ -68,15 +93,13 @@ void KDesktopFileTest::testReadLocalized()
QVERIFY(KDesktopFile::isDesktopFile(fileName));
DefaultLocale defaultLocale;
- // set language to German for which we have a translation
- QLocale::setDefault(QLocale(QLocale::German));
+
+ QFETCH(QLocale, locale);
+ QLocale::setDefault(locale);
KDesktopFile df(fileName);
- QCOMPARE(df.readName(), QString::fromLatin1("Meine Anwendung"));
- // set language to French for which we don't have a translation
- QLocale::setDefault(QLocale(QLocale::French));
- KDesktopFile df2(fileName);
- QCOMPARE(df2.readName(), QString::fromLatin1("My Application"));
+ QEXPECT_FAIL("de@freiburg", "QLocale doesn't support modifiers", Continue);
+ QTEST(df.readName(), "translation");
}
void KDesktopFileTest::testSuccessfulTryExec()
diff --git a/autotests/kdesktopfiletest.h b/autotests/kdesktopfiletest.h
index f854d6cc..f4e0c96b 100644
--- a/autotests/kdesktopfiletest.h
+++ b/autotests/kdesktopfiletest.h
@@ -26,6 +26,7 @@ class KDesktopFileTest : public QObject
Q_OBJECT
private Q_SLOTS:
void testRead();
+ void testReadLocalized_data();
void testReadLocalized();
void testUnsuccessfulTryExec();
void testSuccessfulTryExec();
diff --git a/src/core/kconfig.cpp b/src/core/kconfig.cpp
index b9319994..484a9a97 100644
--- a/src/core/kconfig.cpp
+++ b/src/core/kconfig.cpp
@@ -95,7 +95,7 @@ KConfigPrivate::KConfigPrivate(KConfig::OpenFlags flags,
// mappingsRegistered = true;
// }
- setLocale(QLocale().name().split(QStringLiteral("_")).at(0));
+ setLocale(QLocale().name());
}
bool KConfigPrivate::lockLocal()
diff --git a/src/core/kconfigdata.cpp b/src/core/kconfigdata.cpp
index 109063d6..6ef6af07 100644
--- a/src/core/kconfigdata.cpp
+++ b/src/core/kconfigdata.cpp
@@ -145,6 +145,11 @@ bool KEntryMap::setEntry(const QByteArray &group, const QByteArray &key, const Q
}
e.bExpand = (options & EntryExpansion);
e.bReverted = false;
+ if (options & EntryLocalized) {
+ e.bLocalizedCountry = (options & EntryLocalizedCountry);
+ } else {
+ e.bLocalizedCountry = false;
+ }
if (newKey) {
//qDebug() << "inserting" << k << "=" << value;
@@ -158,6 +163,14 @@ bool KEntryMap::setEntry(const QByteArray &group, const QByteArray &key, const Q
return true;
} else {
// KEntry e2 = it.value();
+ if (options & EntryLocalized) {
+ // fast exit checks for cases where the existing entry is more specific
+ const KEntry &e2 = it.value();
+ if (e2.bLocalizedCountry && !e.bLocalizedCountry) {
+ // lang_COUNTRY > lang
+ return false;
+ }
+ }
if (it.value() != e) {
//qDebug() << "changing" << k << "from" << e.mValue << "to" << value;
it.value() = e;
diff --git a/src/core/kconfigdata.h b/src/core/kconfigdata.h
index fdec85dc..3b70c24f 100644
--- a/src/core/kconfigdata.h
+++ b/src/core/kconfigdata.h
@@ -36,7 +36,8 @@ struct KEntry {
/** Constructor. @internal */
KEntry()
: mValue(), bDirty(false),
- bGlobal(false), bImmutable(false), bDeleted(false), bExpand(false), bReverted(false) {}
+ bGlobal(false), bImmutable(false), bDeleted(false), bExpand(false), bReverted(false),
+ bLocalizedCountry(false) {}
/** @internal */
QByteArray mValue;
/**
@@ -63,6 +64,11 @@ struct KEntry {
* Entry has been reverted to its default value (from a more global file).
*/
bool bReverted: 1;
+ /**
+ * Entry is for a localized key. If @c false the value references just language e.g. "de",
+ * if @c true the value references language and country, e.g. "de_DE".
+ **/
+ bool bLocalizedCountry: 1;
};
// These operators are used to check whether an entry which is about
@@ -165,6 +171,7 @@ public:
EntryDeleted = 8,
EntryExpansion = 16,
EntryRawKey = 32,
+ EntryLocalizedCountry = 64,
EntryDefault = (SearchDefaults << 16),
EntryLocalized = (SearchLocalized << 16)
};
diff --git a/src/core/kconfigini.cpp b/src/core/kconfigini.cpp
index f4ce9410..5fe4de03 100644
--- a/src/core/kconfigini.cpp
+++ b/src/core/kconfigini.cpp
@@ -85,6 +85,8 @@ KConfigIniBackend::parseConfig(const QByteArray &currentLocale, KEntryMap &entry
return ParseOk;
}
+ const QByteArray currentLanguage = currentLocale.split('_').first();
+
bool bDefault = options & ParseDefaults;
bool allowExecutableValues = options & ParseExpansions;
@@ -251,7 +253,7 @@ KConfigIniBackend::parseConfig(const QByteArray &currentLocale, KEntryMap &entry
}
printableToString(&aKey, file, lineNo);
if (!locale.isEmpty()) {
- if (locale != currentLocale) {
+ if (locale != currentLocale && locale != currentLanguage) {
// backward compatibility. C == en_US
if (locale.at(0) != 'C' || currentLocale != "en_US") {
if (merging) {
@@ -275,6 +277,9 @@ KConfigIniBackend::parseConfig(const QByteArray &currentLocale, KEntryMap &entry
}
if (!locale.isNull()) {
entryOptions |= KEntryMap::EntryLocalized;
+ if (locale.indexOf('_') != -1) {
+ entryOptions |= KEntryMap::EntryLocalizedCountry;
+ }
}
printableToString(&line, file, lineNo);
if (entryOptions & KEntryMap::EntryRawKey) {