Revision control

Copy as Markdown

// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <linguistproject/profileutils.h>
#include <linguistproject/projsongenerator.h>
#include <linguistproject/projectdescriptionreader.h>
#include <releasehelper.h>
#include <translator.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qdebug.h>
#include <QtCore/qdir.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qlibraryinfo.h>
#include <QtCore/qtemporaryfile.h>
#include <QtCore/qtranslator.h>
#include <iostream>
QT_USE_NAMESPACE
using namespace Qt::StringLiterals;
static void printUsage()
{
printOut(uR"(
Usage:
lrelease-pro [options] [project-file]...
lrelease-pro is part of Qt's Linguist tool chain. It extracts project
information from qmake projects and passes it to lrelease.
All command line options that are not consumed by lrelease-pro are
passed to lrelease.
Options:
-help Display this information and exit
-dump-json <file>
Only generate the project description json file.
-fail-on-invalid
Fail if translations failing the following checks are found:
validity check of accelerators
validity check of surrounding whitespaces
validity check of ending punctuation
validity check of place markers
To get more details refer to Qt Linguist help
-silent
Do not explain what is being done
-version
Display the version of lrelease-pro and exit
)"_s);
}
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
#ifndef QT_BOOTSTRAPPED
#ifndef Q_OS_WIN32
QTranslator translator;
QTranslator qtTranslator;
QString sysLocale = QLocale::system().name();
QString resourceDir = QLibraryInfo::paths(QLibraryInfo::TranslationsPath).value(0);
if (translator.load("linguist_"_L1 + sysLocale, resourceDir)
&& qtTranslator.load("qt_"_L1 + sysLocale, resourceDir)) {
app.installTranslator(&translator);
app.installTranslator(&qtTranslator);
}
#endif // Q_OS_WIN32
#endif // QT_BOOTSTRAPPED
std::optional<QString> dumpJsonFile;
QStringList inputFiles;
ParamFlags params;
QString markUntranslated;
ConversionData cd;
for (int i = 1; i < argc; ++i) {
QString arg = QString::fromLocal8Bit(argv[i]);
if (arg == "-silent"_L1) {
cd.m_verbose = false;
} else if (arg == "-verbose"_L1) {
cd.m_verbose = true;
} else if (arg == "-version"_L1) {
printOut(QStringLiteral("lrelease-pro version %1\n")
.arg(QLatin1String(QT_VERSION_STR)));
return 0;
} else if (arg == "-help"_L1) {
printUsage();
return 0;
} else if (arg == "-dump-json"_L1) {
++i;
if (i == argc) {
printErr(u"The -dump-json option should be followed by a file name.\n"_s);
return 1;
}
dumpJsonFile.emplace(QFileInfo(QLatin1String(argv[i])).absoluteFilePath());
} else if (arg == "-removeidentical"_L1) {
params.removeIdentical = true;
} else if (arg == "-fail-on-unfinished"_L1) {
params.failOnUnfinished = true;
} else if (arg == "-fail-on-invalid"_L1) {
params.failOnInvalid = true;
} else if (arg == "-nounfinished"_L1) {
cd.m_ignoreUnfinished = true;
} else if (arg == "-markuntranslated"_L1) {
++i;
if (i < argc)
markUntranslated = QString::fromLocal8Bit(argv[i]);
} else if (arg == "-idbased"_L1) {
printOut("The flag -idbased is deprecated and not required anymore."
"It will be removed in a future version\n"_L1);
} else if (!arg.startsWith(u'-')) {
inputFiles << arg;
}
}
if (inputFiles.isEmpty()) {
printUsage();
return 1;
}
const QStringList proFiles = extractProFiles(&inputFiles);
if (proFiles.isEmpty()) {
printErr(u"lrelease-pro: No .pro/.pri files given.\n"_s);
return 1;
}
if (!inputFiles.isEmpty()) {
printErr(QStringLiteral("lrelease-pro: Only .pro/.pri files are supported. "
"Offending files:\n %1\n")
.arg(inputFiles.join("\n "_L1)));
return 1;
}
QStringList translationsVariables = { "TRANSLATIONS"_L1, "EXTRA_TRANSLATIONS"_L1 };
QString outDir = QDir::currentPath();
QHash<QString, QString> outDirMap;
QStringList cleanProFiles;
for (const QString &proFile : proFiles) {
QString cleanFile = QDir::cleanPath(QFileInfo(proFile).absoluteFilePath());
cleanProFiles << cleanFile;
outDirMap[cleanFile] = outDir;
}
QString errorString;
QJsonArray results;
Projects projects = generateProjects(cleanProFiles, translationsVariables, outDirMap, 0,
cd.m_verbose, &errorString, &results);
if (dumpJsonFile) {
QFile projectDescriptionFile(*dumpJsonFile);
if (!projectDescriptionFile.open(QIODevice::WriteOnly))
return 1;
const QByteArray output = QJsonDocument(results).toJson(QJsonDocument::Compact);
projectDescriptionFile.write(output);
projectDescriptionFile.write("\n");
projectDescriptionFile.close();
printOut("Project description saved to: %1\n"_L1.arg(projectDescriptionFile.fileName()));
return 0;
}
if (!errorString.isEmpty()) {
printErr(QStringLiteral("lrelease-pro error: %1\n").arg(errorString));
return 1;
}
if (projects.empty()) {
printErr(u"lrelease-pro error: No projects found in project description\n"_s);
return 1;
}
QStringList tsFiles = translationsFromProjects(projects);
if (tsFiles.isEmpty()) {
printErr(u"lrelease-pro error: no TS files specified.\n"_s);
return 1;
}
if (!markUntranslated.isEmpty())
cd.m_unTrPrefix = markUntranslated;
bool fail = false;
for (const QString &tsFile : std::as_const(tsFiles)) {
if (!releaseTsFile(tsFile, cd, params))
fail = true;
}
return fail ? 1 : 0;
}