QT的动态翻译功能,可能依赖于消息(事件)机制
Posted 朝闻道
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
以上是关于QT的动态翻译功能,可能依赖于消息(事件)机制的主要内容,如果未能解决你的问题,请参考以下文章
Qt事件机制(是动作发生后,一种通知对象的消息,是被动与主动的总和。先处理自己队列中的消息,然后再处理系统消息队列中的消息)