QTranslator: refactor loading translation files

QTranslator::load() used to:
- call find_translation(), which finds the file, ensures it's readable,
  and returns file name
- pass the file name to do_load() which would proceed to open the
  file

During the time between calling find_translation()/is_readable_file()
and calling do_load(), the underlying filesystem could have changed.

Solve the issue by making find_translation() call do_load() itself (as
suggested in the bug report). Also rename the method to
load_translation() and make it a member method so that it can call
do_load().

Remove the now redundant is_readable_file() static helper, since
QFile::open() in do_load() will do the necessary checks.

Note that there is a slight behavior change:
- with this commit we call do_load() on a variant of the translation
  file name, if that fails we call it again on the next variant ...etc
- before this, if the file was readable, the code called do_load() once,
  if it failed, it didn't try again.
This was suggested by Volker in code review as a good/welcome
side-effect.

Task-number: QTBUG-129777
Change-Id: Ie5fada60dd6267e67cda4272530db69a44f3ee55
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Ahmad Samir 2024-10-10 19:30:52 +03:00
parent 3bb4c4949f
commit c41aa89610

View File

@ -292,6 +292,8 @@ public:
QString language;
QString filePath;
bool load_translation(const QLocale &locale, const QString &filename, const QString &prefix,
const QString &directory, const QString &suffix);
bool do_load(const QString &filename, const QString &directory);
bool do_load(const uchar *data, qsizetype len, const QString &directory);
QString do_translate(const char *context, const char *sourceText, const char *comment,
@ -596,21 +598,11 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo
return false;
}
Q_NEVER_INLINE
static bool is_readable_file(const QString &name)
{
const QFileInfo fi(name);
const bool isReadableFile = fi.isReadable() && fi.isFile();
qCDebug(lcTranslator) << "Testing file" << name << isReadableFile;
return isReadableFile;
}
static QString find_translation(const QLocale & locale,
const QString & filename,
const QString & prefix,
const QString & directory,
const QString & suffix)
bool QTranslatorPrivate::load_translation(const QLocale &locale,
const QString &filename,
const QString &prefix,
const QString &directory,
const QString &suffix)
{
qCDebug(lcTranslator).noquote().nospace() << "Searching translation for "
<< filename << prefix << locale << suffix
@ -638,19 +630,21 @@ static QString find_translation(const QLocale & locale,
const QStringList languages = locale.uiLanguages(QLocale::TagSeparator::Underscore);
qCDebug(lcTranslator) << "Requested UI languages" << languages;
auto loadFile = [this, &realname, &directory] { return do_load(realname, directory); };
for (const QString &localeName : languages) {
QString loc = localeName;
// First try this given name, then in lower-case form (if different):
while (true) {
// First, try with suffix:
realname += loc + suffixOrDotQM;
if (is_readable_file(realname))
return realname;
if (loadFile())
return true;
// Next, try without:
realname.truncate(realNameBaseSize + loc.size());
if (is_readable_file(realname))
return realname;
if (loadFile())
return true;
// Reset realname:
realname.truncate(realNameBaseSize);
@ -669,22 +663,18 @@ static QString find_translation(const QLocale & locale,
if (!suffix.isNull()) {
realname.replace(realNameBaseSizeFallbacks, prefix.size(), suffix);
// realname == path + filename;
if (is_readable_file(realname))
return realname;
if (loadFile())
return true;
realname.replace(realNameBaseSizeFallbacks, suffix.size(), prefix);
}
// realname == path + filename + prefix;
if (is_readable_file(realname))
return realname;
if (loadFile())
return true;
realname.truncate(realNameBaseSizeFallbacks);
// realname == path + filename;
if (is_readable_file(realname))
return realname;
realname.truncate(0);
return realname;
return loadFile();
}
/*!
@ -738,8 +728,7 @@ bool QTranslator::load(const QLocale & locale,
{
Q_D(QTranslator);
d->clear();
QString fname = find_translation(locale, filename, prefix, directory, suffix);
return !fname.isEmpty() && d->do_load(fname, directory);
return d->load_translation(locale, filename, prefix, directory, suffix);
}
/*!