Changeset 561 for trunk/tools/linguist/shared/translator.cpp
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/tools/linguist/shared/translator.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the Qt Linguist of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 46 46 #include <stdio.h> 47 47 48 #include <QtCore/QCoreApplication>49 48 #include <QtCore/QDebug> 50 49 #include <QtCore/QDir> … … 58 57 QT_BEGIN_NAMESPACE 59 58 59 #ifdef QT_BOOTSTRAPPED 60 QString QObject::tr(const char *sourceText, const char *, int n) 61 { 62 QString ret = QString::fromLatin1(sourceText); 63 if (n >= 0) 64 ret.replace(QLatin1String("%n"), QString::number(n)); 65 return ret; 66 } 67 #endif 68 60 69 Translator::Translator() : 61 m_codec Name("ISO-8859-1"),70 m_codec(QTextCodec::codecForName("ISO-8859-1")), 62 71 m_locationsType(AbsoluteLocations) 63 72 { … … 82 91 } 83 92 84 void Translator::replace(const TranslatorMessage &msg)85 {86 int index = m_messages.indexOf(msg);87 if (index == -1)88 m_messages.append(msg);89 else90 m_messages[index] = msg;91 }92 93 93 void Translator::replaceSorted(const TranslatorMessage &msg) 94 94 { 95 int index = m_messages.indexOf(msg);95 int index = find(msg); 96 96 if (index == -1) 97 97 appendSorted(msg); … … 102 102 void Translator::extend(const TranslatorMessage &msg) 103 103 { 104 int index = m_messages.indexOf(msg);104 int index = find(msg); 105 105 if (index == -1) { 106 106 m_messages.append(msg); … … 147 147 int curIdx = 0; 148 148 foreach (const TranslatorMessage &mit, m_messages) { 149 bool sameFile = mit.fileName() == msg.fileName() ;149 bool sameFile = mit.fileName() == msg.fileName() && mit.context() == msg.context(); 150 150 int curLine; 151 151 if (sameFile && (curLine = mit.lineNumber()) >= prevLine) { … … 313 313 } 314 314 315 bool Translator::contains(const QString &context, 316 const QString &sourceText, const QString &comment) const 317 { 318 return m_messages.contains(TranslatorMessage(context, sourceText, comment, 319 QString(), QString(), 0)); 320 } 321 322 TranslatorMessage Translator::find(const QString &context, 323 const QString &sourceText, const QString &comment) const 324 { 325 TranslatorMessage needle(context, sourceText, comment, QString(), QString(), 0); 326 int index = m_messages.indexOf(needle); 327 return index == -1 ? TranslatorMessage() : m_messages.at(index); 315 int Translator::find(const TranslatorMessage &msg) const 316 { 317 for (int i = 0; i < m_messages.count(); ++i) { 318 const TranslatorMessage &tmsg = m_messages.at(i); 319 if (msg.id().isEmpty() || tmsg.id().isEmpty()) { 320 if (msg.context() == tmsg.context() 321 && msg.sourceText() == tmsg.sourceText() 322 && msg.comment() == tmsg.comment()) 323 return i; 324 } else { 325 if (msg.id() == tmsg.id()) 326 return i; 327 } 328 } 329 return -1; 328 330 } 329 331 … … 346 348 { 347 349 foreach (const TranslatorMessage &msg, m_messages) 348 if (msg.context() == context && msg.sourceText().isEmpty() )350 if (msg.context() == context && msg.sourceText().isEmpty() && msg.id().isEmpty()) 349 351 return true; 350 352 return false; … … 354 356 { 355 357 foreach (const TranslatorMessage &msg, m_messages) 356 if (msg.context() == context && msg.sourceText().isEmpty() )358 if (msg.context() == context && msg.sourceText().isEmpty() && msg.id().isEmpty()) 357 359 return msg; 358 360 return TranslatorMessage(); … … 417 419 } 418 420 419 QSet<TranslatorMessagePtr> Translator::resolveDuplicates() 420 { 421 QSet<TranslatorMessagePtr> dups; 422 QHash<TranslatorMessagePtr, int> refs; 421 void Translator::dropUiLines() 422 { 423 QString uiXt = QLatin1String(".ui"); 424 QString juiXt = QLatin1String(".jui"); 425 for (TMM::Iterator it = m_messages.begin(); it != m_messages.end(); ++it) { 426 QHash<QString, int> have; 427 QList<TranslatorMessage::Reference> refs; 428 foreach (const TranslatorMessage::Reference &itref, it->allReferences()) { 429 const QString &fn = itref.fileName(); 430 if (fn.endsWith(uiXt) || fn.endsWith(juiXt)) { 431 if (++have[fn] == 1) 432 refs.append(TranslatorMessage::Reference(fn, -1)); 433 } else { 434 refs.append(itref); 435 } 436 } 437 it->setReferences(refs); 438 } 439 } 440 441 struct TranslatorMessageIdPtr { 442 explicit TranslatorMessageIdPtr(const TranslatorMessage &tm) 443 { 444 ptr = &tm; 445 } 446 447 inline const TranslatorMessage *operator->() const 448 { 449 return ptr; 450 } 451 452 const TranslatorMessage *ptr; 453 }; 454 455 Q_DECLARE_TYPEINFO(TranslatorMessageIdPtr, Q_MOVABLE_TYPE); 456 457 inline int qHash(TranslatorMessageIdPtr tmp) 458 { 459 return qHash(tmp->id()); 460 } 461 462 inline bool operator==(TranslatorMessageIdPtr tmp1, TranslatorMessageIdPtr tmp2) 463 { 464 return tmp1->id() == tmp2->id(); 465 } 466 467 struct TranslatorMessageContentPtr { 468 explicit TranslatorMessageContentPtr(const TranslatorMessage &tm) 469 { 470 ptr = &tm; 471 } 472 473 inline const TranslatorMessage *operator->() const 474 { 475 return ptr; 476 } 477 478 const TranslatorMessage *ptr; 479 }; 480 481 Q_DECLARE_TYPEINFO(TranslatorMessageContentPtr, Q_MOVABLE_TYPE); 482 483 inline int qHash(TranslatorMessageContentPtr tmp) 484 { 485 int hash = qHash(tmp->context()) ^ qHash(tmp->sourceText()); 486 if (!tmp->sourceText().isEmpty()) 487 // Special treatment for context comments (empty source). 488 hash ^= qHash(tmp->comment()); 489 return hash; 490 } 491 492 inline bool operator==(TranslatorMessageContentPtr tmp1, TranslatorMessageContentPtr tmp2) 493 { 494 if (tmp1->context() != tmp2->context() || tmp1->sourceText() != tmp2->sourceText()) 495 return false; 496 // Special treatment for context comments (empty source). 497 if (tmp1->sourceText().isEmpty()) 498 return true; 499 return tmp1->comment() == tmp2->comment(); 500 } 501 502 Translator::Duplicates Translator::resolveDuplicates() 503 { 504 Duplicates dups; 505 QHash<TranslatorMessageIdPtr, int> idRefs; 506 QHash<TranslatorMessageContentPtr, int> contentRefs; 423 507 for (int i = 0; i < m_messages.count();) { 424 508 const TranslatorMessage &msg = m_messages.at(i); 425 QHash<TranslatorMessagePtr, int>::ConstIterator it = refs.constFind(msg); 426 if (it != refs.constEnd()) { 427 TranslatorMessage &omsg = m_messages[*it]; 428 if (omsg.isUtf8() != msg.isUtf8() && !omsg.isNonUtf8()) { 429 // Dual-encoded message 430 omsg.setUtf8(true); 431 omsg.setNonUtf8(true); 432 } else { 433 // Duplicate 434 dups.insert(omsg); 509 TranslatorMessage *omsg; 510 int oi; 511 QSet<int> *pDup; 512 if (!msg.id().isEmpty()) { 513 QHash<TranslatorMessageIdPtr, int>::ConstIterator it = 514 idRefs.constFind(TranslatorMessageIdPtr(msg)); 515 if (it != idRefs.constEnd()) { 516 oi = *it; 517 omsg = &m_messages[oi]; 518 pDup = &dups.byId; 519 goto gotDupe; 435 520 } 436 if (!omsg.isTranslated() && msg.isTranslated()) 437 omsg.setTranslations(msg.translations()); 438 m_messages.removeAt(i); 521 } 522 { 523 QHash<TranslatorMessageContentPtr, int>::ConstIterator it = 524 contentRefs.constFind(TranslatorMessageContentPtr(msg)); 525 if (it != contentRefs.constEnd()) { 526 oi = *it; 527 omsg = &m_messages[oi]; 528 if (msg.id().isEmpty() || omsg->id().isEmpty()) { 529 if (!msg.id().isEmpty() && omsg->id().isEmpty()) { 530 omsg->setId(msg.id()); 531 idRefs[TranslatorMessageIdPtr(*omsg)] = oi; 532 } 533 pDup = &dups.byContents; 534 goto gotDupe; 535 } 536 // This is really a content dupe, but with two distinct IDs. 537 } 538 } 539 if (!msg.id().isEmpty()) 540 idRefs[TranslatorMessageIdPtr(msg)] = i; 541 contentRefs[TranslatorMessageContentPtr(msg)] = i; 542 ++i; 543 continue; 544 gotDupe: 545 if (omsg->isUtf8() != msg.isUtf8() && !omsg->isNonUtf8()) { 546 // Dual-encoded message 547 omsg->setUtf8(true); 548 omsg->setNonUtf8(true); 439 549 } else { 440 refs[msg] = i; 441 ++i; 442 } 550 // Duplicate 551 pDup->insert(oi); 552 } 553 if (!omsg->isTranslated() && msg.isTranslated()) 554 omsg->setTranslations(msg.translations()); 555 m_messages.removeAt(i); 443 556 } 444 557 return dups; 445 558 } 446 559 447 void Translator::reportDuplicates(const QSet<TranslatorMessagePtr>&dupes,560 void Translator::reportDuplicates(const Duplicates &dupes, 448 561 const QString &fileName, bool verbose) 449 562 { 450 if (!dupes. isEmpty()) {563 if (!dupes.byId.isEmpty() || !dupes.byContents.isEmpty()) { 451 564 if (!verbose) { 452 565 qWarning("Warning: dropping duplicate messages in '%s'\n(try -verbose for more info).", … … 454 567 } else { 455 568 qWarning("Warning: dropping duplicate messages in '%s':", qPrintable(fileName)); 456 foreach (const TranslatorMessagePtr &msg, dupes) { 569 foreach (int i, dupes.byId) 570 qWarning("\n* ID: %s", qPrintable(message(i).id())); 571 foreach (int j, dupes.byContents) { 572 const TranslatorMessage &msg = message(j); 457 573 qWarning("\n* Context: %s\n* Source: %s", 458 qPrintable(msg ->context()),459 qPrintable(msg ->sourceText()));460 if (!msg ->comment().isEmpty())461 qWarning("* Comment: %s", qPrintable(msg ->comment()));574 qPrintable(msg.context()), 575 qPrintable(msg.sourceText())); 576 if (!msg.comment().isEmpty()) 577 qWarning("* Comment: %s", qPrintable(msg.comment())); 462 578 } 463 579 qWarning(); … … 499 615 } 500 616 501 QStringList Translator::normalizedTranslations(const TranslatorMessage &msg, 502 QLocale::Language language, QLocale::Country country) 617 QStringList Translator::normalizedTranslations(const TranslatorMessage &msg, int numPlurals) 503 618 { 504 619 QStringList translations = msg.translations(); 505 int numTranslations = 1; 506 if (msg.isPlural() && language != QLocale::C) { 507 QStringList forms; 508 if (getNumerusInfo(language, country, 0, &forms)) 509 numTranslations = forms.count(); // includes singular 510 } 620 int numTranslations = msg.isPlural() ? numPlurals : 1; 511 621 512 622 // make sure that the stringlist always have the size of the … … 522 632 } 523 633 524 QStringList Translator::normalizedTranslations(const TranslatorMessage &msg, 525 ConversionData &cd, bool *ok) const 526 { 634 void Translator::normalizeTranslations(ConversionData &cd) 635 { 636 bool truncated = false; 527 637 QLocale::Language l; 528 638 QLocale::Country c; 529 639 languageAndCountry(languageCode(), &l, &c); 530 QStringList translns = normalizedTranslations(msg, l, c); 531 if (msg.translations().size() > translns.size() && ok) { 640 int numPlurals = 1; 641 if (l != QLocale::C) { 642 QStringList forms; 643 if (getNumerusInfo(l, c, 0, &forms)) 644 numPlurals = forms.count(); // includes singular 645 } 646 for (int i = 0; i < m_messages.count(); ++i) { 647 const TranslatorMessage &msg = m_messages.at(i); 648 QStringList tlns = msg.translations(); 649 int ccnt = msg.isPlural() ? numPlurals : 1; 650 if (tlns.count() != ccnt) { 651 while (tlns.count() < ccnt) 652 tlns.append(QString()); 653 while (tlns.count() > ccnt) { 654 tlns.removeLast(); 655 truncated = true; 656 } 657 TranslatorMessage msg2(msg); 658 msg2.setTranslations(tlns); 659 m_messages[i] = msg2; 660 } 661 } 662 if (truncated) 532 663 cd.appendError(QLatin1String( 533 664 "Removed plural forms as the target language has less " 534 665 "forms.\nIf this sounds wrong, possibly the target language is " 535 666 "not set or recognized.\n")); 536 *ok = false;537 }538 return translns;539 667 } 540 668 … … 586 714 if (!name.isEmpty()) 587 715 qWarning("No QTextCodec for %s available. Using Latin1\n", name.constData()); 588 m_codec Name = "ISO-8859-1";716 m_codec = QTextCodec::codecForName("ISO-8859-1"); 589 717 } else { 590 m_codecName = codec->name(); 591 } 718 m_codec = codec; 719 } 720 } 721 722 QByteArray Translator::codecName() const 723 { 724 return m_codec->name(); 592 725 } 593 726
Note:
See TracChangeset
for help on using the changeset viewer.