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) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
5#include "fileverifier.h"
6#include "utils.h"
8#include <translator.h>
9#include <trlib/trparser.h>
10
11#include <QtCore/QCoreApplication>
12#include <QtCore/QCommandLineParser>
13#include <QtCore/QCommandLineOption>
14#include <QDirIterator>
15#include <iostream>
16
17QT_USE_NAMESPACE
18
19using namespace Qt::StringLiterals;
20
21int main(int argc, char *argv[])
22{
23 QCoreApplication app(argc, argv);
24 QCoreApplication::setApplicationName("ltext2id"_L1);
25 QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR));
26
27 QCommandLineParser parser;
28 parser.setApplicationDescription(
29 "ltext2id is part of the Qt Linguist toolchain. It transforms\n"
30 "a project that uses text-based translations into using id-based\n"
31 "translations. It extracts the source and translation files (TS\n"
32 "files) from the given project root by traversing the\n"
33 "directories recursively. The code will be updated to use\n"
34 "id-based translations. Also, the TS files are updated accordingly.\n"
35 "Please make a backup of your code base before running ltext2id.\n"
36 "For best results, include the sources along with TS files to get\n"
37 "consistent transformation across sources and TS files."_L1);
38 parser.addHelpOption();
39 parser.addVersionOption();
40
41 QCommandLineOption noAutoIdOption(
42 "no-auto-id"_L1,
43 "Do not auto generate IDs when missing meta string IDs. Ignores the\n"
44 "translation functions without meta IDs."_L1);
45 parser.addOption(noAutoIdOption);
46
47 QCommandLineOption noLabelsOption(
48 "no-labels"_L1,
49 "Do not generate labels for id-based translations. The default\n"
50 "behavior is to use message contexts as labels, to preserve\n"
51 "the same visualization form in Linguist."_L1);
52 parser.addOption(noLabelsOption);
53
54 QCommandLineOption onlyMetaIdOption(
55 "only-meta-id"_L1,
56 "Only generate ID suggestions in form of meta strings. Does not\n"
57 "perform the actual transformation into ID based."_L1);
58 parser.addOption(onlyMetaIdOption);
59
60 QCommandLineOption quietOption("quiet"_L1, "Do not print progress output"_L1);
61 parser.addOption(quietOption);
62
63 QCommandLineOption sortMessagesOption(
64 "sort-messages"_L1, "Sort messages in a context alphabetically in TS files."_L1);
65 parser.addOption(sortMessagesOption);
66
67 QCommandLineOption sourceUtf16Option(
68 "source-utf16"_L1,
69 "If the encoding of the source files is UTF16 (default is UTF-8)"_L1);
70 parser.addOption(sourceUtf16Option);
71
72 parser.addPositionalArgument("project-root"_L1,
73 "Path to the project root directory or file"_L1);
74
75 parser.process(app);
76
77 const QStringList positionalArgs = parser.positionalArguments();
78 if (positionalArgs.isEmpty()) {
79 std::cerr << "ltext2id error: a project root must be specified\n";
80 parser.showHelp(1);
81 }
82
83 const QString projectRoot = positionalArgs.first();
84 const bool labels = !parser.isSet(noLabelsOption);
85 const bool sortMessages = parser.isSet(sortMessagesOption);
86 const bool utf16 = parser.isSet(sourceUtf16Option);
87 const bool quiet = parser.isSet(quietOption);
88 const bool autoId = !parser.isSet(noAutoIdOption);
89 const bool onlyId = parser.isSet(onlyMetaIdOption);
90 QFileInfo rootInfo(projectRoot);
91 if (!rootInfo.exists()) {
92 std::cerr << "ltext2id error: invalid project root\n";
93 parser.showHelp(1);
94 }
95
96 QStringList sources;
97 QStringList cSources;
98 QStringList translations;
99
100 auto routeFile = [&sources, &cSources, &translations](QString file) {
101 file = QFileInfo(file).absoluteFilePath();
102 if (QString ext = QFileInfo(file).suffix(); FileTransformer::cppExtensions.contains(ext)) {
103 cSources << file;
104 sources << std::move(file);
105 } else if (FileTransformer::otherExtensions.contains(ext))
106 sources << std::move(file);
107 else if (ext == "ts" || ext == "TS")
108 translations << std::move(file);
109 };
110
111 if (rootInfo.isDir()) {
112 QDirIterator it(projectRoot, QDir::Files | QDir::NoSymLinks, QDirIterator::Subdirectories);
113 while (it.hasNext())
114 routeFile(it.next());
115 } else {
116 routeFile(projectRoot);
117 }
118
120 Translator tor;
121 cd.m_projectRoots = { std::move(projectRoot) };
122 cd.m_allCSources = Utils::getIncludeOptions(rootInfo, cSources);
123 cd.m_sourceIsUtf16 = utf16;
124 processSources(tor, sources, cd);
125
126 RecordDirectory records;
127 for (const TranslatorMessage &msg : tor.messages())
128 if (msg.context().isEmpty())
129 records.recordExistingId(msg.id());
130 for (const TranslatorMessage &msg : tor.messages())
131 if (!msg.context().isEmpty() && (autoId || !msg.extra(meta_id_key).isEmpty()))
132 records.recordMessage(msg);
133
134 bool fail = false;
135 FileTransformer transformer(records, labels, quiet);
136 FileVerifier verifier(records, quiet);
137
138 if (onlyId) {
139 transformer.generateMetaIds();
140 fail = !transformer.updateTsFiles(translations);
141 } else {
142 transformer.transformUi();
143 transformer.transformSources();
144
145 fail = !transformer.transformTsFiles(translations, sortMessages);
146 verifier.verifySources(sources, cd);
147 fail |= !records.errors().empty();
148 if (fail)
149 Utils::printErr("ltext2id failed to migrate some translations. Please look for "
150 "the comments from ltext2id annotated by '//ltext2id error:' in "
151 "your source code to find the failed transformations and fix them "
152 "manually as instructed."_L1);
153 }
154
155 std::cout << "ltext2id: finished migration from text-based to id-based translation.\n";
156 return fail ? 1 : 0;
157}
bool m_sourceIsUtf16
Definition translator.h:44
FileTransformer(RecordDirectory &records, bool labels, bool quiet)
FileVerifier(const RecordDirectory &records, bool quiet)
void printErr(const QString &out)
Definition utils.cpp:17
int main(int argc, char *argv[])
[ctor_close]