6#include <profileutils.h>
7#include <projectdescriptionreader.h>
10#ifndef QT_BOOTSTRAPPED
11#include <QtCore/QCoreApplication>
12#include <QtCore/QTranslator>
14#include <QtCore/QDebug>
16#include <QtCore/QFile>
17#include <QtCore/QFileInfo>
18#include <QtCore/QString>
19#include <QtCore/QStringList>
20#include <QtCore/QTextStream>
21#include <QtCore/QLibraryInfo>
25using namespace Qt::StringLiterals;
29 QTextStream stream(stdout);
35 QTextStream stream(stderr);
42 lrelease [options] -project project-file
43 lrelease [options] ts-files [-qm qm-file]
45lrelease is part of Qt's Linguist tool chain. It can be used as a
46stand-alone tool to convert XML-based translations files in the TS
47format into the 'compiled' QM format used by QTranslator objects.
48
49Passing .pro files to lrelease is deprecated.
50Please use the lrelease-pro tool instead, or use qmake's lrelease.prf
51feature.
52
53Options:
54 -help Display this information and exit
55 -idbased
56 Deprecated. The flag is not required anymore and will be removed
57 in a future version. It was used to enable ID based translation.
59 Compress the QM files
60 -nounfinished
61 Do not include unfinished translations
62 -fail-on-unfinished
63 Generate an error if unfinished translations are found
64 -removeidentical
65 If the translated text is the same as
66 the source text, do not include the message
67 -markuntranslated <prefix>
68 If a message has no real translation, use the source text
69 prefixed with the given string instead
70 -project <filename>
71 Name of a file containing the project's description in JSON format.
72 Such a file may be generated from a .pro file using the lprodump tool.
73 -silent
74 Do not explain what is being done
75 -verbose
76 Explain what is being done (default)
77 -version
78 Display the version of lrelease and exit
79)"_s);
82static bool loadTsFile(
Translator &tor,
const QString &tsFileName)
85 bool ok = tor.load(tsFileName, cd,
"auto"_L1);
87 printErr(
"lrelease error: %1"_L1.arg(cd.error()));
89 if (!cd.errors().isEmpty())
97 bool removeIdentical,
bool failOnUnfinished)
100 printErr(
"lrelease error: cannot create '%1': existing unfinished translation(s) "
101 "found (-fail-on-unfinished)"_L1.arg(qmFileName));
108 printOut(
"Updating '%1'...\n"_L1.arg(qmFileName));
109 if (removeIdentical) {
111 printOut(
"Removing translations equal to source text in '%1'...\n"_L1.arg(qmFileName));
115 QFile file(qmFileName);
116 if (!file.open(QIODevice::WriteOnly)) {
117 printErr(
"lrelease error: cannot create '%1': %2\n"_L1.arg(qmFileName, file.errorString()));
122 bool ok = saveQM(tor, file, cd);
126 printErr(
"lrelease error: cannot save '%1': %2"_L1.arg(qmFileName, cd.error()));
127 }
else if (!cd.errors().isEmpty()) {
128 printOut(cd.error());
134static bool releaseTsFile(
const QString &tsFileName,
ConversionData &cd,
bool removeIdentical,
135 bool failOnUnfinished)
138 if (!loadTsFile(tor, tsFileName))
141 QString qmFileName = tsFileName;
142 for (
const Translator::FileFormat &fmt : std::as_const(Translator::registeredFileFormats())) {
143 if (qmFileName.endsWith(u'.' + fmt.extension)) {
144 qmFileName.chop(fmt.extension.size() + 1);
148 qmFileName +=
".qm"_L1;
150 return releaseTranslator(tor, qmFileName, cd, removeIdentical, failOnUnfinished);
153static QStringList translationsFromProjects(
const Projects &projects,
bool topLevel);
155static QStringList translationsFromProject(
const Project &project,
bool topLevel)
158 if (project.translations)
159 result = *project.translations;
160 result << translationsFromProjects(project.subProjects,
false);
161 if (topLevel && result.isEmpty()) {
162 printErr(
"lrelease warning: Met no 'TRANSLATIONS' entry in project file '%1'\n"_L1.arg(
168static QStringList translationsFromProjects(
const Projects &projects,
bool topLevel =
true)
171 for (
const Project &p : projects)
172 result << translationsFromProject(p, topLevel);
176int main(
int argc,
char **argv)
178 QCoreApplication app(argc, argv);
182 bool removeIdentical =
false;
183 bool failOnUnfinished =
false;
185 QStringList inputFiles;
187 QString projectDescriptionFile;
189 for (
int i = 1; i < argc; ++i) {
190 const char *arg = argv[i];
191 if (!strcmp(arg,
"-compress")) {
194 }
else if (!strcmp(arg,
"-idbased")) {
195 printOut(
"The flag -idbased is deprecated and not required anymore."
196 "It will be removed in a future version"_L1);
198 }
else if (!strcmp(arg,
"-nocompress")) {
201 }
else if (!strcmp(arg,
"-removeidentical")) {
202 removeIdentical =
true;
204 }
else if (!strcmp(arg,
"-nounfinished")) {
207 }
else if (!strcmp(arg,
"-fail-on-unfinished")) {
208 failOnUnfinished =
true;
210 }
else if (!strcmp(arg,
"-markuntranslated")) {
215 cd.m_unTrPrefix = QString::fromLocal8Bit(argv[++i]);
216 }
else if (!strcmp(arg,
"-project")) {
218 printErr(
"The option -project requires a parameter.\n"_L1);
221 if (!projectDescriptionFile.isEmpty()) {
222 printErr(
"The option -project must appear only once.\n"_L1);
225 projectDescriptionFile = QString::fromLocal8Bit(argv[++i]);
226 }
else if (!strcmp(arg,
"-silent")) {
229 }
else if (!strcmp(arg,
"-verbose")) {
232 }
else if (!strcmp(arg,
"-version")) {
233 printOut(
"lrelease version %1\n"_L1.arg(QLatin1StringView(QT_VERSION_STR)));
235 }
else if (!strcmp(arg,
"-qm")) {
240 outputFile = QString::fromLocal8Bit(argv[++i]);
241 }
else if (!strcmp(arg,
"-help")) {
244 }
else if (arg[0] ==
'-') {
248 inputFiles << QString::fromLocal8Bit(arg);
252 if (inputFiles.isEmpty() && projectDescriptionFile.isEmpty()) {
258 if (!extractProFiles(&inputFiles).isEmpty()) {
259 runInternalQtTool(
"lrelease-pro"_L1, app.arguments().mid(1));
263 if (!projectDescriptionFile.isEmpty()) {
264 if (!inputFiles.isEmpty()) {
265 printErr(QLatin1String(
266 "lrelease error: Do not specify TS files if -project is given.\n"));
269 Projects projectDescription = readProjectDescription(projectDescriptionFile, &errorString);
270 if (!errorString.isEmpty()) {
271 printErr(
"lrelease error: %1\n"_L1.arg(errorString));
274 inputFiles = translationsFromProjects(projectDescription);
277 for (
const QString &inputFile : std::as_const(inputFiles)) {
278 if (outputFile.isEmpty()) {
279 if (!releaseTsFile(inputFile, cd, removeIdentical, failOnUnfinished))
282 if (!loadTsFile(tor, inputFile))
287 if (!outputFile.isEmpty())
288 return releaseTranslator(tor, outputFile, cd, removeIdentical, failOnUnfinished) ? 0 : 1;
TranslatorSaveMode m_saveMode
bool unfinishedTranslationsExist() const
void stripIdenticalSourceTranslations()
Duplicates resolveDuplicates()
void normalizeTranslations(ConversionData &cd)
std::vector< Project > Projects
static void printOut(const QString &out)
static void printErr(const QString &out)
int main(int argc, char *argv[])
[ctor_close]