1
1
/****************************************************************************
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)
6
7
** This file is part of the Qt Linguist of the Qt Toolkit.
8
9
** $QT_BEGIN_LICENSE:LGPL$
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
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.
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
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.
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.
28
** If you have questions regarding the use of this file, please contact
29
** Nokia at qt-info@nokia.com.
38
38
** $QT_END_LICENSE$
40
40
****************************************************************************/
42
#include "translator.h"
43
#include "translatortools.h"
44
#include "profileevaluator.h"
44
#include <translator.h>
45
#include <profileevaluator.h>
46
#include <proreader.h>
46
48
#include <QtCore/QCoreApplication>
47
49
#include <QtCore/QDebug>
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)
67
filter |= QDir::AllDirs;
68
QFileInfoList entries = dir.entryInfoList(nameFilters, filter);
70
QFileInfoList::iterator it;
71
for (it = entries.begin(); it != entries.end(); ++it) {
72
QString fname = it->fileName();
73
if (fname != QLatin1String(".") && fname != QLatin1String("..")) {
75
recursiveFileInfoList(QDir(it->absoluteFilePath()), nameFilters, filter, recursive, fileinfolist);
77
fileinfolist->append(*it);
68
foreach (const QFileInfo &fi, dir.entryInfoList(filter))
70
recursiveFileInfoList(QDir(fi.absoluteFilePath()), nameFilters, filter, fileinfolist);
71
else if (nameFilters.contains(fi.suffix()))
72
fileinfolist->append(fi);
82
75
static void printUsage()
84
77
printOut(QObject::tr(
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"
93
86
" -help Display this information and exit.\n"
103
96
" Do not explain what is being done.\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"
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"
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));
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);
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(","));
397
extensions.insert(0, QLatin1String("*."));
398
extensions.replace(QLatin1Char(','), QLatin1String(",*."));
399
extensionsNameFilters = extensions.split(QLatin1Char(','));
408
foreach (QString ext, extensions.split(QLatin1Char(','))) {
410
if (ext.startsWith(QLatin1Char('.')))
412
extensionsNameFilters.insert(ext);
401
415
QDir::Filters filters = QDir::Files | QDir::NoSymLinks;
417
filters |= QDir::AllDirs | QDir::NoDotAndDotDot;
402
418
QFileInfoList fileinfolist;
403
recursiveFileInfoList(dir, extensionsNameFilters, filters,
404
recursiveScan, &fileinfolist);
405
QFileInfoList::iterator ii;
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());
425
if (!fn.endsWith(QLatin1String(".java"))
426
&& !fn.endsWith(QLatin1String(".ui"))
427
&& !fn.endsWith(QLatin1String(".js"))
428
&& !fn.endsWith(QLatin1String(".qs"))) {
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);
412
sourceFiles << fi.canonicalFilePath().replace(QLatin1Char('\\'), QLatin1Char('/'));
439
sourceFiles << QDir::cleanPath(fi.absoluteFilePath());;
444
foreach (const QString &proFile, proFiles)
445
projectRoots.insert(QDir::cleanPath(QFileInfo(proFile).absolutePath()) + QLatin1Char('/'));
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;
425
457
QStringList tsFiles = tsFileNames;
426
458
if (proFiles.count() > 0) {
472
506
tsFiles += variables.value("TRANSLATIONS");
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);
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);
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"));
492
fetchedTor.load(*it, cd, QLatin1String("cpp"));
493
//fetchtr_cpp(*it, &fetchedTor, defaultContext, true, codecForSource);
517
|| it->endsWith(QLatin1String(".qs"), Qt::CaseInsensitive))
518
loadQScript(fetchedTor, *it, cd);
520
sourceFilesCpp << *it;
522
loadCPP(fetchedTor, sourceFilesCpp, cd);
496
523
if (!cd.error().isEmpty())
497
524
printOut(cd.error());