~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to tools/linguist/lupdate/main.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi
  • Date: 2009-11-02 18:30:08 UTC
  • mfrom: (1.2.2 upstream)
  • mto: (15.2.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 88.
  • Revision ID: james.westby@ubuntu.com-20091102183008-b6a4gcs128mvfb3m
Tags: upstream-4.6.0~beta1
ImportĀ upstreamĀ versionĀ 4.6.0~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/****************************************************************************
2
2
**
3
3
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
 
4
** All rights reserved.
4
5
** Contact: Nokia Corporation (qt-info@nokia.com)
5
6
**
6
7
** This file is part of the Qt Linguist of the Qt Toolkit.
7
8
**
8
9
** $QT_BEGIN_LICENSE:LGPL$
9
 
** Commercial Usage
10
 
** Licensees holding valid Qt Commercial licenses may use this file in
11
 
** accordance with the Qt Commercial License Agreement provided with the
12
 
** Software or, alternatively, in accordance with the terms contained in
13
 
** a written agreement between you and Nokia.
 
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.
14
15
**
15
16
** GNU Lesser General Public License Usage
16
17
** Alternatively, this file may be used under the terms of the GNU Lesser
20
21
** ensure the GNU Lesser General Public License version 2.1 requirements
21
22
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22
23
**
23
 
** In addition, as a special exception, Nokia gives you certain
24
 
** additional rights. These rights are described in the Nokia Qt LGPL
25
 
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26
 
** package.
27
 
**
28
 
** GNU General Public License Usage
29
 
** Alternatively, this file may be used under the terms of the GNU
30
 
** General Public License version 3.0 as published by the Free Software
31
 
** Foundation and appearing in the file LICENSE.GPL included in the
32
 
** packaging of this file.  Please review the following information to
33
 
** ensure the GNU General Public License version 3.0 requirements will be
34
 
** met: http://www.gnu.org/copyleft/gpl.html.
35
 
**
36
 
** If you are unsure which license is appropriate for your use, please
37
 
** contact the sales department at http://www.qtsoftware.com/contact.
 
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
38
** $QT_END_LICENSE$
39
39
**
40
40
****************************************************************************/
41
41
 
42
 
#include "translator.h"
43
 
#include "translatortools.h"
44
 
#include "profileevaluator.h"
 
42
#include "lupdate.h"
 
43
 
 
44
#include <translator.h>
 
45
#include <profileevaluator.h>
 
46
#include <proreader.h>
45
47
 
46
48
#include <QtCore/QCoreApplication>
47
49
#include <QtCore/QDebug>
60
62
}
61
63
 
62
64
static void recursiveFileInfoList(const QDir &dir,
63
 
    const QStringList &nameFilters, QDir::Filters filter, bool recursive,
 
65
    const QSet<QString> &nameFilters, QDir::Filters filter,
64
66
    QFileInfoList *fileinfolist)
65
67
{
66
 
    if (recursive)
67
 
        filter |= QDir::AllDirs;
68
 
    QFileInfoList entries = dir.entryInfoList(nameFilters, filter);
69
 
 
70
 
    QFileInfoList::iterator it;
71
 
    for (it = entries.begin(); it != entries.end(); ++it) {
72
 
        QString fname = it->fileName();
73
 
        if (fname != QLatin1String(".") && fname != QLatin1String("..")) {
74
 
            if (it->isDir())
75
 
                recursiveFileInfoList(QDir(it->absoluteFilePath()), nameFilters, filter, recursive, fileinfolist);
76
 
            else
77
 
                fileinfolist->append(*it);
78
 
        }
79
 
    }
 
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);
80
73
}
81
74
 
82
75
static void printUsage()
83
76
{
84
77
    printOut(QObject::tr(
85
78
        "Usage:\n"
86
 
        "    lupdate [options] [project-file]\n"
 
79
        "    lupdate [options] [project-file]...\n"
87
80
        "    lupdate [options] [source-file|path]... -ts ts-files\n\n"
88
 
        "lupdate is part of Qt's Linguist tool chain. It can be used as a\n"
89
 
        "stand-alone tool to create XML based translations files in the .ts\n"
90
 
        "format from translatable messages in C++ and Java source code.\n\n"
91
 
        "lupdate can also merge such messages into existing .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"
92
85
        "Options:\n"
93
86
        "    -help  Display this information and exit.\n"
94
87
        "    -no-obsolete\n"
102
95
        "    -silent\n"
103
96
        "           Do not explain what is being done.\n"
104
97
        "    -no-sort\n"
105
 
        "           Do not sort contexts in .ts files.\n"
 
98
        "           Do not sort contexts in TS files.\n"
106
99
        "    -no-recursive\n"
107
100
        "           Do not recursively scan the following directories.\n"
108
101
        "    -recursive\n"
109
 
        "           Recursively scan the following directories.\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"
110
106
        "    -locations {absolute|relative|none}\n"
111
 
        "           Specify/override how source code references are saved in ts files.\n"
 
107
        "           Specify/override how source code references are saved in TS files.\n"
112
108
        "           Default is absolute.\n"
113
109
        "    -no-ui-lines\n"
114
 
        "           Do not record line numbers in references to .ui files.\n"
 
110
        "           Do not record line numbers in references to UI files.\n"
115
111
        "    -disable-heuristic {sametext|similartext|number}\n"
116
112
        "           Disable the named merge heuristic. Can be specified multiple times.\n"
117
113
        "    -pro <filename>\n"
118
114
        "           Name of a .pro file. Useful for files with .pro\n"
119
115
        "           file syntax but different file suffix\n"
120
116
        "    -source-language <language>[_<region>]\n"
121
 
        "           Specify/override the language of the source strings. Defaults to\n"
122
 
        "           POSIX if not specified and the file does not name it yet.\n"
 
117
        "           Specify the language of the source strings for new files.\n"
 
118
        "           Defaults to POSIX if not specified.\n"
123
119
        "    -target-language <language>[_<region>]\n"
124
 
        "           Specify/override the language of the translation.\n"
125
 
        "           The target language is guessed from the file name if this option\n"
126
 
        "           is not specified and the file contents name no language yet.\n"
 
120
        "           Specify the language of the translations for new files.\n"
 
121
        "           Guessed from the file name if not specified.\n"
127
122
        "    -version\n"
128
123
        "           Display the version of lupdate and exit.\n"
129
124
    ).arg(m_defaultExtensions));
178
173
        if (options & Verbose)
179
174
            printOut(QObject::tr("Updating '%1'...\n").arg(fn));
180
175
 
 
176
        UpdateOptions theseOptions = options;
181
177
        if (tor.locationsType() == Translator::NoLocations) // Could be set from file
182
 
            options |= NoLocations;
183
 
        Translator out = merge(tor, fetchedTor, options, err);
 
178
            theseOptions |= NoLocations;
 
179
        Translator out = merge(tor, fetchedTor, theseOptions, err);
184
180
        if (!codecForTr.isEmpty())
185
181
            out.setCodecName(codecForTr);
186
182
 
197
193
            out.stripObsoleteMessages();
198
194
        out.stripEmptyContexts();
199
195
 
 
196
        out.normalizeTranslations(cd);
 
197
        if (!cd.errors().isEmpty()) {
 
198
            printOut(cd.error());
 
199
            cd.clearErrors();
 
200
        }
200
201
        if (!out.save(fileName, cd, QLatin1String("auto"))) {
201
202
            printOut(cd.error());
202
203
            *fail = true;
216
217
    QByteArray codecForSource;
217
218
    QStringList tsFileNames;
218
219
    QStringList proFiles;
 
220
    QMultiHash<QString, QString> allCSources;
 
221
    QSet<QString> projectRoots;
219
222
    QStringList sourceFiles;
 
223
    QStringList includePath;
220
224
    QString targetLanguage;
221
225
    QString sourceLanguage;
222
226
 
229
233
    bool recursiveScan = true;
230
234
 
231
235
    QString extensions = m_defaultExtensions;
232
 
    QStringList extensionsNameFilters;
 
236
    QSet<QString> extensionsNameFilters;
233
237
 
234
238
    for (int  i = 1; i < argc; ++i) {
235
239
        if (args.at(i) == QLatin1String("-ts"))
343
347
            proFiles += args[i];
344
348
            numFiles++;
345
349
            continue;
 
350
        } else if (arg.startsWith(QLatin1String("-I"))) {
 
351
            if (arg.length() == 2) {
 
352
                ++i;
 
353
                if (i == argc) {
 
354
                    qWarning("The -I option should be followed by a path.");
 
355
                    return 1;
 
356
                }
 
357
                includePath += args[i];
 
358
            } else {
 
359
                includePath += args[i].mid(2);
 
360
            }
 
361
            continue;
346
362
        } else if (arg.startsWith(QLatin1String("-")) && arg != QLatin1String("-")) {
347
363
            qWarning("Unrecognized option '%s'", qPrintable(arg));
348
364
            return 1;
387
403
                if (options & Verbose)
388
404
                    printOut(QObject::tr("Scanning directory '%1'...").arg(arg));
389
405
                QDir dir = QDir(fi.filePath());
 
406
                projectRoots.insert(dir.absolutePath() + QLatin1Char('/'));
390
407
                if (extensionsNameFilters.isEmpty()) {
391
 
                    extensions = extensions.trimmed();
392
 
                    // Remove the potential dot in front of each extension
393
 
                    if (extensions.startsWith(QLatin1Char('.')))
394
 
                        extensions.remove(0,1);
395
 
                    extensions.replace(QLatin1String(",."), QLatin1String(","));
396
 
 
397
 
                    extensions.insert(0, QLatin1String("*."));
398
 
                    extensions.replace(QLatin1Char(','), QLatin1String(",*."));
399
 
                    extensionsNameFilters = extensions.split(QLatin1Char(','));
 
408
                    foreach (QString ext, extensions.split(QLatin1Char(','))) {
 
409
                        ext = ext.trimmed();
 
410
                        if (ext.startsWith(QLatin1Char('.')))
 
411
                            ext.remove(0, 1);
 
412
                        extensionsNameFilters.insert(ext);
 
413
                    }
400
414
                }
401
415
                QDir::Filters filters = QDir::Files | QDir::NoSymLinks;
 
416
                if (recursiveScan)
 
417
                    filters |= QDir::AllDirs | QDir::NoDotAndDotDot;
402
418
                QFileInfoList fileinfolist;
403
 
                recursiveFileInfoList(dir, extensionsNameFilters, filters,
404
 
                    recursiveScan, &fileinfolist);
405
 
                QFileInfoList::iterator ii;
406
 
                QString fn;
407
 
                for (ii = fileinfolist.begin(); ii != fileinfolist.end(); ++ii) {
408
 
                    // Make sure the path separator is stored with '/' in the ts file
409
 
                    sourceFiles << ii->canonicalFilePath().replace(QLatin1Char('\\'), QLatin1Char('/'));
 
419
                recursiveFileInfoList(dir, extensionsNameFilters, filters, &fileinfolist);
 
420
                int scanRootLen = dir.absolutePath().length();
 
421
                foreach (const QFileInfo &fi, fileinfolist) {
 
422
                    QString fn = QDir::cleanPath(fi.absoluteFilePath());
 
423
                    sourceFiles << fn;
 
424
 
 
425
                    if (!fn.endsWith(QLatin1String(".java"))
 
426
                        && !fn.endsWith(QLatin1String(".ui"))
 
427
                        && !fn.endsWith(QLatin1String(".js"))
 
428
                        && !fn.endsWith(QLatin1String(".qs"))) {
 
429
                        int offset = 0;
 
430
                        int depth = 0;
 
431
                        do {
 
432
                            offset = fn.lastIndexOf(QLatin1Char('/'), offset - 1);
 
433
                            QString ffn = fn.mid(offset + 1);
 
434
                            allCSources.insert(ffn, fn);
 
435
                        } while (++depth < 3 && offset > scanRootLen);
 
436
                    }
410
437
                }
411
438
            } else {
412
 
                sourceFiles << fi.canonicalFilePath().replace(QLatin1Char('\\'), QLatin1Char('/'));
 
439
                sourceFiles << QDir::cleanPath(fi.absoluteFilePath());;
413
440
            }
414
441
        }
415
442
    } // for args
416
443
 
 
444
    foreach (const QString &proFile, proFiles)
 
445
        projectRoots.insert(QDir::cleanPath(QFileInfo(proFile).absolutePath()) + QLatin1Char('/'));
417
446
 
418
447
    bool firstPass = true;
419
448
    bool fail = false;
421
450
        ConversionData cd;
422
451
        cd.m_defaultContext = defaultContext;
423
452
        cd.m_noUiLines = options & NoUiLines;
 
453
        cd.m_projectRoots = projectRoots;
 
454
        cd.m_includePath = includePath;
 
455
        cd.m_allCSources = allCSources;
424
456
 
425
457
        QStringList tsFiles = tsFileNames;
426
458
        if (proFiles.count() > 0) {
450
482
                continue;
451
483
            }
452
484
 
453
 
            evaluateProFile(visitor, &variables);
 
485
            cd.m_includePath += visitor.values(QLatin1String("INCLUDEPATH"));
 
486
 
 
487
            evaluateProFile(visitor, &variables, pfi.absolutePath());
454
488
 
455
489
            sourceFiles = variables.value("SOURCES");
456
490
 
472
506
            tsFiles += variables.value("TRANSLATIONS");
473
507
        }
474
508
 
 
509
        QStringList sourceFilesCpp;
475
510
        for (QStringList::iterator it = sourceFiles.begin(); it != sourceFiles.end(); ++it) {
476
 
            if (it->endsWith(QLatin1String(".java"), Qt::CaseInsensitive)) {
477
 
                cd.m_sourceFileName = *it;
478
 
                fetchedTor.load(*it, cd, QLatin1String("java"));
479
 
                //fetchtr_java(*it, &fetchedTor, defaultContext, true, codecForSource);
480
 
            }
481
 
            else if (it->endsWith(QLatin1String(".ui"), Qt::CaseInsensitive)) {
482
 
                fetchedTor.load(*it, cd, QLatin1String("ui"));
483
 
                //fetchedTor.load(*it + QLatin1String(".h"), cd, QLatin1String("cpp"));
484
 
                //fetchtr_ui(*it, &fetchedTor, defaultContext, true);
485
 
                //fetchtr_cpp(*it + QLatin1String(".h"), &fetchedTor,
486
 
                //             defaultContext, false, codecForSource);
487
 
            }
 
511
            if (it->endsWith(QLatin1String(".java"), Qt::CaseInsensitive))
 
512
                loadJava(fetchedTor, *it, cd);
 
513
            else if (it->endsWith(QLatin1String(".ui"), Qt::CaseInsensitive)
 
514
                     || it->endsWith(QLatin1String(".jui"), Qt::CaseInsensitive))
 
515
                loadUI(fetchedTor, *it, cd);
488
516
            else if (it->endsWith(QLatin1String(".js"), Qt::CaseInsensitive)
489
 
                || it->endsWith(QLatin1String(".qs"), Qt::CaseInsensitive)) {
490
 
                fetchedTor.load(*it, cd, QLatin1String("js"));
491
 
            } else {
492
 
                fetchedTor.load(*it, cd, QLatin1String("cpp"));
493
 
                //fetchtr_cpp(*it, &fetchedTor, defaultContext, true, codecForSource);
494
 
            }
 
517
                     || it->endsWith(QLatin1String(".qs"), Qt::CaseInsensitive))
 
518
                loadQScript(fetchedTor, *it, cd);
 
519
            else
 
520
                sourceFilesCpp << *it;
495
521
        }
 
522
        loadCPP(fetchedTor, sourceFilesCpp, cd);
496
523
        if (!cd.error().isEmpty())
497
524
            printOut(cd.error());
498
525