zoukankan      html  css  js  c++  java
  • QT的动态翻译功能,可能依赖于消息(事件)机制

    QTranslator translator;
    bool b = translator.load(QString(":/qm/lang_en"));
    以后,无论使用QObject的tr,还是使用QApplication的translate,都依赖于消息(事件)循环,有代码为证:

    QString QCoreApplication::translate(const char *context, const char *sourceText,
                                        const char *disambiguation, int n)
    {
        QString result;
    
        if (!sourceText)
            return result;
    
        if (self && !self->d_func()->translators.isEmpty()) {
            QList<QTranslator*>::ConstIterator it;
            QTranslator *translationFile;
            for (it = self->d_func()->translators.constBegin(); it != self->d_func()->translators.constEnd(); ++it) {
                translationFile = *it;
                result = translationFile->translate(context, sourceText, disambiguation, n);
                if (!result.isNull())
                    break;
            }
        }
    
        if (result.isNull())
            result = QString::fromUtf8(sourceText);
    
        replacePercentN(&result, n);
        return result;
    }
    
    static QString getMessage(const uchar *m, const uchar *end, const char *context,
                              const char *sourceText, const char *comment, uint numerus)
    {
        const uchar *tn = 0;
        uint tn_length = 0;
    
        for (;;) {
            uchar tag = 0;
            if (m < end)
                tag = read8(m++);
            switch((Tag)tag) {
            case Tag_End:
                goto end;
            case Tag_Translation: {
                int len = read32(m);
                if (len % 1)
                    return QString();
                m += 4;
                if (!numerus--) {
                    tn_length = len;
                    tn = m;
                }
                m += len;
                break;
            }
            case Tag_Obsolete1:
                m += 4;
                break;
            case Tag_SourceText: {
                quint32 len = read32(m);
                m += 4;
                if (!match(m, sourceText, len))
                    return QString();
                m += len;
            }
                break;
            case Tag_Context: {
                quint32 len = read32(m);
                m += 4;
                if (!match(m, context, len))
                    return QString();
                m += len;
            }
                break;
            case Tag_Comment: {
                quint32 len = read32(m);
                m += 4;
                if (*m && !match(m, comment, len))
                    return QString();
                m += len;
            }
                break;
            default:
                return QString();
            }
        }
    end:
        if (!tn)
            return QString();
        QString str = QString((const QChar *)tn, tn_length/2);
        if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
            for (int i = 0; i < str.length(); ++i)
                str[i] = QChar((str.at(i).unicode() >> 8) + ((str.at(i).unicode() << 8) & 0xff00));
        }
        return str;
    }
    
    QString QTranslatorPrivate::do_translate(const char *context, const char *sourceText,
                                             const char *comment, int n) const
    {
        if (context == 0)
            context = "";
        if (sourceText == 0)
            sourceText = "";
        if (comment == 0)
            comment = "";
    
        uint numerus = 0;
        size_t numItems = 0;
    
        if (!offsetLength)
            goto searchDependencies;
    
        /*
            Check if the context belongs to this QTranslator. If many
            translators are installed, this step is necessary.
        */
        if (contextLength) {
            quint16 hTableSize = read16(contextArray);
            uint g = elfHash(context) % hTableSize;
            const uchar *c = contextArray + 2 + (g << 1);
            quint16 off = read16(c);
            c += 2;
            if (off == 0)
                return QString();
            c = contextArray + (2 + (hTableSize << 1) + (off << 1));
    
            for (;;) {
                quint8 len = read8(c++);
                if (len == 0)
                    return QString();
                if (match(c, context, len))
                    break;
                c += len;
            }
        }
    
        numItems = offsetLength / (2 * sizeof(quint32));
        if (!numItems)
            goto searchDependencies;
    
        if (n >= 0)
            numerus = numerusHelper(n, numerusRulesArray, numerusRulesLength);
    
        for (;;) {
            quint32 h = 0;
            elfHash_continue(sourceText, h);
            elfHash_continue(comment, h);
            elfHash_finish(h);
    
            const uchar *start = offsetArray;
            const uchar *end = start + ((numItems-1) << 3);
            while (start <= end) {
                const uchar *middle = start + (((end - start) >> 4) << 3);
                uint hash = read32(middle);
                if (h == hash) {
                    start = middle;
                    break;
                } else if (hash < h) {
                    start = middle + 8;
                } else {
                    end = middle - 8;
                }
            }
    
            if (start <= end) {
                // go back on equal key
                while (start != offsetArray && read32(start) == read32(start-8))
                    start -= 8;
    
                while (start < offsetArray + offsetLength) {
                    quint32 rh = read32(start);
                    start += 4;
                    if (rh != h)
                        break;
                    quint32 ro = read32(start);
                    start += 4;
                    QString tn = getMessage(messageArray + ro, messageArray + messageLength, context,
                                            sourceText, comment, numerus);
                    if (!tn.isNull())
                        return tn;
                }
            }
            if (!comment[0])
                break;
            comment = "";
        }
    
    searchDependencies:
        foreach (QTranslator *translator, subTranslators) {
            QString tn = translator->translate(context, sourceText, comment, n);
            if (!tn.isNull())
                return tn;
        }
        return QString();
    }

    本来在GUI下使用好好的tr和translate函数,在QtService中再开线程就出了问题(在QtService中使用本身没有问题)

    解决方法:
    1. 自己读取翻译文件xml以后,用它做一个Map,供我自己随时动态把它的内容都查询出来
    2. 在每一个线程里申请一个Service,重新安装QTranslator,然后再使用tr或者translate函数(没试,不知道行不行)
    3. 把tr或者translate转发到执行exec()的那个全局service里去,相当于转到主事件循环里去,翻译完了再跳回来(没试,不知道行不行)

    官方参考文档:
    http://doc.qt.io/qt-5/i18n-source-translation.html

  • 相关阅读:
    C++编程中的小规范(转)
    windows的消息大全(收集)
    C中的一些好玩的事(一)转
    C++ 温故而知新(三)
    C++温故而知新(二)
    C++的内存分布(一)转
    C++ 温故而知新(一)
    C++反射机制模拟
    VS2010 下配置opeNGL遇到的问题
    SharedPreference.Editor的apply和commit方法异同
  • 原文地址:https://www.cnblogs.com/findumars/p/5506257.html
Copyright © 2011-2022 走看看