metatranslator.cpp

来自「奇趣公司比较新的qt/emd版本」· C++ 代码 · 共 837 行 · 第 1/2 页

CPP
837
字号
    }    reader.setContentHandler( hand );    reader.setErrorHandler( hand );    bool ok = reader.parse( in );    reader.setContentHandler( 0 );    reader.setErrorHandler( 0 );    makeFileNamesAbsolute(QFileInfo(filename).absoluteDir());    delete hand;    f.close();    return ok;}bool MetaTranslator::saveTS( const QString& filename) const{    QFile f( filename );    if ( !f.open(QIODevice::WriteOnly | QIODevice::Text) )        return false;    QTextStream t( &f );    t.setCodec( QTextCodec::codecForName("ISO-8859-1") );    //### The xml prolog allows processors to easily detect the correct encoding    t << QLatin1String("<?xml version=\"1.0\"");    t << QLatin1String(" encoding=\"utf-8\"");    t << QLatin1String("?>\n<!DOCTYPE TS><TS version=\"1.1\"");    if (!languageCode().isEmpty() && languageCode() != QLatin1String("C"))        t << QLatin1String(" language=\"") << languageCode() << QLatin1String("\"");    t << QLatin1String(">\n");    if ( codecName != "ISO-8859-1" )        t << QLatin1String("<defaultcodec>") << codecName << QLatin1String("</defaultcodec>\n");    TMM::ConstIterator m = mm.begin();    while ( m != mm.end() ) {        TMMInv inv;        TMMInv::Iterator i;        bool contextIsUtf8 = m.key().utf8();        QByteArray context = m.key().context();        QByteArray comment = "";        do {            if (QByteArray(m.key().sourceText()) == ContextComment) {                if ( m.key().type() != MetaTranslatorMessage::Obsolete ) {                    contextIsUtf8 = m.key().utf8();                    comment = QByteArray(m.key().comment());                }            } else {                inv.insert( *m, m.key() );            }        } while ( ++m != mm.end() && QByteArray(m.key().context()) == context );        t << "<context";        if ( contextIsUtf8 )            t << " encoding=\"UTF-8\"";        t << ">\n";        t << "    <name>" << evilBytes( context, contextIsUtf8 )          << "</name>\n";        if ( !comment.isEmpty() )            t << "    <comment>" << evilBytes( comment, contextIsUtf8 )              << "</comment>\n";        for ( i = inv.begin(); i != inv.end(); ++i ) {            MetaTranslatorMessage msg = *i;            // no need for such noise            if ( msg.type() == MetaTranslatorMessage::Obsolete && msg.translation().isEmpty() ) {                continue;            }            t << "    <message";            if ( msg.utf8() )                t << " encoding=\"UTF-8\"";            if ( msg.isPlural() )                t << " numerus=\"yes\"";            t << ">\n";            if (!msg.fileName().isEmpty() && msg.lineNumber() >= 0) {                QDir tsPath = QFileInfo(filename).absoluteDir();                QString fn = tsPath.relativeFilePath(msg.fileName()).replace(QLatin1Char('\\'),QLatin1Char('/'));                t << QLatin1String("        <location filename=\"") << fn << QLatin1String("\" line=\"") << msg.lineNumber() << QLatin1String("\"/>\n");            }            t  << QLatin1String("        <source>") << evilBytes( (*i).sourceText(), (*i).utf8() )              << QLatin1String("</source>\n");            if ( !QByteArray((*i).comment()).isEmpty() )                t << QLatin1String("        <comment>") << evilBytes( (*i).comment(), (*i).utf8() )                  << QLatin1String("</comment>\n");            t << QLatin1String("        <translation");            if ( (*i).type() == MetaTranslatorMessage::Unfinished )                t << QLatin1String(" type=\"unfinished\"");            else if ( (*i).type() == MetaTranslatorMessage::Obsolete )                t << QLatin1String(" type=\"obsolete\"");            t << ">";            if (msg.isPlural()) {                t << "\n";                QLocale::Language l;                QLocale::Country c;                languageAndCountry(m_language, &l, &c);                QStringList translns = normalizedTranslations(*i, l, c);                for (int j = 0; j < qMax(1, translns.count()); ++j)                    t << QLatin1String("            <numerusform>") << protect( translns.value(j).toUtf8() ) << QLatin1String("</numerusform>\n");                t << QLatin1String("        ");            } else {                t << protect( (*i).translation().toUtf8() );            }            t << QLatin1String("</translation>\n");            t << QLatin1String("    </message>\n");        }        t << QLatin1String("</context>\n");    }    t << QLatin1String("</TS>\n");    f.close();    return true;}bool MetaTranslator::save( const QString& filename) const{    if (filename.endsWith(QLatin1String(".xlf")) ) {            // XLIFF documents use the .xlf extension.         // No other extension is recommended by the specification.        return saveXLIFF(filename);    }    return saveTS(filename);}bool MetaTranslator::release( const QString& filename, bool verbose,                              bool ignoreUnfinished,                              Translator::SaveMode mode ) const{    QFile file(filename);    if (file.open(QIODevice::WriteOnly)) {        bool ok = release(&file, verbose, ignoreUnfinished, mode);        file.close();        return ok;    }    return false;}void MetaTranslator::languageAndCountry(const QString &languageCode, QLocale::Language *lang, QLocale::Country *country){    QLocale locale(languageCode);    if (lang)         *lang = locale.language();    if (country) {        if (languageCode.indexOf(QLatin1Char('_')) != -1) {            *country = locale.country();        } else {            *country = QLocale::AnyCountry;        }    }}bool MetaTranslator::release( QIODevice *iod, bool verbose /*= false*/,              bool ignoreUnfinished /*= false*/,              Translator::SaveMode mode /*= Translator::Stripped */) const{    Translator tor( 0 );    QLocale::Language l;    QLocale::Country c;    languageAndCountry(m_language, &l, &c);    QByteArray rules;    if (getNumerusInfo(l, c, &rules, 0)) {        tor.setNumerusRules(rules);    }    int finished = 0;    int unfinished = 0;    int untranslated = 0;    TMM::ConstIterator m;    for ( m = mm.begin(); m != mm.end(); ++m ) {        MetaTranslatorMessage::Type typ = m.key().type();        if ( typ != MetaTranslatorMessage::Obsolete ) {            if ( typ == MetaTranslatorMessage::Unfinished ) {                if (m.key().translation().isEmpty()) {                    untranslated++;                } else {                    unfinished++;                }            } else {                finished++;            }            QByteArray context = m.key().context();            QByteArray sourceText = m.key().sourceText();            QByteArray comment = m.key().comment();            QStringList translations = m.key().translations();            if ( !ignoreUnfinished                || typ != MetaTranslatorMessage::Unfinished ) {                /*                  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).                */                if ( comment.isEmpty()                     || context.isEmpty()                     || contains(context, sourceText, "")                     || !tor.findMessage(context, sourceText, "").translation()                            .isNull() ) {                    tor.insert( m.key() );                } else {                    tor.insert( TranslatorMessage(context, sourceText, "",                                                   QString(), -1, translations) );    //filename and lineNumbers will be ignored from now.                }            }        }    }    bool saved = tor.save( iod, mode );    if ( saved && verbose ) {        int generatedCount = finished + unfinished;        fprintf( stderr,            "    Generated %d translation%s (%d finished and %d unfinished)\n",            generatedCount, generatedCount == 1 ? "" : "s", finished, unfinished);        if (untranslated)            fprintf( stderr, "    Ignored %d untranslated source text%s\n",                 untranslated, untranslated == 1 ? "" : "s");    }    return saved;}QString MetaTranslator::languageCode() const{    return m_language;}void MetaTranslator::setLanguageCode(const QString &languageCode){    m_language = languageCode;}bool MetaTranslator::contains( const char *context, const char *sourceText,                               const char *comment ) const{    return mm.contains(MetaTranslatorMessage(context, sourceText, comment, QString(), 0));}MetaTranslatorMessage MetaTranslator::find( const char *context, const char *sourceText,                   const char *comment ) const{    QMap<MetaTranslatorMessage, int>::const_iterator it =         mm.constFind(MetaTranslatorMessage(context, sourceText, comment, QString(), 0));    return (it == mm.constEnd() ? MetaTranslatorMessage() : it.key());}MetaTranslatorMessage MetaTranslator::find(const char *context, const char *comment,                                 const QString &fileName, int lineNumber) const{    if (lineNumber >= 0 && !fileName.isEmpty()) {        MetaTranslatorMessage m;        for (QMap<MetaTranslatorMessage, int>::const_iterator it = mm.constBegin();            it != mm.constEnd(); ++it) {            m = it.key();            int delta = qstrcmp(m.context(), context);            if (delta == 0) {                delta = qstrcmp(m.comment(), comment);                if (delta == 0) {                    delta = QString::compare(m.fileName(), fileName);                    if (delta == 0) {                        delta = m.lineNumber() - lineNumber;                        if (delta == 0)                            return m;                    }                }            }        }    }    return MetaTranslatorMessage();}void MetaTranslator::insert( const MetaTranslatorMessage& m ){    int pos = mm.count();    if (mm.contains(m)) {        pos = mm.value(m);        mm.remove(m);    }    mm.insert(m, pos);}void MetaTranslator::stripObsoleteMessages(){    TMM newmm;    TMM::Iterator m = mm.begin();    while ( m != mm.end() ) {        if ( m.key().type() != MetaTranslatorMessage::Obsolete )            newmm.insert( m.key(), *m );        ++m;    }    mm = newmm;}void MetaTranslator::stripEmptyContexts(){    TMM newmm;    TMM::Iterator m = mm.begin();    while ( m != mm.end() ) {        if ( QByteArray(m.key().sourceText()) == ContextComment ) {            TMM::Iterator n = m;            ++n;            // the context comment is followed by other messages            if ( n != newmm.end() &&                 qstrcmp(m.key().context(), n.key().context()) == 0 )                newmm.insert( m.key(), *m );        } else {            newmm.insert( m.key(), *m );        }        ++m;    }    mm = newmm;}void MetaTranslator::makeFileNamesAbsolute(const QDir &oldPath){    TMM newmm;    for (TMM::iterator m = mm.begin(); m != mm.end(); ++m) {        MetaTranslatorMessage msg = m.key();        QString fileName = m.key().fileName();        QFileInfo fi (fileName);        if (fi.isRelative()) {            fileName = oldPath.absoluteFilePath(fileName);        }                msg.setFileName(fileName);        newmm.insert(msg, m.value());    }    mm = newmm;}void MetaTranslator::setCodec( const char *name ){    const int latin1 = 4;    codecName = name;    codec = QTextCodec::codecForName( name );    if ( codec == 0 || codec->mibEnum() == latin1 )        codec = 0;}QString MetaTranslator::toUnicode( const char *str, bool utf8 ) const{    if ( utf8 )        return QString::fromUtf8( str );    else if ( codec == 0 )        return QLatin1String( str );    else        return codec->toUnicode( str );}QList<MetaTranslatorMessage> MetaTranslator::messages() const{    int n = mm.count();    TMM::ConstIterator *t = new TMM::ConstIterator[n + 1];    TMM::ConstIterator m;    for ( m = mm.begin(); m != mm.end(); ++m )        t[*m] = m;    QList<MetaTranslatorMessage> val;    for ( int i = 0; i < n; i++ )        val.append( t[i].key() );    delete[] t;    return val;}QList<MetaTranslatorMessage> MetaTranslator::translatedMessages() const{    QList<MetaTranslatorMessage> val;    TMM::ConstIterator m;    for ( m = mm.begin(); m != mm.end(); ++m ) {        if ( m.key().type() == MetaTranslatorMessage::Finished )            val.append( m.key() );    }    return val;}// the grammatical numerus is the number of plural forms + singular forms.// i.e english has two forms: singular og plural.// and polish has three forms: // 1. singular (1), // 2. plural form 1 (numbers that ends with 2,3,4 except 12,13,14)// 3. plural form 2 (all others)// Thus, english returns 2, polish returns 3int MetaTranslator::grammaticalNumerus(QLocale::Language language, QLocale::Country country){    QStringList forms;    getNumerusInfo(language, country, 0, &forms);    return forms.count();}QStringList MetaTranslator::normalizedTranslations(const MetaTranslatorMessage& m,                                                    QLocale::Language language,                                                    QLocale::Country country){    QStringList translations = m.translations();    int numTranslations = 1;    if (m.isPlural() && language != QLocale::C) {        numTranslations = grammaticalNumerus(language, country);    }    // make sure that the stringlist always have the size of the language's current numerus, or 1 if its not plural    if (translations.count() > numTranslations) {        for (int i = translations.count(); i >  numTranslations; --i)            translations.removeLast();    } else if (translations.count() < numTranslations) {        for (int i = translations.count(); i < numTranslations; ++i)            translations << QString();    }    return translations;    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?