summaryrefslogtreecommitdiff
path: root/src/corelib/kernel/qtranslator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel/qtranslator.cpp')
-rw-r--r--src/corelib/kernel/qtranslator.cpp149
1 files changed, 149 insertions, 0 deletions
diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp
index daa5dc6250..802cf1c282 100644
--- a/src/corelib/kernel/qtranslator.cpp
+++ b/src/corelib/kernel/qtranslator.cpp
@@ -47,6 +47,7 @@
#include "qfileinfo.h"
#include "qstring.h"
+#include "qstringlist.h"
#include "qcoreapplication.h"
#include "qcoreapplication_p.h"
#include "qdatastream.h"
@@ -55,6 +56,7 @@
#include "qalgorithms.h"
#include "qhash.h"
#include "qtranslator_p.h"
+#include "qlocale.h"
#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) && !defined(Q_OS_INTEGRITY)
#define QT_USE_MMAP
@@ -236,6 +238,7 @@ public:
uint contextLength;
uint numerusRulesLength;
+ bool do_load(const QString &filename);
bool do_load(const uchar *data, int len);
QString do_translate(const char *context, const char *sourceText, const char *comment,
int n) const;
@@ -435,7 +438,12 @@ bool QTranslator::load(const QString & filename, const QString & directory,
}
// realname is now the fully qualified name of a readable file.
+ return d->do_load(realname);
+}
+bool QTranslatorPrivate::do_load(const QString &realname)
+{
+ QTranslatorPrivate *d = this;
bool ok = false;
#ifdef QT_USE_MMAP
@@ -497,6 +505,147 @@ bool QTranslator::load(const QString & filename, const QString & directory,
return d->do_load(reinterpret_cast<const uchar *>(d->unmapPointer), d->unmapLength);
}
+static QString find_translation(const QLocale & locale,
+ const QString & filename,
+ const QString & prefix,
+ const QString & directory,
+ const QString & suffix)
+{
+ QString path;
+ if (QFileInfo(filename).isRelative()) {
+ path = directory;
+ if (!path.isEmpty() && !path.endsWith(QLatin1Char('/')))
+ path += QLatin1Char('/');
+ }
+
+ QFileInfo fi;
+ QString realname;
+ QStringList fuzzyLocales;
+
+ // see http://www.unicode.org/reports/tr35/#LanguageMatching for inspiration
+
+ QStringList languages = locale.uiLanguages();
+#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)
+ for (int i = languages.size()-1; i >= 0; --i) {
+ QString lang = languages.at(i);
+ QString lowerLang = lang.toLower();
+ if (lang != lowerLang)
+ languages.insert(i+1, lowerLang);
+ }
+#endif
+
+ // try explicit locales names first
+ foreach (QString localeName, languages) {
+ localeName.replace(QLatin1Char('-'), QLatin1Char('_'));
+
+ realname = path + filename + prefix + localeName + (suffix.isNull() ? QLatin1String(".qm") : suffix);
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+
+ realname = path + filename + prefix + localeName;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+
+ fuzzyLocales.append(localeName);
+ }
+
+ // start guessing
+ foreach (QString localeName, fuzzyLocales) {
+ for (;;) {
+ int rightmost = localeName.lastIndexOf(QLatin1Char('_'));
+ // no truncations? fail
+ if (rightmost <= 0)
+ break;
+ localeName.truncate(rightmost);
+
+ realname = path + filename + prefix + localeName + (suffix.isNull() ? QLatin1String(".qm") : suffix);
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+
+ realname = path + filename + prefix + localeName;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+ }
+ }
+
+ if (!suffix.isNull()) {
+ realname = path + filename + suffix;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+ }
+
+ realname = path + filename + prefix;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+
+ realname = path + filename;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+
+ return QString();
+}
+
+/*!
+ \since 4.8
+
+ Loads \a filename + \a prefix + \a locale name + \a suffix (".qm" if the \a
+ suffix is not specified), which may be an absolute file name or relative to
+ \a directory. Returns true if the translation is successfully loaded;
+ otherwise returns false.
+
+ The previous contents of this translator object are discarded.
+
+ If the file name does not exist, other file names are tried
+ in the following order:
+
+ \list 1
+ \o File name without \a suffix appended.
+ \o File name with locale part after a "_" character stripped and \a suffix.
+ \o File name with locale part stripped without \a suffix appended.
+ \o File name with locale part stripped further, etc.
+ \endlist
+
+ For example, an application running in the locale with the following
+ l{QLocale::uiLanguages()}{ui languages} - "es", "fr-CA", "de" might call
+ load(QLocale::system(), "foo", ".", "/opt/foolib", ".qm"). load() would
+ then try to open the first existing readable file from this list:
+
+ \list 1
+ \o \c /opt/foolib/foo.es.qm
+ \o \c /opt/foolib/foo.es
+ \o \c /opt/foolib/foo.fr_CA.qm
+ \o \c /opt/foolib/foo.fr_CA
+ \o \c /opt/foolib/foo.de.qm
+ \o \c /opt/foolib/foo.de
+ \o \c /opt/foolib/foo.fr.qm
+ \o \c /opt/foolib/foo.fr
+ \o \c /opt/foolib/foo.qm
+ \o \c /opt/foolib/foo.
+ \o \c /opt/foolib/foo
+ \endlist
+
+ For OSs where file system is case sensitive, QTranslator also tries to load
+ a lower-cased version of the locale name.
+*/
+bool QTranslator::load(const QLocale & locale,
+ const QString & filename,
+ const QString & prefix,
+ const QString & directory,
+ const QString & suffix)
+{
+ Q_D(QTranslator);
+ d->clear();
+ QString fname = find_translation(locale, filename, prefix, directory, suffix);
+ return !fname.isEmpty() && d->do_load(fname);
+}
+
/*!
\overload load()
\fn bool QTranslator::load(const uchar *data, int len)