diff options
author | Kent Hansen <khansen@trolltech.com> | 2009-07-14 15:49:56 (GMT) |
---|---|---|
committer | Kent Hansen <khansen@trolltech.com> | 2009-07-14 15:49:56 (GMT) |
commit | 8fd9cbc859346d758bb730e85c679635f00940df (patch) | |
tree | bc3b10d79a458933b1f481bd7e88d1a633e7bc1e /tools/linguist/shared | |
parent | 65b788014759fa06d65d1677b3dbd5cc4b596f6b (diff) | |
parent | 06af27069497a693f5b1a867b29d96297f68eb75 (diff) | |
download | Qt-8fd9cbc859346d758bb730e85c679635f00940df.zip Qt-8fd9cbc859346d758bb730e85c679635f00940df.tar.gz Qt-8fd9cbc859346d758bb730e85c679635f00940df.tar.bz2 |
Merge branch 'qtwebkit-4.6-staging' into qtscript-jsc-backend
Conflicts:
src/3rdparty/webkit/JavaScriptCore/interpreter/Interpreter.cpp
src/script/qscriptecmafunction.cpp
src/script/qscriptecmaglobal.cpp
src/script/qscriptengine.cpp
src/script/qscriptengine_p.cpp
src/script/qscriptenginefwd_p.h
src/script/qscriptextqobject.cpp
src/script/qscriptextqobject_p.h
tests/auto/qscriptqobject/tst_qscriptqobject.cpp
Diffstat (limited to 'tools/linguist/shared')
-rw-r--r-- | tools/linguist/shared/po.cpp | 10 | ||||
-rw-r--r-- | tools/linguist/shared/profileevaluator.cpp | 235 | ||||
-rw-r--r-- | tools/linguist/shared/profileevaluator.h | 10 | ||||
-rw-r--r-- | tools/linguist/shared/proparser.pri | 2 | ||||
-rw-r--r-- | tools/linguist/shared/proreader.cpp | 131 | ||||
-rw-r--r-- | tools/linguist/shared/proreader.h | 57 | ||||
-rw-r--r-- | tools/linguist/shared/qm.cpp | 64 | ||||
-rw-r--r-- | tools/linguist/shared/qph.cpp | 7 | ||||
-rw-r--r-- | tools/linguist/shared/translator.h | 8 | ||||
-rw-r--r-- | tools/linguist/shared/ts.cpp | 6 | ||||
-rw-r--r-- | tools/linguist/shared/ts.dtd | 8 | ||||
-rw-r--r-- | tools/linguist/shared/xliff.cpp | 7 |
12 files changed, 331 insertions, 214 deletions
diff --git a/tools/linguist/shared/po.cpp b/tools/linguist/shared/po.cpp index cb943be..e22aa7d 100644 --- a/tools/linguist/shared/po.cpp +++ b/tools/linguist/shared/po.cpp @@ -395,7 +395,10 @@ bool loadPO(Translator &translator, QIODevice &dev, ConversionData &cd) const QString prefix = QLatin1String(isObsolete ? "#~ " : ""); while (true) { int idx = line.indexOf(QLatin1Char(' '), prefix.length()); - item.msgStr.append(slurpEscapedString(lines, l, idx, prefix, cd)); + QString str = slurpEscapedString(lines, l, idx, prefix, cd); + str.replace(QChar(Translator::TextVariantSeparator), + QChar(Translator::BinaryVariantSeparator)); + item.msgStr.append(str); if (l + 1 >= lines.size() || !isTranslationLine(lines.at(l + 1))) break; ++l; @@ -635,8 +638,11 @@ bool savePO(const Translator &translator, QIODevice &dev, ConversionData &cd) out << poEscapedString(prefix, QLatin1String("msgid_plural"), noWrap, plural); QStringList translations = translator.normalizedTranslations(msg, cd, &ok); for (int i = 0; i != translations.size(); ++i) { + QString str = translations.at(i); + str.replace(QChar(Translator::BinaryVariantSeparator), + QChar(Translator::TextVariantSeparator)); out << poEscapedString(prefix, QString::fromLatin1("msgstr[%1]").arg(i), noWrap, - translations.at(i)); + str); } } first = false; diff --git a/tools/linguist/shared/profileevaluator.cpp b/tools/linguist/shared/profileevaluator.cpp index ef59543..0ce27af 100644 --- a/tools/linguist/shared/profileevaluator.cpp +++ b/tools/linguist/shared/profileevaluator.cpp @@ -68,8 +68,10 @@ #ifdef Q_OS_WIN32 #define QT_POPEN _popen +#define QT_PCLOSE _pclose #else #define QT_POPEN popen +#define QT_PCLOSE pclose #endif QT_BEGIN_NAMESPACE @@ -188,9 +190,6 @@ public: QString propertyValue(const QString &val) const; bool isActiveConfig(const QString &config, bool regex = false); - QStringList expandPattern(const QString &pattern); - void expandPatternHelper(const QString &relName, const QString &absName, - QStringList &sources_out); QStringList expandVariableReferences(const QString &value); QStringList evaluateExpandFunction(const QString &function, const QString &arguments); QString format(const char *format) const; @@ -761,29 +760,6 @@ bool ProFileEvaluator::Private::visitProValue(ProValue *value) m_prevLineNo = m_lineNo; m_prevProFile = currentProFile(); - // The following two blocks fix bug 180128 by making all "interesting" - // file name absolute in each .pro file, not just the top most one - if (varName == QLatin1String("SOURCES") - || varName == QLatin1String("HEADERS") - || varName == QLatin1String("INTERFACES") - || varName == QLatin1String("FORMS") - || varName == QLatin1String("FORMS3") - || varName == QLatin1String("RESOURCES")) { - // matches only existent files, expand certain(?) patterns - QStringList vv; - for (int i = v.count(); --i >= 0; ) - vv << expandPattern(v[i]); - v = vv; - } - - if (varName == QLatin1String("TRANSLATIONS")) { - // also matches non-existent files, but does not expand pattern - QString dir = QFileInfo(currentFileName()).absolutePath(); - dir += QLatin1Char('/'); - for (int i = v.count(); --i >= 0; ) - v[i] = QFileInfo(dir, v[i]).absoluteFilePath(); - } - switch (m_variableOperator) { case ProVariable::SetOperator: // = if (!m_cumulative) { @@ -1513,6 +1489,8 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun output += QLatin1String(buff); } ret += split_value_list(output); + if (proc) + QT_PCLOSE(proc); } } break; @@ -1949,9 +1927,9 @@ QStringList ProFileEvaluator::Private::values(const QString &variableName, ret = QLatin1String("Windows"); } else if (type == QLatin1String("name")) { DWORD name_length = 1024; - TCHAR name[1024]; + wchar_t name[1024]; if (GetComputerName(name, &name_length)) - ret = QString::fromUtf16((ushort*)name, name_length); + ret = QString::fromWCharArray(name); } else if (type == QLatin1String("version") || type == QLatin1String("version_string")) { QSysInfo::WinVersion ver = QSysInfo::WindowsVersion; if (type == QLatin1String("version")) @@ -2067,7 +2045,7 @@ bool ProFileEvaluator::Private::evaluateFile(const QString &fileName, bool *resu ProFile *pro = q->parsedProFile(fileName); if (pro) { m_profileStack.push(pro); - ok = (currentProFile() ? pro->Accept(this) : false); + ok = pro->Accept(this); m_profileStack.pop(); q->releaseParsedProFile(pro); @@ -2077,16 +2055,6 @@ bool ProFileEvaluator::Private::evaluateFile(const QString &fileName, bool *resu if (result) *result = false; } -/* if (ok && readFeatures) { - QStringList configs = values("CONFIG"); - QSet<QString> processed; - foreach (const QString &fn, configs) { - if (!processed.contains(fn)) { - processed.insert(fn); - evaluateFeatureFile(fn, 0); - } - } - } */ return ok; } @@ -2115,82 +2083,6 @@ bool ProFileEvaluator::Private::evaluateFeatureFile(const QString &fileName, boo return ok; } -void ProFileEvaluator::Private::expandPatternHelper(const QString &relName, const QString &absName, - QStringList &sources_out) -{ - const QStringList vpaths = values(QLatin1String("VPATH")) - + values(QLatin1String("QMAKE_ABSOLUTE_SOURCE_PATH")) - + values(QLatin1String("DEPENDPATH")) - + values(QLatin1String("VPATH_SOURCES")); - - QFileInfo fi(absName); - bool found = fi.exists(); - // Search in all vpaths - if (!found) { - foreach (const QString &vpath, vpaths) { - fi.setFile(vpath + QDir::separator() + relName); - if (fi.exists()) { - found = true; - break; - } - } - } - - if (found) { - sources_out += fi.absoluteFilePath(); // Not resolving symlinks - } else { - QString val = relName; - QString dir; - QString wildcard = val; - QString real_dir; - if (wildcard.lastIndexOf(QLatin1Char('/')) != -1) { - dir = wildcard.left(wildcard.lastIndexOf(QLatin1Char('/')) + 1); - real_dir = dir; - wildcard = wildcard.right(wildcard.length() - dir.length()); - } - - if (real_dir.isEmpty() || QFileInfo(real_dir).exists()) { - QStringList files = QDir(real_dir).entryList(QStringList(wildcard)); - if (files.isEmpty()) { - q->logMessage(format("Failure to find %1").arg(val)); - } else { - QString a; - for (int i = files.count() - 1; i >= 0; --i) { - if (files[i] == QLatin1String(".") || files[i] == QLatin1String("..")) - continue; - a = dir + files[i]; - sources_out += a; - } - } - } else { - q->logMessage(format("Cannot match %1/%2, as %3 does not exist.") - .arg(real_dir).arg(wildcard).arg(real_dir)); - } - } -} - - -/* - * Lookup of files are done in this order: - * 1. look in pwd - * 2. look in vpaths - * 3. expand wild card files relative from the profiles folder - **/ - -// FIXME: This code supports something that I'd consider a flaw in .pro file syntax -// which is not even documented. So arguably this can be ditched completely... -QStringList ProFileEvaluator::Private::expandPattern(const QString& pattern) -{ - if (!currentProFile()) - return QStringList(); - - QStringList sources_out; - const QString absName = QDir::cleanPath(QDir::current().absoluteFilePath(pattern)); - - expandPatternHelper(pattern, absName, sources_out); - return sources_out; -} - QString ProFileEvaluator::Private::format(const char *fmt) const { ProFile *pro = currentProFile(); @@ -2241,6 +2133,59 @@ QStringList ProFileEvaluator::values(const QString &variableName, const ProFile return fixEnvVariables(d->values(variableName, pro)); } +QStringList ProFileEvaluator::absolutePathValues( + const QString &variable, const QString &baseDirectory) const +{ + QStringList result; + foreach (const QString &el, values(variable)) { + const QFileInfo info = QFileInfo(baseDirectory, el); + if (info.isDir()) + result << QDir::cleanPath(info.absoluteFilePath()); + } + return result; +} + +QStringList ProFileEvaluator::absoluteFileValues( + const QString &variable, const QString &baseDirectory, const QStringList &searchDirs, + const ProFile *pro) const +{ + QStringList result; + foreach (const QString &el, pro ? values(variable, pro) : values(variable)) { + QFileInfo info(el); + if (info.isAbsolute()) { + if (info.exists()) { + result << QDir::cleanPath(el); + goto next; + } + } else { + foreach (const QString &dir, searchDirs) { + QFileInfo info(dir, el); + if (info.isFile()) { + result << QDir::cleanPath(info.filePath()); + goto next; + } + } + if (baseDirectory.isEmpty()) + goto next; + info = QFileInfo(baseDirectory, el); + } + { + QFileInfo baseInfo(info.absolutePath()); + if (baseInfo.exists()) { + QString wildcard = info.fileName(); + if (wildcard.contains(QLatin1Char('*')) || wildcard.contains(QLatin1Char('?'))) { + QDir theDir(QDir::cleanPath(baseInfo.filePath())); + foreach (const QString &fn, theDir.entryList(QStringList(wildcard))) + if (fn != QLatin1String(".") && fn != QLatin1String("..")) + result << theDir.absoluteFilePath(fn); + } + } + } + next: ; + } + return result; +} + ProFileEvaluator::TemplateType ProFileEvaluator::templateType() { QStringList templ = values(QLatin1String("TEMPLATE")); @@ -2327,64 +2272,4 @@ void ProFileEvaluator::setOutputDir(const QString &dir) d->m_outputDir = dir; } -void evaluateProFile(const ProFileEvaluator &visitor, QHash<QByteArray, QStringList> *varMap) -{ - QStringList sourceFiles; - QString codecForTr; - QString codecForSource; - QStringList tsFileNames; - - // app/lib template - sourceFiles += visitor.values(QLatin1String("SOURCES")); - sourceFiles += visitor.values(QLatin1String("HEADERS")); - tsFileNames = visitor.values(QLatin1String("TRANSLATIONS")); - - QStringList trcodec = visitor.values(QLatin1String("CODEC")) - + visitor.values(QLatin1String("DEFAULTCODEC")) - + visitor.values(QLatin1String("CODECFORTR")); - if (!trcodec.isEmpty()) - codecForTr = trcodec.last(); - - QStringList srccodec = visitor.values(QLatin1String("CODECFORSRC")); - if (!srccodec.isEmpty()) - codecForSource = srccodec.last(); - - QStringList forms = visitor.values(QLatin1String("INTERFACES")) - + visitor.values(QLatin1String("FORMS")) - + visitor.values(QLatin1String("FORMS3")); - sourceFiles << forms; - - sourceFiles.sort(); - sourceFiles.removeDuplicates(); - tsFileNames.sort(); - tsFileNames.removeDuplicates(); - - varMap->insert("SOURCES", sourceFiles); - varMap->insert("CODECFORTR", QStringList() << codecForTr); - varMap->insert("CODECFORSRC", QStringList() << codecForSource); - varMap->insert("TRANSLATIONS", tsFileNames); -} - -bool evaluateProFile(const QString &fileName, bool verbose, QHash<QByteArray, QStringList> *varMap) -{ - QFileInfo fi(fileName); - if (!fi.exists()) - return false; - - ProFile pro(fi.absoluteFilePath()); - - ProFileEvaluator visitor; - visitor.setVerbose(verbose); - - if (!visitor.queryProFile(&pro)) - return false; - - if (!visitor.accept(&pro)) - return false; - - evaluateProFile(visitor, varMap); - - return true; -} - QT_END_NAMESPACE diff --git a/tools/linguist/shared/profileevaluator.h b/tools/linguist/shared/profileevaluator.h index 69f47f5..688022b 100644 --- a/tools/linguist/shared/profileevaluator.h +++ b/tools/linguist/shared/profileevaluator.h @@ -52,12 +52,6 @@ QT_BEGIN_NAMESPACE -class ProFile; -class ProFileEvaluator; - -void evaluateProFile(const ProFileEvaluator &visitor, QHash<QByteArray, QStringList> *varMap); -bool evaluateProFile(const QString &fileName, bool verbose, QHash<QByteArray, QStringList> *varMap); - class ProFileEvaluator { public: @@ -85,6 +79,10 @@ public: void addProperties(const QHash<QString, QString> &properties); QStringList values(const QString &variableName) const; QStringList values(const QString &variableName, const ProFile *pro) const; + QStringList absolutePathValues(const QString &variable, const QString &baseDirectory) const; + QStringList absoluteFileValues( + const QString &variable, const QString &baseDirectory, const QStringList &searchDirs, + const ProFile *pro) const; QString propertyValue(const QString &val) const; // for our descendents diff --git a/tools/linguist/shared/proparser.pri b/tools/linguist/shared/proparser.pri index 372247e..99d32e7 100644 --- a/tools/linguist/shared/proparser.pri +++ b/tools/linguist/shared/proparser.pri @@ -2,11 +2,13 @@ INCLUDEPATH *= $$PWD HEADERS += \ + $$PWD/proreader.h \ $$PWD/abstractproitemvisitor.h \ $$PWD/proitems.h \ $$PWD/profileevaluator.h \ $$PWD/proparserutils.h SOURCES += \ + $$PWD/proreader.cpp \ $$PWD/proitems.cpp \ $$PWD/profileevaluator.cpp diff --git a/tools/linguist/shared/proreader.cpp b/tools/linguist/shared/proreader.cpp new file mode 100644 index 0000000..3400f20 --- /dev/null +++ b/tools/linguist/shared/proreader.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Linguist of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "profileevaluator.h" + +#include <QtCore/QDir> +#include <QtCore/QFileInfo> + +QT_BEGIN_NAMESPACE + +static QStringList getSources(const char *var, const char *vvar, const QStringList &baseVPaths, + const QString &projectDir, const ProFileEvaluator &visitor) +{ + QStringList vPaths = + visitor.absolutePathValues(QLatin1String(vvar), projectDir); + vPaths += baseVPaths; + vPaths.removeDuplicates(); + return visitor.absoluteFileValues(QLatin1String(var), projectDir, vPaths, 0); +} + +void evaluateProFile(const ProFileEvaluator &visitor, QHash<QByteArray, QStringList> *varMap, + const QString &projectDir) +{ + QStringList baseVPaths; + baseVPaths += visitor.absolutePathValues(QLatin1String("VPATH"), projectDir); + baseVPaths << projectDir; // QMAKE_ABSOLUTE_SOURCE_PATH + baseVPaths += visitor.absolutePathValues(QLatin1String("DEPENDPATH"), projectDir); + baseVPaths.removeDuplicates(); + + QStringList sourceFiles; + QString codecForTr; + QString codecForSource; + QStringList tsFileNames; + + // app/lib template + sourceFiles += getSources("SOURCES", "VPATH_SOURCES", baseVPaths, projectDir, visitor); + + sourceFiles += getSources("FORMS", "VPATH_FORMS", baseVPaths, projectDir, visitor); + sourceFiles += getSources("FORMS3", "VPATH_FORMS3", baseVPaths, projectDir, visitor); + + QStringList vPathsInc = baseVPaths; + vPathsInc += visitor.absolutePathValues(QLatin1String("INCLUDEPATH"), projectDir); + vPathsInc.removeDuplicates(); + sourceFiles += visitor.absoluteFileValues(QLatin1String("HEADERS"), projectDir, vPathsInc, 0); + + QDir proDir(projectDir); + foreach (const QString &tsFile, visitor.values(QLatin1String("TRANSLATIONS"))) + tsFileNames << QFileInfo(proDir, tsFile).filePath(); + + QStringList trcodec = visitor.values(QLatin1String("CODEC")) + + visitor.values(QLatin1String("DEFAULTCODEC")) + + visitor.values(QLatin1String("CODECFORTR")); + if (!trcodec.isEmpty()) + codecForTr = trcodec.last(); + + QStringList srccodec = visitor.values(QLatin1String("CODECFORSRC")); + if (!srccodec.isEmpty()) + codecForSource = srccodec.last(); + + sourceFiles.sort(); + sourceFiles.removeDuplicates(); + tsFileNames.sort(); + tsFileNames.removeDuplicates(); + + varMap->insert("SOURCES", sourceFiles); + varMap->insert("CODECFORTR", QStringList() << codecForTr); + varMap->insert("CODECFORSRC", QStringList() << codecForSource); + varMap->insert("TRANSLATIONS", tsFileNames); +} + +bool evaluateProFile(const QString &fileName, bool verbose, QHash<QByteArray, QStringList> *varMap) +{ + QFileInfo fi(fileName); + if (!fi.exists()) + return false; + + ProFile pro(fi.absoluteFilePath()); + + ProFileEvaluator visitor; + visitor.setVerbose(verbose); + + if (!visitor.queryProFile(&pro)) + return false; + + if (!visitor.accept(&pro)) + return false; + + evaluateProFile(visitor, varMap, fi.absolutePath()); + + return true; +} + +QT_END_NAMESPACE diff --git a/tools/linguist/shared/proreader.h b/tools/linguist/shared/proreader.h new file mode 100644 index 0000000..f663e23 --- /dev/null +++ b/tools/linguist/shared/proreader.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Linguist of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PROREADER_H +#define PROREADER_H + +#include <QtCore/QHash> + +QT_BEGIN_NAMESPACE + +class ProFileEvaluator; + +void evaluateProFile(const ProFileEvaluator &visitor, QHash<QByteArray, QStringList> *varMap, + const QString &projectDir); +bool evaluateProFile(const QString &fileName, bool verbose, QHash<QByteArray, QStringList> *varMap); + +QT_END_NAMESPACE + +#endif // PROREADER_H diff --git a/tools/linguist/shared/qm.cpp b/tools/linguist/shared/qm.cpp index 323bd29..9523fde 100644 --- a/tools/linguist/shared/qm.cpp +++ b/tools/linguist/shared/qm.cpp @@ -173,6 +173,7 @@ public: bool save(QIODevice *iod); void insert(const TranslatorMessage &msg, bool forceComment); + void insertIdBased(const TranslatorMessage &message); void squeeze(TranslatorSaveMode mode); @@ -238,17 +239,13 @@ Prefix Releaser::commonPrefix(const ByteTranslatorMessage &m1, const ByteTransla void Releaser::writeMessage(const ByteTranslatorMessage &msg, QDataStream &stream, TranslatorSaveMode mode, Prefix prefix) const { - for (int i = 0; i < msg.translations().count(); ++i) { - QString str = msg.translations().at(i); - str.replace(QChar(Translator::DefaultVariantSeparator), - QChar(Translator::InternalVariantSeparator)); - stream << quint8(Tag_Translation) << str; - } + for (int i = 0; i < msg.translations().count(); ++i) + stream << quint8(Tag_Translation) << msg.translations().at(i); if (mode == SaveEverything) prefix = HashContextSourceTextComment; - // lrelease produces "wrong" .qm files for QByteArrays that are .isNull(). + // lrelease produces "wrong" QM files for QByteArrays that are .isNull(). switch (prefix) { default: case HashContextSourceTextComment: @@ -440,6 +437,16 @@ void Releaser::insert(const TranslatorMessage &message, bool forceComment) insertInternal(message, forceComment, false); } +void Releaser::insertIdBased(const TranslatorMessage &message) +{ + QStringList tlns = message.translations(); + for (int i = 0; i < tlns.size(); ++i) + if (tlns.at(i).isEmpty()) + tlns[i] = message.sourceText(); + ByteTranslatorMessage bmsg("", originalBytes(message.id(), false), "", tlns); + m_messages.insert(bmsg, 0); +} + void Releaser::setNumerusRules(const QByteArray &rules) { m_numerusRules = rules; @@ -592,8 +599,6 @@ bool loadQM(Translator &translator, QIODevice &dev, ConversionData &cd) str[i] = QChar((str.at(i).unicode() >> 8) + ((str.at(i).unicode() << 8) & 0xff00)); } - str.replace(QChar(Translator::InternalVariantSeparator), - QChar(Translator::DefaultVariantSeparator)); translations << str; m += len; break; @@ -695,11 +700,17 @@ static bool saveQM(const Translator &translator, QIODevice &dev, ConversionData int finished = 0; int unfinished = 0; int untranslated = 0; + int missingIds = 0; + int droppedData = 0; for (int i = 0; i != translator.messageCount(); ++i) { const TranslatorMessage &msg = translator.message(i); TranslatorMessage::Type typ = msg.type(); if (typ != TranslatorMessage::Obsolete) { + if (cd.m_idBased && msg.id().isEmpty()) { + ++missingIds; + continue; + } if (typ == TranslatorMessage::Unfinished) { if (msg.translation().isEmpty()) { ++untranslated; @@ -712,19 +723,34 @@ static bool saveQM(const Translator &translator, QIODevice &dev, ConversionData } else { ++finished; } - // Drop the comment in (context, sourceText, comment), - // unless the context is empty, - // unless (context, sourceText, "") already exists or - // unless we already dropped the comment of (context, - // sourceText, comment0). - bool forceComment = - msg.comment().isEmpty() - || msg.context().isEmpty() - || translator.contains(msg.context(), msg.sourceText(), QString()); - releaser.insert(msg, forceComment); + if (cd.m_idBased) { + if (!msg.context().isEmpty() || !msg.comment().isEmpty()) + ++droppedData; + releaser.insertIdBased(msg); + } else { + // Drop the comment in (context, sourceText, comment), + // unless the context is empty, + // unless (context, sourceText, "") already exists or + // unless we already dropped the comment of (context, + // sourceText, comment0). + bool forceComment = + msg.comment().isEmpty() + || msg.context().isEmpty() + || translator.contains(msg.context(), msg.sourceText(), QString()); + releaser.insert(msg, forceComment); + } } } + if (missingIds) + cd.appendError(QCoreApplication::translate("LRelease", + "Dropped %n message(s) which had no ID.", 0, + QCoreApplication::CodecForTr, missingIds)); + if (droppedData) + cd.appendError(QCoreApplication::translate("LRelease", + "Excess context/disambiguation dropped from %n message(s).", 0, + QCoreApplication::CodecForTr, droppedData)); + releaser.squeeze(cd.m_saveMode); bool saved = releaser.save(&dev); if (saved && cd.isVerbose()) { diff --git a/tools/linguist/shared/qph.cpp b/tools/linguist/shared/qph.cpp index 40f0386..4a29e0f 100644 --- a/tools/linguist/shared/qph.cpp +++ b/tools/linguist/shared/qph.cpp @@ -99,6 +99,8 @@ bool QPHReader::read(Translator &translator) else if (m_currentField == DefinitionField) m_currentDefinition += text(); } else if (isEndElement() && name() == QLatin1String("phrase")) { + m_currentTarget.replace(QChar(Translator::TextVariantSeparator), + QChar(Translator::BinaryVariantSeparator)); TranslatorMessage msg; msg.setSourceText(m_currentSource); msg.setTranslation(m_currentTarget); @@ -159,7 +161,10 @@ static bool saveQPH(const Translator &translator, QIODevice &dev, ConversionData foreach (const TranslatorMessage &msg, translator.messages()) { t << "<phrase>\n"; t << " <source>" << protect(msg.sourceText()) << "</source>\n"; - t << " <target>" << protect(msg.translations().join(QLatin1String("@"))) + QString str = msg.translations().join(QLatin1String("@")); + str.replace(QChar(Translator::BinaryVariantSeparator), + QChar(Translator::TextVariantSeparator)); + t << " <target>" << protect(str) << "</target>\n"; if (!msg.context().isEmpty() || !msg.comment().isEmpty()) t << " <definition>" << msg.context() << msg.comment() diff --git a/tools/linguist/shared/translator.h b/tools/linguist/shared/translator.h index 2651af0..fb17fd1 100644 --- a/tools/linguist/shared/translator.h +++ b/tools/linguist/shared/translator.h @@ -65,6 +65,7 @@ public: m_ignoreUnfinished(false), m_sortContexts(false), m_noUiLines(false), + m_idBased(false), m_saveMode(SaveEverything) {} @@ -97,6 +98,7 @@ public: bool m_ignoreUnfinished; bool m_sortContexts; bool m_noUiLines; + bool m_idBased; TranslatorSaveMode m_saveMode; }; @@ -190,9 +192,9 @@ public: static void registerFileFormat(const FileFormat &format); static QList<FileFormat> ®isteredFileFormats(); - enum VariantSeparators { - DefaultVariantSeparator = 0x2762, // some weird character nobody ever heard of :-D - InternalVariantSeparator = 0x9c // unicode "STRING TERMINATOR" + enum { + TextVariantSeparator = 0x2762, // some weird character nobody ever heard of :-D + BinaryVariantSeparator = 0x9c // unicode "STRING TERMINATOR" }; private: diff --git a/tools/linguist/shared/ts.cpp b/tools/linguist/shared/ts.cpp index 6c95dbd..3efce15 100644 --- a/tools/linguist/shared/ts.cpp +++ b/tools/linguist/shared/ts.cpp @@ -197,7 +197,7 @@ QString TSReader::readTransContents() // ignore these, just whitespace } else if (elementStarts(strlengthvariant)) { if (!result.isEmpty()) - result += QChar(Translator::DefaultVariantSeparator); + result += QChar(Translator::BinaryVariantSeparator); result += readContents(); } else { handleError(); @@ -514,7 +514,7 @@ static void writeExtras(QTextStream &t, const char *indent, static void writeVariants(QTextStream &t, const char *indent, const QString &input) { int offset; - if ((offset = input.indexOf(QChar(Translator::DefaultVariantSeparator))) >= 0) { + if ((offset = input.indexOf(QChar(Translator::BinaryVariantSeparator))) >= 0) { t << " variants=\"yes\">"; int start = 0; forever { @@ -524,7 +524,7 @@ static void writeVariants(QTextStream &t, const char *indent, const QString &inp if (offset == input.length()) break; start = offset + 1; - offset = input.indexOf(QChar(Translator::DefaultVariantSeparator), start); + offset = input.indexOf(QChar(Translator::BinaryVariantSeparator), start); if (offset < 0) offset = input.length(); } diff --git a/tools/linguist/shared/ts.dtd b/tools/linguist/shared/ts.dtd index ab77f64..4d2cdeb 100644 --- a/tools/linguist/shared/ts.dtd +++ b/tools/linguist/shared/ts.dtd @@ -34,7 +34,7 @@ version CDATA #IMPLIED sourcelanguage CDATA #IMPLIED language CDATA #IMPLIED> -<!-- The encoding to use in the .qm file by default. Default is ISO-8859-1. --> +<!-- The encoding to use in the QM file by default. Default is ISO-8859-1. --> <!ELEMENT defaultcodec (#PCDATA) > <!ELEMENT context (name?, comment?, (context|message)+) > <!ATTLIST context @@ -54,7 +54,7 @@ <!ELEMENT message (location*, source?, oldsource?, comment?, oldcomment?, extracomment?, translatorcomment?, translation?, userdata?, extra-**) > <!-- ! If utf8 is true, the defaultcodec is overridden and the message is encoded - ! in UTF-8 in the .qm file. + ! in UTF-8 in the QM file. --> <!ATTLIST message id CDATA #IMPLIED @@ -70,7 +70,7 @@ ! is omitted, the "current" one is used. For the 1st location in a message, ! "current" is the filename used for the 1st location of the previous message. ! For subsequent locations, it is the filename used for the previous location. - ! A single .ts file has either all absolute or all relative locations. + ! A single TS file has either all absolute or all relative locations. --> <!ATTLIST location filename CDATA #IMPLIED @@ -106,7 +106,7 @@ <!-- ! The translation variants have a priority between 1 ("highest") and 9 ("lowest") ! Typically longer translations get a higher priority. - ! If omitted, the order of appearance of the variants in the .ts files is used. + ! If omitted, the order of appearance of the variants in the TS files is used. --> <!ATTLIST lengthvariant priority (1|2|3|4|5|6|7|8|9) #IMPLIED> diff --git a/tools/linguist/shared/xliff.cpp b/tools/linguist/shared/xliff.cpp index 61e4b9f..1313172 100644 --- a/tools/linguist/shared/xliff.cpp +++ b/tools/linguist/shared/xliff.cpp @@ -303,6 +303,8 @@ static void writeTransUnits(QTextStream &ts, const TranslatorMessage &msg, const QString translation; if (transit != transend) { translation = *transit; + translation.replace(QChar(Translator::BinaryVariantSeparator), + QChar(Translator::TextVariantSeparator)); ++transit; puttrans = true; } @@ -598,8 +600,11 @@ bool XLIFFHandler::endElement(const QString &namespaceURI, const QString& localN m_sources.append(accum); } } else if (localName == QLatin1String("target")) { - if (popContext(XC_restype_translation)) + if (popContext(XC_restype_translation)) { + accum.replace(QChar(Translator::TextVariantSeparator), + QChar(Translator::BinaryVariantSeparator)); m_translations.append(accum); + } } else if (localName == QLatin1String("context-group")) { if (popContext(XC_context_group)) { m_refs.append(TranslatorMessage::Reference( |