Ignore:
Timestamp:
Feb 11, 2010, 11:19:06 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.6.1 sources.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/tools/linguist/shared/translator.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the Qt Linguist of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    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.
     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.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4646#include <stdio.h>
    4747
    48 #include <QtCore/QCoreApplication>
    4948#include <QtCore/QDebug>
    5049#include <QtCore/QDir>
     
    5857QT_BEGIN_NAMESPACE
    5958
     59#ifdef QT_BOOTSTRAPPED
     60QString QObject::tr(const char *sourceText, const char *, int n)
     61{
     62    QString ret = QString::fromLatin1(sourceText);
     63    if (n >= 0)
     64        ret.replace(QLatin1String("%n"), QString::number(n));
     65    return ret;
     66}
     67#endif
     68
    6069Translator::Translator() :
    61     m_codecName("ISO-8859-1"),
     70    m_codec(QTextCodec::codecForName("ISO-8859-1")),
    6271    m_locationsType(AbsoluteLocations)
    6372{
     
    8291}
    8392
    84 void Translator::replace(const TranslatorMessage &msg)
    85 {
    86     int index = m_messages.indexOf(msg);
    87     if (index == -1)
    88         m_messages.append(msg);
    89     else
    90         m_messages[index] = msg;
    91 }
    92 
    9393void Translator::replaceSorted(const TranslatorMessage &msg)
    9494{
    95     int index = m_messages.indexOf(msg);
     95    int index = find(msg);
    9696    if (index == -1)
    9797        appendSorted(msg);
     
    102102void Translator::extend(const TranslatorMessage &msg)
    103103{
    104     int index = m_messages.indexOf(msg);
     104    int index = find(msg);
    105105    if (index == -1) {
    106106        m_messages.append(msg);
     
    147147    int curIdx = 0;
    148148    foreach (const TranslatorMessage &mit, m_messages) {
    149         bool sameFile = mit.fileName() == msg.fileName();
     149        bool sameFile = mit.fileName() == msg.fileName() && mit.context() == msg.context();
    150150        int curLine;
    151151        if (sameFile && (curLine = mit.lineNumber()) >= prevLine) {
     
    313313}
    314314
    315 bool Translator::contains(const QString &context,
    316     const QString &sourceText, const QString &comment) const
    317 {
    318     return m_messages.contains(TranslatorMessage(context, sourceText, comment,
    319         QString(), QString(), 0));
    320 }
    321 
    322 TranslatorMessage Translator::find(const QString &context,
    323     const QString &sourceText, const QString &comment) const
    324 {
    325     TranslatorMessage needle(context, sourceText, comment, QString(), QString(), 0);
    326     int index = m_messages.indexOf(needle);
    327     return index == -1 ? TranslatorMessage() : m_messages.at(index);
     315int Translator::find(const TranslatorMessage &msg) const
     316{
     317    for (int i = 0; i < m_messages.count(); ++i) {
     318        const TranslatorMessage &tmsg = m_messages.at(i);
     319        if (msg.id().isEmpty() || tmsg.id().isEmpty()) {
     320            if (msg.context() == tmsg.context()
     321                && msg.sourceText() == tmsg.sourceText()
     322                && msg.comment() == tmsg.comment())
     323                return i;
     324        } else {
     325            if (msg.id() == tmsg.id())
     326                return i;
     327        }
     328    }
     329    return -1;
    328330}
    329331
     
    346348{
    347349    foreach (const TranslatorMessage &msg, m_messages)
    348         if (msg.context() == context && msg.sourceText().isEmpty())
     350        if (msg.context() == context && msg.sourceText().isEmpty() && msg.id().isEmpty())
    349351            return true;
    350352    return false;
     
    354356{
    355357    foreach (const TranslatorMessage &msg, m_messages)
    356         if (msg.context() == context && msg.sourceText().isEmpty())
     358        if (msg.context() == context && msg.sourceText().isEmpty() && msg.id().isEmpty())
    357359            return msg;
    358360    return TranslatorMessage();
     
    417419}
    418420
    419 QSet<TranslatorMessagePtr> Translator::resolveDuplicates()
    420 {
    421     QSet<TranslatorMessagePtr> dups;
    422     QHash<TranslatorMessagePtr, int> refs;
     421void Translator::dropUiLines()
     422{
     423    QString uiXt = QLatin1String(".ui");
     424    QString juiXt = QLatin1String(".jui");
     425    for (TMM::Iterator it = m_messages.begin(); it != m_messages.end(); ++it) {
     426        QHash<QString, int> have;
     427        QList<TranslatorMessage::Reference> refs;
     428        foreach (const TranslatorMessage::Reference &itref, it->allReferences()) {
     429            const QString &fn = itref.fileName();
     430            if (fn.endsWith(uiXt) || fn.endsWith(juiXt)) {
     431                if (++have[fn] == 1)
     432                    refs.append(TranslatorMessage::Reference(fn, -1));
     433            } else {
     434                refs.append(itref);
     435            }
     436        }
     437        it->setReferences(refs);
     438    }
     439}
     440
     441struct TranslatorMessageIdPtr {
     442    explicit TranslatorMessageIdPtr(const TranslatorMessage &tm)
     443    {
     444        ptr = &tm;
     445    }
     446
     447    inline const TranslatorMessage *operator->() const
     448    {
     449        return ptr;
     450    }
     451
     452    const TranslatorMessage *ptr;
     453};
     454
     455Q_DECLARE_TYPEINFO(TranslatorMessageIdPtr, Q_MOVABLE_TYPE);
     456
     457inline int qHash(TranslatorMessageIdPtr tmp)
     458{
     459    return qHash(tmp->id());
     460}
     461
     462inline bool operator==(TranslatorMessageIdPtr tmp1, TranslatorMessageIdPtr tmp2)
     463{
     464    return tmp1->id() == tmp2->id();
     465}
     466
     467struct TranslatorMessageContentPtr {
     468    explicit TranslatorMessageContentPtr(const TranslatorMessage &tm)
     469    {
     470        ptr = &tm;
     471    }
     472
     473    inline const TranslatorMessage *operator->() const
     474    {
     475        return ptr;
     476    }
     477
     478    const TranslatorMessage *ptr;
     479};
     480
     481Q_DECLARE_TYPEINFO(TranslatorMessageContentPtr, Q_MOVABLE_TYPE);
     482
     483inline int qHash(TranslatorMessageContentPtr tmp)
     484{
     485    int hash = qHash(tmp->context()) ^ qHash(tmp->sourceText());
     486    if (!tmp->sourceText().isEmpty())
     487        // Special treatment for context comments (empty source).
     488        hash ^= qHash(tmp->comment());
     489    return hash;
     490}
     491
     492inline bool operator==(TranslatorMessageContentPtr tmp1, TranslatorMessageContentPtr tmp2)
     493{
     494    if (tmp1->context() != tmp2->context() || tmp1->sourceText() != tmp2->sourceText())
     495        return false;
     496    // Special treatment for context comments (empty source).
     497    if (tmp1->sourceText().isEmpty())
     498        return true;
     499    return tmp1->comment() == tmp2->comment();
     500}
     501
     502Translator::Duplicates Translator::resolveDuplicates()
     503{
     504    Duplicates dups;
     505    QHash<TranslatorMessageIdPtr, int> idRefs;
     506    QHash<TranslatorMessageContentPtr, int> contentRefs;
    423507    for (int i = 0; i < m_messages.count();) {
    424508        const TranslatorMessage &msg = m_messages.at(i);
    425         QHash<TranslatorMessagePtr, int>::ConstIterator it = refs.constFind(msg);
    426         if (it != refs.constEnd()) {
    427             TranslatorMessage &omsg = m_messages[*it];
    428             if (omsg.isUtf8() != msg.isUtf8() && !omsg.isNonUtf8()) {
    429                 // Dual-encoded message
    430                 omsg.setUtf8(true);
    431                 omsg.setNonUtf8(true);
    432             } else {
    433                 // Duplicate
    434                 dups.insert(omsg);
     509        TranslatorMessage *omsg;
     510        int oi;
     511        QSet<int> *pDup;
     512        if (!msg.id().isEmpty()) {
     513            QHash<TranslatorMessageIdPtr, int>::ConstIterator it =
     514                    idRefs.constFind(TranslatorMessageIdPtr(msg));
     515            if (it != idRefs.constEnd()) {
     516                oi = *it;
     517                omsg = &m_messages[oi];
     518                pDup = &dups.byId;
     519                goto gotDupe;
    435520            }
    436             if (!omsg.isTranslated() && msg.isTranslated())
    437                 omsg.setTranslations(msg.translations());
    438             m_messages.removeAt(i);
     521        }
     522        {
     523            QHash<TranslatorMessageContentPtr, int>::ConstIterator it =
     524                    contentRefs.constFind(TranslatorMessageContentPtr(msg));
     525            if (it != contentRefs.constEnd()) {
     526                oi = *it;
     527                omsg = &m_messages[oi];
     528                if (msg.id().isEmpty() || omsg->id().isEmpty()) {
     529                    if (!msg.id().isEmpty() && omsg->id().isEmpty()) {
     530                        omsg->setId(msg.id());
     531                        idRefs[TranslatorMessageIdPtr(*omsg)] = oi;
     532                    }
     533                    pDup = &dups.byContents;
     534                    goto gotDupe;
     535                }
     536                // This is really a content dupe, but with two distinct IDs.
     537            }
     538        }
     539        if (!msg.id().isEmpty())
     540            idRefs[TranslatorMessageIdPtr(msg)] = i;
     541        contentRefs[TranslatorMessageContentPtr(msg)] = i;
     542        ++i;
     543        continue;
     544      gotDupe:
     545        if (omsg->isUtf8() != msg.isUtf8() && !omsg->isNonUtf8()) {
     546            // Dual-encoded message
     547            omsg->setUtf8(true);
     548            omsg->setNonUtf8(true);
    439549        } else {
    440             refs[msg] = i;
    441             ++i;
    442         }
     550            // Duplicate
     551            pDup->insert(oi);
     552        }
     553        if (!omsg->isTranslated() && msg.isTranslated())
     554            omsg->setTranslations(msg.translations());
     555        m_messages.removeAt(i);
    443556    }
    444557    return dups;
    445558}
    446559
    447 void Translator::reportDuplicates(const QSet<TranslatorMessagePtr> &dupes,
     560void Translator::reportDuplicates(const Duplicates &dupes,
    448561                                  const QString &fileName, bool verbose)
    449562{
    450     if (!dupes.isEmpty()) {
     563    if (!dupes.byId.isEmpty() || !dupes.byContents.isEmpty()) {
    451564        if (!verbose) {
    452565            qWarning("Warning: dropping duplicate messages in '%s'\n(try -verbose for more info).",
     
    454567        } else {
    455568            qWarning("Warning: dropping duplicate messages in '%s':", qPrintable(fileName));
    456             foreach (const TranslatorMessagePtr &msg, dupes) {
     569            foreach (int i, dupes.byId)
     570                qWarning("\n* ID: %s", qPrintable(message(i).id()));
     571            foreach (int j, dupes.byContents) {
     572                const TranslatorMessage &msg = message(j);
    457573                qWarning("\n* Context: %s\n* Source: %s",
    458                         qPrintable(msg->context()),
    459                         qPrintable(msg->sourceText()));
    460                 if (!msg->comment().isEmpty())
    461                     qWarning("* Comment: %s", qPrintable(msg->comment()));
     574                        qPrintable(msg.context()),
     575                        qPrintable(msg.sourceText()));
     576                if (!msg.comment().isEmpty())
     577                    qWarning("* Comment: %s", qPrintable(msg.comment()));
    462578            }
    463579            qWarning();
     
    499615}
    500616
    501 QStringList Translator::normalizedTranslations(const TranslatorMessage &msg,
    502     QLocale::Language language, QLocale::Country country)
     617QStringList Translator::normalizedTranslations(const TranslatorMessage &msg, int numPlurals)
    503618{
    504619    QStringList translations = msg.translations();
    505     int numTranslations = 1;
    506     if (msg.isPlural() && language != QLocale::C) {
    507         QStringList forms;
    508         if (getNumerusInfo(language, country, 0, &forms))
    509             numTranslations = forms.count(); // includes singular
    510     }
     620    int numTranslations = msg.isPlural() ? numPlurals : 1;
    511621
    512622    // make sure that the stringlist always have the size of the
     
    522632}
    523633
    524 QStringList Translator::normalizedTranslations(const TranslatorMessage &msg,
    525     ConversionData &cd, bool *ok) const
    526 {
     634void Translator::normalizeTranslations(ConversionData &cd)
     635{
     636    bool truncated = false;
    527637    QLocale::Language l;
    528638    QLocale::Country c;
    529639    languageAndCountry(languageCode(), &l, &c);
    530     QStringList translns = normalizedTranslations(msg, l, c);
    531     if (msg.translations().size() > translns.size() && ok) {
     640    int numPlurals = 1;
     641    if (l != QLocale::C) {
     642        QStringList forms;
     643        if (getNumerusInfo(l, c, 0, &forms))
     644            numPlurals = forms.count(); // includes singular
     645    }
     646    for (int i = 0; i < m_messages.count(); ++i) {
     647        const TranslatorMessage &msg = m_messages.at(i);
     648        QStringList tlns = msg.translations();
     649        int ccnt = msg.isPlural() ? numPlurals : 1;
     650        if (tlns.count() != ccnt) {
     651            while (tlns.count() < ccnt)
     652                tlns.append(QString());
     653            while (tlns.count() > ccnt) {
     654                tlns.removeLast();
     655                truncated = true;
     656            }
     657            TranslatorMessage msg2(msg);
     658            msg2.setTranslations(tlns);
     659            m_messages[i] = msg2;
     660        }
     661    }
     662    if (truncated)
    532663        cd.appendError(QLatin1String(
    533664            "Removed plural forms as the target language has less "
    534665            "forms.\nIf this sounds wrong, possibly the target language is "
    535666            "not set or recognized.\n"));
    536         *ok = false;
    537     }
    538     return translns;
    539667}
    540668
     
    586714        if (!name.isEmpty())
    587715            qWarning("No QTextCodec for %s available. Using Latin1\n", name.constData());
    588         m_codecName = "ISO-8859-1";
     716        m_codec = QTextCodec::codecForName("ISO-8859-1");
    589717    } else {
    590         m_codecName = codec->name();
    591     }
     718        m_codec = codec;
     719    }
     720}
     721
     722QByteArray Translator::codecName() const
     723{
     724    return m_codec->name();
    592725}
    593726
Note: See TracChangeset for help on using the changeset viewer.