您的位置:首页 > 编程语言 > Qt开发

QT的动态翻译功能,可能依赖于消息(事件)机制

2016-05-18 19:01 549 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: