Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#include "translator.h"
5
6#include <profileutils.h>
7#include <projectdescriptionreader.h>
8#include <runqttool.h>
9
10#ifndef QT_BOOTSTRAPPED
11#include <QtCore/QCoreApplication>
12#include <QtCore/QTranslator>
13#endif
14#include <QtCore/QDebug>
15#include <QtCore/QDir>
16#include <QtCore/QFile>
17#include <QtCore/QFileInfo>
18#include <QtCore/QString>
19#include <QtCore/QStringList>
20#include <QtCore/QTextStream>
21#include <QtCore/QLibraryInfo>
22
23QT_USE_NAMESPACE
24
25using namespace Qt::StringLiterals;
26
27static void printOut(const QString & out)
28{
30 stream << out;
31}
32
33static void printErr(const QString & out)
34{
36 stream << out;
37}
38
39static void printUsage()
40{
41 printOut(uR"(Usage:
42 lrelease [options] -project project-file
43 lrelease [options] ts-files [-qm qm-file]
44
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 Use IDs instead of source strings for message keying
57 -compress
58 Compress the QM files
59 -nounfinished
60 Do not include unfinished translations
61 -removeidentical
62 If the translated text is the same as
63 the source text, do not include the message
64 -markuntranslated <prefix>
65 If a message has no real translation, use the source text
66 prefixed with the given string instead
67 -project <filename>
68 Name of a file containing the project's description in JSON format.
69 Such a file may be generated from a .pro file using the lprodump tool.
70 -silent
71 Do not explain what is being done
72 -version
73 Display the version of lrelease and exit
74)"_s);
75}
76
77static bool loadTsFile(Translator &tor, const QString &tsFileName, bool /* verbose */)
78{
80 bool ok = tor.load(tsFileName, cd, QLatin1String("auto"));
81 if (!ok) {
82 printErr(QLatin1String("lrelease error: %1").arg(cd.error()));
83 } else {
84 if (!cd.errors().isEmpty())
85 printOut(cd.error());
86 }
88 return ok;
89}
90
91static bool releaseTranslator(Translator &tor, const QString &qmFileName,
92 ConversionData &cd, bool removeIdentical)
93{
94 tor.reportDuplicates(tor.resolveDuplicates(), qmFileName, cd.isVerbose());
95
96 if (cd.isVerbose())
97 printOut(QLatin1String("Updating '%1'...\n").arg(qmFileName));
98 if (removeIdentical) {
99 if (cd.isVerbose())
100 printOut(QLatin1String("Removing translations equal to source text in '%1'...\n")
101 .arg(qmFileName));
103 }
104
105 QFile file(qmFileName);
106 if (!file.open(QIODevice::WriteOnly)) {
107 printErr(QLatin1String("lrelease error: cannot create '%1': %2\n")
108 .arg(qmFileName, file.errorString()));
109 return false;
110 }
111
113 bool ok = saveQM(tor, file, cd);
114 file.close();
115
116 if (!ok) {
117 printErr(QLatin1String("lrelease error: cannot save '%1': %2").arg(qmFileName, cd.error()));
118 } else if (!cd.errors().isEmpty()) {
119 printOut(cd.error());
120 }
122 return ok;
123}
124
125static bool releaseTsFile(const QString& tsFileName,
126 ConversionData &cd, bool removeIdentical)
127{
128 Translator tor;
129 if (!loadTsFile(tor, tsFileName, cd.isVerbose()))
130 return false;
131
132 QString qmFileName = tsFileName;
133 for (const Translator::FileFormat &fmt : std::as_const(Translator::registeredFileFormats())) {
134 if (qmFileName.endsWith(QLatin1Char('.') + fmt.extension)) {
135 qmFileName.chop(fmt.extension.size() + 1);
136 break;
137 }
138 }
139 qmFileName += QLatin1String(".qm");
140
141 return releaseTranslator(tor, qmFileName, cd, removeIdentical);
142}
143
144static QStringList translationsFromProjects(const Projects &projects, bool topLevel);
145
146static QStringList translationsFromProject(const Project &project, bool topLevel)
147{
148 QStringList result;
149 if (project.translations)
150 result = *project.translations;
151 result << translationsFromProjects(project.subProjects, false);
152 if (topLevel && result.isEmpty()) {
153 printErr(
154 QLatin1String("lrelease warning: Met no 'TRANSLATIONS' entry in project file '%1'\n")
155 .arg(project.filePath));
156 }
157 return result;
158}
159
160static QStringList translationsFromProjects(const Projects &projects, bool topLevel = true)
161{
162 QStringList result;
163 for (const Project &p : projects)
164 result << translationsFromProject(p, topLevel);
165 return result;
166}
167
168int main(int argc, char **argv)
169{
170 QCoreApplication app(argc, argv);
171
173 cd.m_verbose = true; // the default is true starting with Qt 4.2
174 bool removeIdentical = false;
175 Translator tor;
176 QStringList inputFiles;
177 QString outputFile;
178 QString projectDescriptionFile;
179
180 for (int i = 1; i < argc; ++i) {
181 if (!strcmp(argv[i], "-compress")) {
183 continue;
184 } else if (!strcmp(argv[i], "-idbased")) {
185 cd.m_idBased = true;
186 continue;
187 } else if (!strcmp(argv[i], "-nocompress")) {
189 continue;
190 } else if (!strcmp(argv[i], "-removeidentical")) {
191 removeIdentical = true;
192 continue;
193 } else if (!strcmp(argv[i], "-nounfinished")) {
194 cd.m_ignoreUnfinished = true;
195 continue;
196 } else if (!strcmp(argv[i], "-markuntranslated")) {
197 if (i == argc - 1) {
199 return 1;
200 }
201 cd.m_unTrPrefix = QString::fromLocal8Bit(argv[++i]);
202 } else if (!strcmp(argv[i], "-project")) {
203 if (i == argc - 1) {
204 printErr(QLatin1String("The option -project requires a parameter.\n"));
205 return 1;
206 }
207 if (!projectDescriptionFile.isEmpty()) {
208 printErr(QLatin1String("The option -project must appear only once.\n"));
209 return 1;
210 }
211 projectDescriptionFile = QString::fromLocal8Bit(argv[++i]);
212 } else if (!strcmp(argv[i], "-silent")) {
213 cd.m_verbose = false;
214 continue;
215 } else if (!strcmp(argv[i], "-verbose")) {
216 cd.m_verbose = true;
217 continue;
218 } else if (!strcmp(argv[i], "-version")) {
219 printOut(QLatin1String("lrelease version %1\n").arg(QLatin1String(QT_VERSION_STR)));
220 return 0;
221 } else if (!strcmp(argv[i], "-qm")) {
222 if (i == argc - 1) {
224 return 1;
225 }
226 outputFile = QString::fromLocal8Bit(argv[++i]);
227 } else if (!strcmp(argv[i], "-help")) {
229 return 0;
230 } else if (argv[i][0] == '-') {
232 return 1;
233 } else {
234 inputFiles << QString::fromLocal8Bit(argv[i]);
235 }
236 }
237
238 if (inputFiles.isEmpty() && projectDescriptionFile.isEmpty()) {
240 return 1;
241 }
242
243 QString errorString;
244 if (!extractProFiles(&inputFiles).isEmpty()) {
245 runInternalQtTool(QLatin1String("lrelease-pro"), app.arguments().mid(1));
246 return 0;
247 }
248
249 if (!projectDescriptionFile.isEmpty()) {
250 if (!inputFiles.isEmpty()) {
251 printErr(QLatin1String(
252 "lrelease error: Do not specify TS files if -project is given.\n"));
253 return 1;
254 }
255 Projects projectDescription = readProjectDescription(projectDescriptionFile, &errorString);
256 if (!errorString.isEmpty()) {
257 printErr(QLatin1String("lrelease error: %1\n").arg(errorString));
258 return 1;
259 }
260 inputFiles = translationsFromProjects(projectDescription);
261 }
262
263 for (const QString &inputFile : std::as_const(inputFiles)) {
264 if (outputFile.isEmpty()) {
265 if (!releaseTsFile(inputFile, cd, removeIdentical))
266 return 1;
267 } else {
268 if (!loadTsFile(tor, inputFile, cd.isVerbose()))
269 return 1;
270 }
271 }
272
273 if (!outputFile.isEmpty())
274 return releaseTranslator(tor, outputFile, cd, removeIdentical) ? 0 : 1;
275
276 return 0;
277}
int main(int argc, char *argv[])
[2]
Definition buffer.cpp:77
void clearErrors()
Definition translator.h:48
bool isVerbose() const
Definition translator.h:41
TranslatorSaveMode m_saveMode
Definition translator.h:70
bool m_ignoreUnfinished
Definition translator.h:66
void stripIdenticalSourceTranslations()
Duplicates resolveDuplicates()
void normalizeTranslations(ConversionData &cd)
std::vector< Project > Projects
static void printUsage()
Definition main.cpp:60
static void printOut(const QString &out)
Definition main.cpp:18
static void printErr(const QString &out)
Definition main.cpp:23
static bool releaseTsFile(const QString &tsFileName, ConversionData &cd, bool removeIdentical)
Definition main.cpp:125
static bool loadTsFile(Translator &tor, const QString &tsFileName, bool)
Definition main.cpp:77
static bool releaseTranslator(Translator &tor, const QString &qmFileName, ConversionData &cd, bool removeIdentical)
Definition main.cpp:91
static QStringList translationsFromProjects(const Projects &projects, bool topLevel)
Definition main.cpp:160
static QStringList translationsFromProject(const Project &project, bool topLevel)
Definition main.cpp:146
QTextStream stream(stdin)
[0]
@ SaveStripped
@ SaveEverything