21int main(
int argc,
char *argv[])
23 QCoreApplication app(argc, argv);
24 QCoreApplication::setApplicationName(
"ltext2id"_L1);
25 QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR));
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();
41 QCommandLineOption noAutoIdOption(
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);
47 QCommandLineOption noLabelsOption(
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);
54 QCommandLineOption onlyMetaIdOption(
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);
60 QCommandLineOption quietOption(
"quiet"_L1,
"Do not print progress output"_L1);
61 parser.addOption(quietOption);
63 QCommandLineOption sortMessagesOption(
64 "sort-messages"_L1,
"Sort messages in a context alphabetically in TS files."_L1);
65 parser.addOption(sortMessagesOption);
67 QCommandLineOption sourceUtf16Option(
69 "If the encoding of the source files is UTF16 (default is UTF-8)"_L1);
70 parser.addOption(sourceUtf16Option);
72 parser.addPositionalArgument(
"project-root"_L1,
73 "Path to the project root directory or file"_L1);
77 const QStringList positionalArgs = parser.positionalArguments();
78 if (positionalArgs.isEmpty()) {
79 std::cerr <<
"ltext2id error: a project root must be specified\n";
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";
98 QStringList translations;
100 auto routeFile = [&sources, &cSources, &translations](QString file) {
101 file = QFileInfo(file).absoluteFilePath();
102 if (QString ext = QFileInfo(file).suffix(); FileTransformer::cppExtensions.contains(ext)) {
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);
111 if (rootInfo.isDir()) {
112 QDirIterator it(projectRoot, QDir::Files | QDir::NoSymLinks, QDirIterator::Subdirectories);
114 routeFile(it.next());
116 routeFile(projectRoot);
121 cd.m_projectRoots = {
std::move(projectRoot) };
122 cd.m_allCSources = Utils::getIncludeOptions(rootInfo, cSources);
124 processSources(tor, sources, cd);
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);
140 fail = !transformer.updateTsFiles(translations);
145 fail = !transformer.transformTsFiles(translations, sortMessages);
146 verifier.verifySources(sources, cd);
147 fail |= !records.errors().empty();
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);
155 std::cout <<
"ltext2id: finished migration from text-based to id-based translation.\n";