xliff.cpp

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

CPP
581
字号
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the Qt Linguist of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.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 GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "metatranslator.h"#include "xliff.h"#include <QtCore/QTextStream>#include <QtCore/QString>#include <QtCore/QFile>#include <QtCore/QTextCodec>#include <QtXml>#include <QtGui/QApplication>#include <QtGui/QMessageBox>/** * Implementation of XLIFF file format for Linguist */#define XLIFF11_PROFILE_PO_DRAFT#ifdef XLIFF11_PROFILE_PO_DRAFTstatic const char *restypeContext = "x-gettext-domain";static const char *restypePlurals = "x-gettext-plurals";static const char *dataTypeUIFile = "x-trolltech-designer-ui";static const char *contextNameLocation = "po-reference";    //###//static const char *contextTypeComment = "x-po-transcomment";#elsestatic const char *restypeContext = "x-trolltech-linguist-context";static const char *restypePlurals = "x-trolltech-linguist-plurals";static const char *dataTypeUIFile = "x-trolltech-designer-ui";static const char *contextNameLocation = "lineNo";#endifstatic const char *XLIFF11namespaceURI = "urn:oasis:names:tc:xliff:document:1.1";// try our best at XLIFF12 alsostatic const char *XLIFF12namespaceURI = "urn:oasis:names:tc:xliff:document:1.2";#define COMBINE4CHARS(c1, c2, c3, c4) \    (int(c1) << 24 | int(c2) << 16 | int(c3) << 8 | int(c4) )static QString dataType(const MetaTranslatorMessage &m){    QByteArray fileName = m.fileName().toAscii();    unsigned int extHash = 0;    int pos = fileName.count() - 1;    for (int pass = 0; pass < 4 && pos >=0; ++pass, --pos) {        if (fileName.at(pos) == '.')            break;        extHash |= ((int)fileName.at(pos) << (8*pass));    }    switch (extHash) {        case COMBINE4CHARS(0,'c','p','p'):        case COMBINE4CHARS(0,'c','x','x'):        case COMBINE4CHARS(0,'c','+','+'):        case COMBINE4CHARS(0,'h','p','p'):        case COMBINE4CHARS(0,'h','x','x'):        case COMBINE4CHARS(0,'h','+','+'):            return QLatin1String("cpp");        case COMBINE4CHARS(0, 0 , 0 ,'c'):        case COMBINE4CHARS(0, 0 , 0 ,'h'):        case COMBINE4CHARS(0, 0 ,'c','c'):        case COMBINE4CHARS(0, 0 ,'c','h'):        case COMBINE4CHARS(0, 0 ,'h','h'):            return QLatin1String("c");        case COMBINE4CHARS(0, 0 ,'u','i'):            return QLatin1String(dataTypeUIFile);   //### form?        default:            return QLatin1String("plaintext");      // we give up    }}static void writeIndent(QTextStream *t, int indent){    // ### slow (?)    for (int i = 0 ; i < indent; ++i) {        (*t) << " ";    }}struct CharMnemonic{    char ch;    char escape;    char *mnemonic;};static const CharMnemonic charCodeMnemonics[] = {    {0x07, 'a', "bel"},    {0x08, 'b', "bs"},    {0x09, 't', "tab"},    {0x0a, 'n', "lf"},    {0x0b, 'v', "vt"},    {0x0c, 'f', "ff"},    {0x0d, 'r', "cr"}};static char charFromEscape(char escape){    for (uint i = 0; i < sizeof(charCodeMnemonics)/sizeof(CharMnemonic); ++i) {        CharMnemonic cm =  charCodeMnemonics[i];        if (cm.escape == escape) return cm.ch;    }    Q_ASSERT(0);    return escape;}static QString numericEntity( int ch ){    QString name;    char escapechar;        // ### This needs to be reviewed, to reflect the updated XLIFF-PO spec.    if (ch >= 7 && ch <= 0x0d)    {        CharMnemonic cm = charCodeMnemonics[int(ch) - 7];        name = QLatin1String(cm.mnemonic);        escapechar = cm.escape;        static int id = 0;        return QString::fromAscii("<ph id=\"ph%1\" ctype=\"x-ch-%2\">\\%3</ph>")                                .arg(++id)                                .arg(name)                                .arg(escapechar);    } else {        return QString::fromAscii("&#x%1;").arg(QString::number(ch, 16));    }}static QString protect( const QByteArray& str ){    QString result;    int len = (int) str.length();    for ( int k = 0; k < len; k++ ) {        switch( str[k] ) {        case '\"':            result += QLatin1String( "&quot;" );            break;        case '&':            result += QLatin1String( "&amp;" );            break;        case '>':            result += QLatin1String( "&gt;" );            break;        case '<':            result += QLatin1String( "&lt;" );            break;        case '\'':            result += QLatin1String( "&apos;" );            break;        default:            if ( (uchar) str[k] < 0x20 )                result += numericEntity( (uchar) str[k] );            else                result += QLatin1Char(str[k]);        }    }    return result;}static QString evilBytes( const QByteArray& str, bool utf8 ){    if ( utf8 ) {        return protect( str );    } else {        QString result;        QByteArray t = protect( str ).toLatin1();        int len = (int) t.length();        for ( int k = 0; k < len; k++ ) {            if ( (uchar) t[k] >= 0x7f )                result += numericEntity( (uchar) t[k] );            else                result += QLatin1Char( t[k] );        }        return result;    }}static void writeLineNumber(QTextStream *t, const MetaTranslatorMessage &msg, int indent){    if (msg.lineNumber() != -1) {        writeIndent(t, indent);        (*t) << "<context-group name=\"" << contextNameLocation << "\" purpose=\"location\"><context context-type=\"linenumber\">"             << msg.lineNumber() << "</context></context-group>\n";    }}static void writeComment(QTextStream *t, const MetaTranslatorMessage &msg, int indent){    if (msg.comment() && qstrlen(msg.comment())) {        writeIndent(t, indent);        (*t) << "<note>" << msg.comment() << "</note>\n";    }}static void writeTransUnit(QTextStream *t, const MetaTranslatorMessage &msg, int msgid,                            int indent, const QString &translation = QString()){    static int plural = 0;    static int prevMsgId = -1;    writeIndent(t, indent);    (*t) << "<trans-unit id=\"msg";    QString strid;    QByteArray transl;    if (msg.isPlural()) {        if (prevMsgId != msgid)             plural = 0;        strid = QString::fromAscii("%1[%2]").arg(msgid).arg(plural);        ++plural;        transl = translation.toUtf8();    } else {        strid = QString::fromAscii("%1").arg(msgid);        plural = 0;        transl = msg.translation().toUtf8();    }    prevMsgId = msgid;    (*t) << strid << "\"";    QString state;    indent+=2;    if (msg.type() == MetaTranslatorMessage::Obsolete) {        (*t) << " translate=\"no\"";    } else {        state = msg.type() == MetaTranslatorMessage::Finished             ? QLatin1String("final") : QLatin1String("new");        state = QString::fromAscii(" state=\"%1\"").arg(state);    }    (*t) << ">\n";    writeIndent(t, indent);    (*t) << "<source xml:space=\"preserve\">" << evilBytes(msg.sourceText(), msg.utf8()) << "</source>\n";        writeIndent(t, indent);    (*t) << "<target xml:space=\"preserve\"" << state << ">" << evilBytes(transl, msg.utf8()) << "</target>\n";    // ### In XLIFF 1.1, name is marked as required, and it must be unique    // This is questionable behaviour, and was brought up at the xliff-comments mailinglist.    if (!msg.isPlural()) {        writeLineNumber(t, msg, indent);        writeComment(t, msg, indent);    }    indent-=2;    writeIndent(t, indent);    (*t) << "</trans-unit>\n";}static void writeMessage(QTextStream *t, const MetaTranslatorMessage &msg, int indent,                          const QString &languageCode){    static int msgid = 1;    if (msg.isPlural()) {        writeIndent(t, indent);        (*t) << "<group restype=\"" << restypePlurals << "\">\n";        indent+=2;        writeLineNumber(t, msg, indent);        writeComment(t, msg, indent);                QLocale::Language l;        QLocale::Country c;        MetaTranslator::languageAndCountry(languageCode, &l, &c);        QStringList translns = MetaTranslator::normalizedTranslations(msg, l, c);        for (int j = 0; j < qMax(1, translns.count()); ++j) {            writeTransUnit(t, msg, msgid, indent, translns.at(j));

⌨️ 快捷键说明

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