tools/linguist/lupdate/main.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Linguist of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "lupdate.h"
       
    43 
       
    44 #include <translator.h>
       
    45 #include <profileevaluator.h>
       
    46 #include <proreader.h>
       
    47 
       
    48 #include <QtCore/QCoreApplication>
       
    49 #include <QtCore/QDebug>
       
    50 #include <QtCore/QDir>
       
    51 #include <QtCore/QFile>
       
    52 #include <QtCore/QFileInfo>
       
    53 #include <QtCore/QString>
       
    54 #include <QtCore/QStringList>
       
    55 #include <QtCore/QTextCodec>
       
    56 
       
    57 static QString m_defaultExtensions;
       
    58 
       
    59 static void printOut(const QString & out)
       
    60 {
       
    61     qWarning("%s", qPrintable(out));
       
    62 }
       
    63 
       
    64 static void recursiveFileInfoList(const QDir &dir,
       
    65     const QSet<QString> &nameFilters, QDir::Filters filter,
       
    66     QFileInfoList *fileinfolist)
       
    67 {
       
    68     foreach (const QFileInfo &fi, dir.entryInfoList(filter))
       
    69         if (fi.isDir())
       
    70             recursiveFileInfoList(QDir(fi.absoluteFilePath()), nameFilters, filter, fileinfolist);
       
    71         else if (nameFilters.contains(fi.suffix()))
       
    72             fileinfolist->append(fi);
       
    73 }
       
    74 
       
    75 static void printUsage()
       
    76 {
       
    77     printOut(QObject::tr(
       
    78         "Usage:\n"
       
    79         "    lupdate [options] [project-file]...\n"
       
    80         "    lupdate [options] [source-file|path]... -ts ts-files\n\n"
       
    81         "lupdate is part of Qt's Linguist tool chain. It extracts translatable\n"
       
    82         "messages from Qt UI files, C++, Java and JavaScript/QtScript source code.\n"
       
    83         "Extracted messages are stored in textual translation source files (typically\n"
       
    84         "Qt TS XML). New and modified messages can be merged into existing TS files.\n\n"
       
    85         "Options:\n"
       
    86         "    -help  Display this information and exit.\n"
       
    87         "    -no-obsolete\n"
       
    88         "           Drop all obsolete strings.\n"
       
    89         "    -extensions <ext>[,<ext>]...\n"
       
    90         "           Process files with the given extensions only.\n"
       
    91         "           The extension list must be separated with commas, not with whitespace.\n"
       
    92         "           Default: '%1'.\n"
       
    93         "    -pluralonly\n"
       
    94         "           Only include plural form messages.\n"
       
    95         "    -silent\n"
       
    96         "           Do not explain what is being done.\n"
       
    97         "    -no-sort\n"
       
    98         "           Do not sort contexts in TS files.\n"
       
    99         "    -no-recursive\n"
       
   100         "           Do not recursively scan the following directories.\n"
       
   101         "    -recursive\n"
       
   102         "           Recursively scan the following directories (default).\n"
       
   103         "    -I <includepath> or -I<includepath>\n"
       
   104         "           Additional location to look for include files.\n"
       
   105         "           May be specified multiple times.\n"
       
   106         "    -locations {absolute|relative|none}\n"
       
   107         "           Specify/override how source code references are saved in TS files.\n"
       
   108         "           Default is absolute.\n"
       
   109         "    -no-ui-lines\n"
       
   110         "           Do not record line numbers in references to UI files.\n"
       
   111         "    -disable-heuristic {sametext|similartext|number}\n"
       
   112         "           Disable the named merge heuristic. Can be specified multiple times.\n"
       
   113         "    -pro <filename>\n"
       
   114         "           Name of a .pro file. Useful for files with .pro\n"
       
   115         "           file syntax but different file suffix\n"
       
   116         "    -source-language <language>[_<region>]\n"
       
   117         "           Specify the language of the source strings for new files.\n"
       
   118         "           Defaults to POSIX if not specified.\n"
       
   119         "    -target-language <language>[_<region>]\n"
       
   120         "           Specify the language of the translations for new files.\n"
       
   121         "           Guessed from the file name if not specified.\n"
       
   122         "    -version\n"
       
   123         "           Display the version of lupdate and exit.\n"
       
   124     ).arg(m_defaultExtensions));
       
   125 }
       
   126 
       
   127 static void updateTsFiles(const Translator &fetchedTor, const QStringList &tsFileNames,
       
   128     const QByteArray &codecForTr, const QString &sourceLanguage, const QString &targetLanguage,
       
   129     UpdateOptions options, bool *fail)
       
   130 {
       
   131     QDir dir;
       
   132     QString err;
       
   133     foreach (const QString &fileName, tsFileNames) {
       
   134         QString fn = dir.relativeFilePath(fileName);
       
   135         ConversionData cd;
       
   136         Translator tor;
       
   137         cd.m_sortContexts = !(options & NoSort);
       
   138         if (QFile(fileName).exists()) {
       
   139             if (!tor.load(fileName, cd, QLatin1String("auto"))) {
       
   140                 printOut(cd.error());
       
   141                 *fail = true;
       
   142                 continue;
       
   143             }
       
   144             tor.resolveDuplicates();
       
   145             cd.clearErrors();
       
   146             if (!codecForTr.isEmpty() && codecForTr != tor.codecName())
       
   147                 qWarning("lupdate warning: Codec for tr() '%s' disagrees with "
       
   148                          "existing file's codec '%s'. Expect trouble.",
       
   149                          codecForTr.constData(), tor.codecName().constData());
       
   150             if (!targetLanguage.isEmpty() && targetLanguage != tor.languageCode())
       
   151                 qWarning("lupdate warning: Specified target language '%s' disagrees with "
       
   152                          "existing file's language '%s'. Ignoring.",
       
   153                          qPrintable(targetLanguage), qPrintable(tor.languageCode()));
       
   154             if (!sourceLanguage.isEmpty() && sourceLanguage != tor.sourceLanguageCode())
       
   155                 qWarning("lupdate warning: Specified source language '%s' disagrees with "
       
   156                          "existing file's language '%s'. Ignoring.",
       
   157                          qPrintable(sourceLanguage), qPrintable(tor.sourceLanguageCode()));
       
   158         } else {
       
   159             if (!codecForTr.isEmpty())
       
   160                 tor.setCodecName(codecForTr);
       
   161             if (!targetLanguage.isEmpty())
       
   162                 tor.setLanguageCode(targetLanguage);
       
   163             else
       
   164                 tor.setLanguageCode(Translator::guessLanguageCodeFromFileName(fileName));
       
   165             if (!sourceLanguage.isEmpty())
       
   166                 tor.setSourceLanguageCode(sourceLanguage);
       
   167         }
       
   168         tor.makeFileNamesAbsolute(QFileInfo(fileName).absoluteDir());
       
   169         if (options & NoLocations)
       
   170             tor.setLocationsType(Translator::NoLocations);
       
   171         else if (options & RelativeLocations)
       
   172             tor.setLocationsType(Translator::RelativeLocations);
       
   173         else if (options & AbsoluteLocations)
       
   174             tor.setLocationsType(Translator::AbsoluteLocations);
       
   175         if (options & Verbose)
       
   176             printOut(QObject::tr("Updating '%1'...\n").arg(fn));
       
   177 
       
   178         UpdateOptions theseOptions = options;
       
   179         if (tor.locationsType() == Translator::NoLocations) // Could be set from file
       
   180             theseOptions |= NoLocations;
       
   181         Translator out = merge(tor, fetchedTor, theseOptions, err);
       
   182         if (!codecForTr.isEmpty())
       
   183             out.setCodecName(codecForTr);
       
   184 
       
   185         if ((options & Verbose) && !err.isEmpty()) {
       
   186             printOut(err);
       
   187             err.clear();
       
   188         }
       
   189         if (options & PluralOnly) {
       
   190             if (options & Verbose)
       
   191                 printOut(QObject::tr("Stripping non plural forms in '%1'...\n").arg(fn));
       
   192             out.stripNonPluralForms();
       
   193         }
       
   194         if (options & NoObsolete)
       
   195             out.stripObsoleteMessages();
       
   196         out.stripEmptyContexts();
       
   197 
       
   198         out.normalizeTranslations(cd);
       
   199         if (!cd.errors().isEmpty()) {
       
   200             printOut(cd.error());
       
   201             cd.clearErrors();
       
   202         }
       
   203         if (!out.save(fileName, cd, QLatin1String("auto"))) {
       
   204             printOut(cd.error());
       
   205             *fail = true;
       
   206         }
       
   207     }
       
   208 }
       
   209 
       
   210 int main(int argc, char **argv)
       
   211 {
       
   212     QCoreApplication app(argc, argv);
       
   213     m_defaultExtensions = QLatin1String("ui,c,c++,cc,cpp,cxx,ch,h,h++,hh,hpp,hxx");
       
   214 
       
   215     QStringList args = app.arguments();
       
   216     QString defaultContext; // This was QLatin1String("@default") before.
       
   217     Translator fetchedTor;
       
   218     QByteArray codecForTr;
       
   219     QByteArray codecForSource;
       
   220     QStringList tsFileNames;
       
   221     QStringList proFiles;
       
   222     QMultiHash<QString, QString> allCSources;
       
   223     QSet<QString> projectRoots;
       
   224     QStringList sourceFiles;
       
   225     QStringList includePath;
       
   226     QString targetLanguage;
       
   227     QString sourceLanguage;
       
   228 
       
   229     UpdateOptions options =
       
   230         Verbose | // verbose is on by default starting with Qt 4.2
       
   231         HeuristicSameText | HeuristicSimilarText | HeuristicNumber;
       
   232     int numFiles = 0;
       
   233     bool standardSyntax = true;
       
   234     bool metTsFlag = false;
       
   235     bool recursiveScan = true;
       
   236 
       
   237     QString extensions = m_defaultExtensions;
       
   238     QSet<QString> extensionsNameFilters;
       
   239 
       
   240     for (int  i = 1; i < argc; ++i) {
       
   241         if (args.at(i) == QLatin1String("-ts"))
       
   242             standardSyntax = false;
       
   243     }
       
   244 
       
   245     for (int i = 1; i < argc; ++i) {
       
   246         QString arg = args.at(i);
       
   247         if (arg == QLatin1String("-help")
       
   248                 || arg == QLatin1String("--help")
       
   249                 || arg == QLatin1String("-h")) {
       
   250             printUsage();
       
   251             return 0;
       
   252         } else if (arg == QLatin1String("-pluralonly")) {
       
   253             options |= PluralOnly;
       
   254             continue;
       
   255         } else if (arg == QLatin1String("-noobsolete")
       
   256                 || arg == QLatin1String("-no-obsolete")) {
       
   257             options |= NoObsolete;
       
   258             continue;
       
   259         } else if (arg == QLatin1String("-silent")) {
       
   260             options &= ~Verbose;
       
   261             continue;
       
   262         } else if (arg == QLatin1String("-target-language")) {
       
   263             ++i;
       
   264             if (i == argc) {
       
   265                 qWarning("The option -target-language requires a parameter.");
       
   266                 return 1;
       
   267             }
       
   268             targetLanguage = args[i];
       
   269             continue;
       
   270         } else if (arg == QLatin1String("-source-language")) {
       
   271             ++i;
       
   272             if (i == argc) {
       
   273                 qWarning("The option -source-language requires a parameter.");
       
   274                 return 1;
       
   275             }
       
   276             sourceLanguage = args[i];
       
   277             continue;
       
   278         } else if (arg == QLatin1String("-disable-heuristic")) {
       
   279             ++i;
       
   280             if (i == argc) {
       
   281                 qWarning("The option -disable-heuristic requires a parameter.");
       
   282                 return 1;
       
   283             }
       
   284             arg = args[i];
       
   285             if (arg == QLatin1String("sametext")) {
       
   286                 options &= ~HeuristicSameText;
       
   287             } else if (arg == QLatin1String("similartext")) {
       
   288                 options &= ~HeuristicSimilarText;
       
   289             } else if (arg == QLatin1String("number")) {
       
   290                 options &= ~HeuristicNumber;
       
   291             } else {
       
   292                 qWarning("Invalid heuristic name passed to -disable-heuristic.");
       
   293                 return 1;
       
   294             }
       
   295             continue;
       
   296         } else if (arg == QLatin1String("-locations")) {
       
   297             ++i;
       
   298             if (i == argc) {
       
   299                 qWarning("The option -locations requires a parameter.");
       
   300                 return 1;
       
   301             }
       
   302             if (args[i] == QLatin1String("none")) {
       
   303                 options |= NoLocations;
       
   304             } else if (args[i] == QLatin1String("relative")) {
       
   305                 options |= RelativeLocations;
       
   306             } else if (args[i] == QLatin1String("absolute")) {
       
   307                 options |= AbsoluteLocations;
       
   308             } else {
       
   309                 qWarning("Invalid parameter passed to -locations.");
       
   310                 return 1;
       
   311             }
       
   312             continue;
       
   313         } else if (arg == QLatin1String("-no-ui-lines")) {
       
   314             options |= NoUiLines;
       
   315             continue;
       
   316         } else if (arg == QLatin1String("-verbose")) {
       
   317             options |= Verbose;
       
   318             continue;
       
   319         } else if (arg == QLatin1String("-no-recursive")) {
       
   320             recursiveScan = false;
       
   321             continue;
       
   322         } else if (arg == QLatin1String("-recursive")) {
       
   323             recursiveScan = true;
       
   324             continue;
       
   325         } else if (arg == QLatin1String("-no-sort")
       
   326                    || arg == QLatin1String("-nosort")) {
       
   327             options |= NoSort;
       
   328             continue;
       
   329         } else if (arg == QLatin1String("-version")) {
       
   330             printOut(QObject::tr("lupdate version %1\n").arg(QLatin1String(QT_VERSION_STR)));
       
   331             return 0;
       
   332         } else if (arg == QLatin1String("-ts")) {
       
   333             metTsFlag = true;
       
   334             continue;
       
   335         } else if (arg == QLatin1String("-extensions")) {
       
   336             ++i;
       
   337             if (i == argc) {
       
   338                 qWarning("The -extensions option should be followed by an extension list.");
       
   339                 return 1;
       
   340             }
       
   341             extensions = args[i];
       
   342             continue;
       
   343         } else if (arg == QLatin1String("-pro")) {
       
   344             ++i;
       
   345             if (i == argc) {
       
   346                 qWarning("The -pro option should be followed by a filename of .pro file.");
       
   347                 return 1;
       
   348             }
       
   349             proFiles += args[i];
       
   350             numFiles++;
       
   351             continue;
       
   352         } else if (arg.startsWith(QLatin1String("-I"))) {
       
   353             if (arg.length() == 2) {
       
   354                 ++i;
       
   355                 if (i == argc) {
       
   356                     qWarning("The -I option should be followed by a path.");
       
   357                     return 1;
       
   358                 }
       
   359                 includePath += args[i];
       
   360             } else {
       
   361                 includePath += args[i].mid(2);
       
   362             }
       
   363             continue;
       
   364         } else if (arg.startsWith(QLatin1String("-")) && arg != QLatin1String("-")) {
       
   365             qWarning("Unrecognized option '%s'", qPrintable(arg));
       
   366             return 1;
       
   367         }
       
   368 
       
   369         numFiles++;
       
   370 
       
   371         QString fullText;
       
   372 
       
   373         codecForTr.clear();
       
   374         codecForSource.clear();
       
   375 
       
   376         if (metTsFlag) {
       
   377             bool found = false;
       
   378             foreach (const Translator::FileFormat &fmt, Translator::registeredFileFormats()) {
       
   379                 if (arg.endsWith(QLatin1Char('.') + fmt.extension, Qt::CaseInsensitive)) {
       
   380                     QFileInfo fi(arg);
       
   381                     if (!fi.exists() || fi.isWritable()) {
       
   382                         tsFileNames.append(QFileInfo(arg).absoluteFilePath());
       
   383                     } else {
       
   384                         qWarning("lupdate warning: For some reason, '%s' is not writable.\n",
       
   385                                 qPrintable(arg));
       
   386                     }
       
   387                     found = true;
       
   388                     break;
       
   389                 }
       
   390             }
       
   391             if (!found) {
       
   392                 qWarning("lupdate error: File '%s' has no recognized extension\n",
       
   393                          qPrintable(arg));
       
   394                 return 1;
       
   395             }
       
   396         } else if (arg.endsWith(QLatin1String(".pro"), Qt::CaseInsensitive)
       
   397                 || arg.endsWith(QLatin1String(".pri"), Qt::CaseInsensitive)) {
       
   398             proFiles << arg;
       
   399         } else {
       
   400             QFileInfo fi(arg);
       
   401             if (!fi.exists()) {
       
   402                 qWarning("lupdate error: File '%s' does not exists\n", qPrintable(arg));
       
   403                 return 1;
       
   404             } else if (fi.isDir()) {
       
   405                 if (options & Verbose)
       
   406                     printOut(QObject::tr("Scanning directory '%1'...").arg(arg));
       
   407                 QDir dir = QDir(fi.filePath());
       
   408                 projectRoots.insert(dir.absolutePath() + QLatin1Char('/'));
       
   409                 if (extensionsNameFilters.isEmpty()) {
       
   410                     foreach (QString ext, extensions.split(QLatin1Char(','))) {
       
   411                         ext = ext.trimmed();
       
   412                         if (ext.startsWith(QLatin1Char('.')))
       
   413                             ext.remove(0, 1);
       
   414                         extensionsNameFilters.insert(ext);
       
   415                     }
       
   416                 }
       
   417                 QDir::Filters filters = QDir::Files | QDir::NoSymLinks;
       
   418                 if (recursiveScan)
       
   419                     filters |= QDir::AllDirs | QDir::NoDotAndDotDot;
       
   420                 QFileInfoList fileinfolist;
       
   421                 recursiveFileInfoList(dir, extensionsNameFilters, filters, &fileinfolist);
       
   422                 int scanRootLen = dir.absolutePath().length();
       
   423                 foreach (const QFileInfo &fi, fileinfolist) {
       
   424                     QString fn = QDir::cleanPath(fi.absoluteFilePath());
       
   425                     sourceFiles << fn;
       
   426 
       
   427                     if (!fn.endsWith(QLatin1String(".java"))
       
   428                         && !fn.endsWith(QLatin1String(".ui"))
       
   429                         && !fn.endsWith(QLatin1String(".js"))
       
   430                         && !fn.endsWith(QLatin1String(".qs"))) {
       
   431                         int offset = 0;
       
   432                         int depth = 0;
       
   433                         do {
       
   434                             offset = fn.lastIndexOf(QLatin1Char('/'), offset - 1);
       
   435                             QString ffn = fn.mid(offset + 1);
       
   436                             allCSources.insert(ffn, fn);
       
   437                         } while (++depth < 3 && offset > scanRootLen);
       
   438                     }
       
   439                 }
       
   440             } else {
       
   441                 sourceFiles << QDir::cleanPath(fi.absoluteFilePath());;
       
   442             }
       
   443         }
       
   444     } // for args
       
   445 
       
   446     foreach (const QString &proFile, proFiles)
       
   447         projectRoots.insert(QDir::cleanPath(QFileInfo(proFile).absolutePath()) + QLatin1Char('/'));
       
   448 
       
   449     bool firstPass = true;
       
   450     bool fail = false;
       
   451     while (firstPass || !proFiles.isEmpty()) {
       
   452         ConversionData cd;
       
   453         cd.m_defaultContext = defaultContext;
       
   454         cd.m_noUiLines = options & NoUiLines;
       
   455         cd.m_projectRoots = projectRoots;
       
   456         cd.m_includePath = includePath;
       
   457         cd.m_allCSources = allCSources;
       
   458 
       
   459         QStringList tsFiles = tsFileNames;
       
   460         if (proFiles.count() > 0) {
       
   461             QFileInfo pfi(proFiles.takeFirst());
       
   462             QHash<QByteArray, QStringList> variables;
       
   463 
       
   464             ProFileEvaluator visitor;
       
   465             visitor.setVerbose(options & Verbose);
       
   466 
       
   467             ProFile pro(pfi.absoluteFilePath());
       
   468             if (!visitor.queryProFile(&pro))
       
   469                 return 2;
       
   470             if (!visitor.accept(&pro))
       
   471                 return 2;
       
   472 
       
   473             if (visitor.templateType() == ProFileEvaluator::TT_Subdirs) {
       
   474                 QDir proDir(pfi.absoluteDir());
       
   475                 foreach (const QString &subdir, visitor.values(QLatin1String("SUBDIRS"))) {
       
   476                     QString subPro = QDir::cleanPath(proDir.absoluteFilePath(subdir));
       
   477                     QFileInfo subInfo(subPro);
       
   478                     if (subInfo.isDir())
       
   479                         proFiles << (subPro + QLatin1Char('/')
       
   480                                      + subInfo.fileName() + QLatin1String(".pro"));
       
   481                     else
       
   482                         proFiles << subPro;
       
   483                 }
       
   484                 continue;
       
   485             }
       
   486 
       
   487             cd.m_includePath += visitor.values(QLatin1String("INCLUDEPATH"));
       
   488 
       
   489             evaluateProFile(visitor, &variables, pfi.absolutePath());
       
   490 
       
   491             sourceFiles = variables.value("SOURCES");
       
   492 
       
   493             QStringList tmp = variables.value("CODECFORTR");
       
   494             if (!tmp.isEmpty() && !tmp.first().isEmpty()) {
       
   495                 codecForTr = tmp.first().toLatin1();
       
   496                 fetchedTor.setCodecName(codecForTr);
       
   497             }
       
   498             tmp = variables.value("CODECFORSRC");
       
   499             if (!tmp.isEmpty() && !tmp.first().isEmpty()) {
       
   500                 codecForSource = tmp.first().toLatin1();
       
   501                 if (!QTextCodec::codecForName(codecForSource))
       
   502                     qWarning("lupdate warning: Codec for source '%s' is invalid. Falling back to codec for tr().",
       
   503                              codecForSource.constData());
       
   504                 else
       
   505                     cd.m_codecForSource = codecForSource;
       
   506             }
       
   507 
       
   508             tsFiles += variables.value("TRANSLATIONS");
       
   509         }
       
   510 
       
   511         QStringList sourceFilesCpp;
       
   512         for (QStringList::iterator it = sourceFiles.begin(); it != sourceFiles.end(); ++it) {
       
   513             if (it->endsWith(QLatin1String(".java"), Qt::CaseInsensitive))
       
   514                 loadJava(fetchedTor, *it, cd);
       
   515             else if (it->endsWith(QLatin1String(".ui"), Qt::CaseInsensitive)
       
   516                      || it->endsWith(QLatin1String(".jui"), Qt::CaseInsensitive))
       
   517                 loadUI(fetchedTor, *it, cd);
       
   518             else if (it->endsWith(QLatin1String(".js"), Qt::CaseInsensitive)
       
   519                      || it->endsWith(QLatin1String(".qs"), Qt::CaseInsensitive))
       
   520                 loadQScript(fetchedTor, *it, cd);
       
   521             else
       
   522                 sourceFilesCpp << *it;
       
   523         }
       
   524         loadCPP(fetchedTor, sourceFilesCpp, cd);
       
   525         if (!cd.error().isEmpty())
       
   526             printOut(cd.error());
       
   527 
       
   528         tsFiles.sort();
       
   529         tsFiles.removeDuplicates();
       
   530 
       
   531         if (!tsFiles.isEmpty())
       
   532             updateTsFiles(fetchedTor, tsFiles, codecForTr, sourceLanguage, targetLanguage, options, &fail);
       
   533 
       
   534         firstPass = false;
       
   535     }
       
   536 
       
   537     if (numFiles == 0) {
       
   538         printUsage();
       
   539         return 1;
       
   540     }
       
   541 
       
   542     return fail ? 1 : 0;
       
   543 }