Changeset 846 for trunk/tools/linguist


Ignore:
Timestamp:
May 5, 2011, 5:36:53 AM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

Location:
trunk
Files:
84 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/tools/linguist/lconvert/main.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4646#include <QtCore/QString>
    4747#include <QtCore/QStringList>
     48#include <QtCore/QTranslator>
     49#include <QtCore/QLibraryInfo>
    4850
    4951#include <iostream>
     52
     53QT_USE_NAMESPACE
     54
     55class LC {
     56    Q_DECLARE_TR_FUNCTIONS(LConvert)
     57};
    5058
    5159static int usage(const QStringList &args)
     
    5866        loaders += line.arg(format.extension, -5).arg(format.description);
    5967
    60     std::cerr << qPrintable(QString(QLatin1String("\nUsage:\n"
     68    std::cerr << qPrintable(LC::tr("\nUsage:\n"
    6169        "    lconvert [options] <infile> [<infile>...]\n\n"
    6270        "lconvert is part of Qt's Linguist tool chain. It can be used as a\n"
     
    120128        "    1 on command line parse failures\n"
    121129        "    2 on read failures\n"
    122         "    3 on write failures\n")).arg(loaders));
     130        "    3 on write failures\n").arg(loaders));
    123131    return 1;
    124132}
     
    133141{
    134142    QCoreApplication app(argc, argv);
     143#ifndef Q_OS_WIN32
     144    QTranslator translator;
     145    QTranslator qtTranslator;
     146    QString sysLocale = QLocale::system().name();
     147    QString resourceDir = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
     148    if (translator.load(QLatin1String("linguist_") + sysLocale, resourceDir)
     149        && qtTranslator.load(QLatin1String("qt_") + sysLocale, resourceDir)) {
     150        app.installTranslator(&translator);
     151        app.installTranslator(&qtTranslator);
     152    }
     153#endif // Q_OS_WIN32
     154
    135155    QStringList args = app.arguments();
    136 
    137156    QList<File> inFiles;
    138157    QString inFormat(QLatin1String("auto"));
     
    239258
    240259    if (!tr.load(inFiles[0].name, cd, inFiles[0].format)) {
    241         qWarning() << qPrintable(cd.error());
     260        std::cerr << qPrintable(cd.error());
    242261        return 2;
    243262    }
     
    247266        Translator tr2;
    248267        if (!tr2.load(inFiles[i].name, cd, inFiles[i].format)) {
    249             qWarning() << qPrintable(cd.error());
     268            std::cerr << qPrintable(cd.error());
    250269            return 2;
    251270        }
     
    272291    tr.normalizeTranslations(cd);
    273292    if (!cd.errors().isEmpty()) {
    274         qWarning("%s", qPrintable(cd.error()));
     293        std::cerr << qPrintable(cd.error());
    275294        cd.clearErrors();
    276295    }
    277296    if (!tr.save(outFileName, cd, outFormat)) {
    278         qWarning("%s", qPrintable(cd.error()));
     297        std::cerr << qPrintable(cd.error());
    279298        return 3;
    280299    }
  • trunk/tools/linguist/linguist.pro

    r769 r846  
    11TEMPLATE = subdirs
    22SUBDIRS  = \
    3     linguist \
    43    lrelease \
    54    lupdate \
    65    lconvert
     6!no-png:!contains(QT_CONFIG, no-gui):SUBDIRS += linguist
  • trunk/tools/linguist/linguist/batchtranslation.ui

    r651 r846  
    33 <comment>*********************************************************************
    44**
    5 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     5** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    66** All rights reserved.
    77** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/batchtranslationdialog.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/batchtranslationdialog.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/errorsview.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/errorsview.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/finddialog.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/finddialog.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/finddialog.ui

    r651 r846  
    33 <comment>*********************************************************************
    44**
    5 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     5** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    66** All rights reserved.
    77** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/formpreviewview.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/formpreviewview.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/globals.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/globals.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/linguist.pro

    r769 r846  
    1010
    1111DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII
    12 build_all:!build_pass { 
     12build_all:!build_pass {
    1313    CONFIG -= build_all
    1414    CONFIG += release
     
    4343    translatedialog.cpp \
    4444    translationsettingsdialog.cpp \
    45     ../shared/simtexth.cpp 
     45    ../shared/simtexth.cpp
    4646
    4747HEADERS += \
     
    7373win32:RC_FILE = linguist.rc
    7474os2:RC_FILE = linguist_os2.rc
    75 mac { 
     75mac {
    7676    static:CONFIG -= global_init_link_order
    7777    ICON = linguist.icns
     
    9797RESOURCES += linguist.qrc
    9898
    99 TR_DIR = $$PWD/../../../translations
    100 TRANSLATIONS = \
    101     $$TR_DIR/linguist_cs.ts \
    102     $$TR_DIR/linguist_de.ts \
    103     $$TR_DIR/linguist_fr.ts \
    104     $$TR_DIR/linguist_ja.ts \
    105     $$TR_DIR/linguist_pl.ts \
    106     $$TR_DIR/linguist_ru.ts \
    107     $$TR_DIR/linguist_zh_CN.ts \
    108     $$TR_DIR/linguist_zh_TW.ts
    109 
    11099include(../../../src/qt_targets.pri)
  • trunk/tools/linguist/linguist/linguist.rc

    r651 r846  
    1919            VALUE "FileDescription", "Qt Linguist"
    2020            VALUE "FileVersion", "1.0.0.0"
    21             VALUE "LegalCopyright", "Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)."
     21            VALUE "LegalCopyright", "Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)."
    2222            VALUE "InternalName", "linguist"
    2323            VALUE "OriginalFilename", "linguist.exe"
  • trunk/tools/linguist/linguist/main.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/mainwindow.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    143143    case 0x2049: // exclamation question mark
    144144    case 0x2762: // heavy exclamation mark ornament
     145    case 0xff01: // full width exclamation mark
     146    case 0xff1f: // full width question mark
    145147        return End_Interrobang;
    146148    case 0x003b: // greek 'compatibility' questionmark
    147149        return lang == QLocale::Greek ? End_Interrobang : End_None;
    148150    case 0x003a: // colon
     151    case 0xff1a: // full width colon
    149152        return End_Colon;
    150153    case 0x2026: // horizontal ellipsis
     
    10361039                        if (searchItem(m->extraComment()))
    10371040                            break;
     1041                        if (searchItem(m->translatorComment()))
     1042                            break;
    10381043                        m_foundWhere = DataModel::NoLocation;
    10391044                        // did not find the search string in this message
     
    13581363        << (QT_VERSION & 0xFF)
    13591364        << QLatin1String("/qdoc/linguist-manual.html")
    1360         << QLatin1Char('\0') << endl;
     1365        << QLatin1Char('\n') << endl;
    13611366}
    13621367
     
    13711376                    "<p>Qt Linguist is a tool for adding translations to Qt "
    13721377                    "applications.</p>"
    1373                     "<p>Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)."
     1378                    "<p>Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)."
    13741379                   ).arg(version));
    13751380
     
    15281533            m_phraseView->setSourceText(-1, QString());
    15291534        }
    1530         if (m) {
     1535        if (m && !m->fileName().isEmpty()) {
    15311536            if (hasFormPreview(m->fileName())) {
    15321537                m_sourceAndFormView->setCurrentWidget(m_formPreviewView);
     
    15831588
    15841589    m->setTranslations(translations);
    1585     if (hasFormPreview(m->fileName()))
     1590    if (!m->fileName().isEmpty() && hasFormPreview(m->fileName()))
    15861591        m_formPreviewView->setSourceContext(m_currentIndex.model(), m);
    15871592    updateDanger(m_currentIndex, true);
     
    18211826}
    18221827
     1828static inline void setThemeIcon(QAction *action, const char *name, const char *fallback)
     1829{
     1830    const QIcon fallbackIcon(MainWindow::resourcePrefix() + QLatin1String(fallback));
     1831#ifdef Q_WS_X11
     1832    action->setIcon(QIcon::fromTheme(QLatin1String(name), fallbackIcon));
     1833#else
     1834    Q_UNUSED(name)
     1835    action->setIcon(fallbackIcon);
     1836#endif
     1837}
     1838
    18231839void MainWindow::setupMenuBar()
    18241840{
     1841    // There are no fallback icons for these
     1842#ifdef Q_WS_X11
     1843    m_ui.menuRecentlyOpenedFiles->setIcon(QIcon::fromTheme(QLatin1String("document-open-recent")));
     1844    m_ui.actionCloseAll->setIcon(QIcon::fromTheme(QLatin1String("window-close")));
     1845    m_ui.actionExit->setIcon(QIcon::fromTheme(QLatin1String("application-exit")));
     1846    m_ui.actionSelectAll->setIcon(QIcon::fromTheme(QLatin1String("edit-select-all")));
     1847#endif
     1848
     1849    // Prefer theme icons when available for these actions
     1850    setThemeIcon(m_ui.actionOpen, "document-open", "/fileopen.png");
     1851    setThemeIcon(m_ui.actionOpenAux, "document-open", "/fileopen.png");
     1852    setThemeIcon(m_ui.actionSave, "document-save", "/filesave.png");
     1853    setThemeIcon(m_ui.actionSaveAll, "document-save", "/filesave.png");
     1854    setThemeIcon(m_ui.actionPrint, "document-print", "/print.png");
     1855    setThemeIcon(m_ui.actionRedo, "edit-redo", "/redo.png");
     1856    setThemeIcon(m_ui.actionUndo, "edit-undo", "/undo.png");
     1857    setThemeIcon(m_ui.actionCut, "edit-cut", "/editcut.png");
     1858    setThemeIcon(m_ui.actionCopy, "edit-copy", "/editcopy.png");
     1859    setThemeIcon(m_ui.actionPaste, "edit-paste", "/editpaste.png");
     1860    setThemeIcon(m_ui.actionFind, "edit-find", "/searchfind.png");
     1861
     1862    // No well defined theme icons for these actions
    18251863    m_ui.actionAccelerators->setIcon(QIcon(resourcePrefix() + QLatin1String("/accelerator.png")));
    18261864    m_ui.actionOpenPhraseBook->setIcon(QIcon(resourcePrefix() + QLatin1String("/book.png")));
    18271865    m_ui.actionDoneAndNext->setIcon(QIcon(resourcePrefix() + QLatin1String("/doneandnext.png")));
    1828     m_ui.actionCopy->setIcon(QIcon(resourcePrefix() + QLatin1String("/editcopy.png")));
    1829     m_ui.actionCut->setIcon(QIcon(resourcePrefix() + QLatin1String("/editcut.png")));
    1830     m_ui.actionPaste->setIcon(QIcon(resourcePrefix() + QLatin1String("/editpaste.png")));
    1831     m_ui.actionOpen->setIcon(QIcon(resourcePrefix() + QLatin1String("/fileopen.png")));
    1832     m_ui.actionOpenAux->setIcon(QIcon(resourcePrefix() + QLatin1String("/fileopen.png")));
    1833     m_ui.actionSaveAll->setIcon(QIcon(resourcePrefix() + QLatin1String("/filesave.png")));
    1834     m_ui.actionSave->setIcon(QIcon(resourcePrefix() + QLatin1String("/filesave.png")));
    18351866    m_ui.actionNext->setIcon(QIcon(resourcePrefix() + QLatin1String("/next.png")));
    18361867    m_ui.actionNextUnfinished->setIcon(QIcon(resourcePrefix() + QLatin1String("/nextunfinished.png")));
     
    18391870    m_ui.actionPrev->setIcon(QIcon(resourcePrefix() + QLatin1String("/prev.png")));
    18401871    m_ui.actionPrevUnfinished->setIcon(QIcon(resourcePrefix() + QLatin1String("/prevunfinished.png")));
    1841     m_ui.actionPrint->setIcon(QIcon(resourcePrefix() + QLatin1String("/print.png")));
    1842     m_ui.actionRedo->setIcon(QIcon(resourcePrefix() + QLatin1String("/redo.png")));
    1843     m_ui.actionFind->setIcon(QIcon(resourcePrefix() + QLatin1String("/searchfind.png")));
    1844     m_ui.actionUndo->setIcon(QIcon(resourcePrefix() + QLatin1String("/undo.png")));
    18451872    m_ui.actionPlaceMarkerMatches->setIcon(QIcon(resourcePrefix() + QLatin1String("/validateplacemarkers.png")));
    18461873    m_ui.actionWhatsThis->setIcon(QIcon(resourcePrefix() + QLatin1String("/whatsthis.png")));
     
    19802007        if (m_currentIndex.isValid()) {
    19812008            if (MessageItem *item = m_dataModel->messageItem(m_currentIndex)) {
    1982                 if (hasFormPreview(item->fileName()))
     2009                if (!item->fileName().isEmpty() && hasFormPreview(item->fileName()))
    19832010                    m_formPreviewView->setSourceContext(model, item);
    19842011                if (enableRw && !item->isObsolete())
     
    23812408            if (c != '&' && c != ' ' && QChar(c).isPrint()) {
    23822409                const ushort *pp = p;
    2383                 for (; *p < 256 && ::isalpha(*p); p++) ;
     2410                for (; *p < 256 && isalpha(*p); p++) ;
    23842411                if (pp == p || *p != ';')
    23852412                    return true;
     
    24822509
    24832510            if (m_ui.actionPlaceMarkerMatches->isChecked()) {
    2484                 // Stores the occurence count of the place markers in the map placeMarkerIndexes.
    2485                 // i.e. the occurence count of %1 is stored at placeMarkerIndexes[1],
     2511                // Stores the occurrence count of the place markers in the map placeMarkerIndexes.
     2512                // i.e. the occurrence count of %1 is stored at placeMarkerIndexes[1],
    24862513                // count of %2 is stored at placeMarkerIndexes[2] etc.
    24872514                // In the first pass, it counts all place markers in the sourcetext.
  • trunk/tools/linguist/linguist/mainwindow.h

    r663 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/mainwindow.ui

    r651 r846  
    33 <comment>*********************************************************************
    44**
    5 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     5** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    66** All rights reserved.
    77** Contact: Nokia Corporation (qt-info@nokia.com)
     
    680680   </property>
    681681   <property name="whatsThis">
    682     <string>Display information about the Qt toolkit by Trolltech.</string>
     682    <string>Display information about the Qt toolkit by Nokia.</string>
    683683   </property>
    684684   <property name="menuRole">
  • trunk/tools/linguist/linguist/messageeditor.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/messageeditor.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/messageeditorwidgets.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/messageeditorwidgets.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/messagehighlighter.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/messagehighlighter.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/messagemodel.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    210210    }
    211211
     212    if (!tor.messageCount()) {
     213        QMessageBox::warning(parent, QObject::tr("Qt Linguist"),
     214                             tr("The translation file '%1' will not be loaded because it is empty.")
     215                             .arg(Qt::escape(fileName)));
     216        return false;
     217    }
     218
    212219    Translator::Duplicates dupes = tor.resolveDuplicates();
    213220    if (!dupes.byId.isEmpty() || !dupes.byContents.isEmpty()) {
     
    403410        lang = QLocale::English;
    404411    QByteArray rules;
    405     bool ok = getNumerusInfo(lang, country, &rules, &m_numerusForms);
     412    bool ok = getNumerusInfo(lang, country, &rules, &m_numerusForms, 0);
    406413    m_localizedLanguage = QCoreApplication::translate("MessageEditor", QLocale::languageToString(lang).toAscii());
    407414    m_countRefNeeds.clear();
  • trunk/tools/linguist/linguist/messagemodel.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/phrase.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    189189{
    190190    if (ferrorCount++ == 0) {
    191         QString msg;
    192         msg.sprintf("Parse error at line %d, column %d (%s).",
    193             exception.lineNumber(), exception.columnNumber(),
    194             exception.message().toLatin1().constData());
     191        QString msg = PhraseBook::tr("Parse error at line %1, column %2 (%3).")
     192            .arg(exception.lineNumber()).arg(exception.columnNumber())
     193            .arg(exception.message());
    195194        QMessageBox::information(0,
    196195            QObject::tr("Qt Linguist"), msg);
  • trunk/tools/linguist/linguist/phrase.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/phrasebookbox.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/phrasebookbox.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/phrasebookbox.ui

    r651 r846  
    33 <comment>*********************************************************************
    44**
    5 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     5** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    66** All rights reserved.
    77** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/phrasemodel.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/phrasemodel.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/phraseview.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/phraseview.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/printout.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    133133}
    134134
    135 // use init if inital vsize should be calculated (first breakPage call)
     135// use init if initial vsize should be calculated (first breakPage call)
    136136void PrintOut::breakPage(bool init)
    137137{
  • trunk/tools/linguist/linguist/printout.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/recentfiles.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/recentfiles.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/sourcecodeview.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6565    setToolTip(fileName);
    6666
    67     if (fileName.isNull()) {
     67    if (fileName.isEmpty()) {
    6868        clear();
    6969        m_currentFileName.clear();
  • trunk/tools/linguist/linguist/sourcecodeview.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/statistics.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/statistics.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/statistics.ui

    r651 r846  
    33 <comment>*********************************************************************
    44**
    5 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     5** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    66** All rights reserved.
    77** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/translatedialog.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/translatedialog.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/translatedialog.ui

    r651 r846  
    33 <comment>*********************************************************************
    44**
    5 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     5** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    66** All rights reserved.
    77** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/translationsettingsdialog.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/linguist/translationsettingsdialog.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/lrelease/lrelease.pro

    r596 r846  
    1717include(../shared/formats.pri)
    1818include(../shared/proparser.pri)
     19include(../../shared/symbian/epocroot.pri)
    1920
    2021win32:LIBS += -ladvapi32   # for qsettings_win.cpp
  • trunk/tools/linguist/lrelease/main.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5656#include <QtCore/QTextStream>
    5757
     58#include <iostream>
     59
    5860QT_USE_NAMESPACE
    5961
     
    6466#endif
    6567        );
     68
     69struct LR {
     70    static inline QString tr(const char *sourceText, const char *comment = 0)
     71    {
     72        return QCoreApplication::translate("LRelease", sourceText, comment);
     73    }
     74};
     75#else
     76class LR {
     77    Q_DECLARE_TR_FUNCTIONS(LRelease)
     78};
    6679#endif
    6780
     
    7487static void printUsage()
    7588{
    76     printOut(QCoreApplication::tr(
     89    printOut(LR::tr(
    7790        "Usage:\n"
    7891        "    lrelease [options] project-file\n"
     
    107120    bool ok = tor.load(tsFileName, cd, QLatin1String("auto"));
    108121    if (!ok) {
    109         qWarning("lrelease error: %s\n", qPrintable(cd.error()));
     122        std::cerr << qPrintable(LR::tr("lrelease error: %1").arg(cd.error()));
    110123    } else {
    111124        if (!cd.errors().isEmpty())
     
    122135
    123136    if (cd.isVerbose())
    124         printOut(QCoreApplication::tr( "Updating '%1'...\n").arg(qmFileName));
     137        printOut(LR::tr("Updating '%1'...\n").arg(qmFileName));
    125138    if (removeIdentical) {
    126139        if (cd.isVerbose())
    127             printOut(QCoreApplication::tr( "Removing translations equal to source text in '%1'...\n").arg(qmFileName));
     140            printOut(LR::tr("Removing translations equal to source text in '%1'...\n").arg(qmFileName));
    128141        tor.stripIdenticalSourceTranslations();
    129142    }
     
    131144    QFile file(qmFileName);
    132145    if (!file.open(QIODevice::WriteOnly)) {
    133         qWarning("lrelease error: cannot create '%s': %s\n",
    134                  qPrintable(qmFileName), qPrintable(file.errorString()));
     146        std::cerr << qPrintable(LR::tr("lrelease error: cannot create '%1': %2\n")
     147                                .arg(qmFileName, file.errorString()));
    135148        return false;
    136149    }
     
    141154
    142155    if (!ok) {
    143         qWarning("lrelease error: cannot save '%s': %s\n",
    144                  qPrintable(qmFileName), qPrintable(cd.error()));
     156        std::cerr << qPrintable(LR::tr("lrelease error: cannot save '%1': %2")
     157                                .arg(qmFileName, cd.error()));
    145158    } else if (!cd.errors().isEmpty()) {
    146159        printOut(cd.error());
     
    179192#else
    180193    QCoreApplication app(argc, argv);
     194#ifndef Q_OS_WIN32
    181195    QTranslator translator;
    182     if (translator.load(QLatin1String("lrelease_") + QLocale::system().name()))
     196    QTranslator qtTranslator;
     197    QString sysLocale = QLocale::system().name();
     198    QString resourceDir = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
     199    if (translator.load(QLatin1String("linguist_") + sysLocale, resourceDir)
     200        && qtTranslator.load(QLatin1String("qt_") + sysLocale, resourceDir)) {
    183201        app.installTranslator(&translator);
    184 #endif
     202        app.installTranslator(&qtTranslator);
     203    }
     204#endif // Q_OS_WIN32
     205#endif // QT_BOOTSTRAPPED
    185206
    186207    ConversionData cd;
     
    220241            continue;
    221242        } else if (!strcmp(argv[i], "-version")) {
    222             printOut(QCoreApplication::tr( "lrelease version %1\n").arg(QLatin1String(QT_VERSION_STR)) );
     243            printOut(LR::tr("lrelease version %1\n").arg(QLatin1String(QT_VERSION_STR)));
    223244            return 0;
    224245        } else if (!strcmp(argv[i], "-qm")) {
     
    254275
    255276            if (!visitor.queryProFile(&pro)) {
    256                 qWarning("lrelease error: cannot read project file '%s'.", qPrintable(inputFile));
     277                std::cerr << qPrintable(LR::tr(
     278                          "lrelease error: cannot read project file '%1'.\n")
     279                          .arg(inputFile));
    257280                continue;
    258281            }
    259282            if (!visitor.accept(&pro)) {
    260                 qWarning("lrelease error: cannot process project file '%s'.", qPrintable(inputFile));
     283                std::cerr << qPrintable(LR::tr(
     284                          "lrelease error: cannot process project file '%1'.\n")
     285                          .arg(inputFile));
    261286                continue;
    262287            }
     
    264289            QStringList translations = visitor.values(QLatin1String("TRANSLATIONS"));
    265290            if (translations.isEmpty()) {
    266                 qWarning("lrelease warning: Met no 'TRANSLATIONS' entry in"
    267                          " project file '%s'\n",
    268                          qPrintable(inputFile));
     291                std::cerr << qPrintable(LR::tr(
     292                          "lrelease warning: Met no 'TRANSLATIONS' entry in project file '%1'\n")
     293                          .arg(inputFile));
    269294            } else {
    270295                QDir proDir(fi.absolutePath());
  • trunk/tools/linguist/lupdate/cpp.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5151#include <QtCore/QTextCodec>
    5252#include <QtCore/QTextStream>
     53#include <QtCore/QCoreApplication>
     54
     55#include <iostream>
    5356
    5457#include <ctype.h>              // for isXXX()
    5558
    5659QT_BEGIN_NAMESPACE
     60
     61class LU {
     62    Q_DECLARE_TR_FUNCTIONS(LUpdate)
     63};
    5764
    5865/* qmake ignore Q_OBJECT */
     
    226233        int elseLine;
    227234    };
     235
     236    std::ostream &yyMsg(int line = 0);
    228237
    229238    uint getChar();
     
    353362}
    354363
     364
     365std::ostream &CppParser::yyMsg(int line)
     366{
     367    return std::cerr << qPrintable(yyFileName) << ':' << (line ? line : yyLineNo) << ": ";
     368}
     369
    355370void CppParser::setInput(const QString &in)
    356371{
     
    475490STRING(friend);
    476491STRING(namespace);
     492STRING(operator);
    477493STRING(qtTrId);
    478494STRING(return);
     
    614630                                || yyBraceDepth != is.braceDepth1st
    615631                                || yyParenDepth != is.parenDepth1st)
    616                                 qWarning("%s:%d: Parenthesis/bracket/brace mismatch between "
    617                                          "#if and #else branches; using #if branch\n",
    618                                          qPrintable(yyFileName), is.elseLine);
     632                                yyMsg(is.elseLine)
     633                                    << qPrintable(LU::tr("Parenthesis/bracket/brace mismatch between "
     634                                                         "#if and #else branches; using #if branch\n"));
    619635                        } else {
    620636                            is.bracketDepth1st = yyBracketDepth;
     
    637653                                || yyBraceDepth != is.braceDepth1st
    638654                                || yyParenDepth != is.parenDepth1st)
    639                                 qWarning("%s:%d: Parenthesis/brace mismatch between "
    640                                          "#if and #else branches; using #if branch\n",
    641                                          qPrintable(yyFileName), is.elseLine);
     655                                yyMsg(is.elseLine)
     656                                    << qPrintable(LU::tr("Parenthesis/brace mismatch between "
     657                                                         "#if and #else branches; using #if branch\n"));
    642658                            yyBracketDepth = is.bracketDepth1st;
    643659                            yyBraceDepth = is.braceDepth1st;
     
    665681                            yyCh = getChar();
    666682                            if (yyCh == EOF) {
    667                                 qWarning("%s:%d: Unterminated C++ comment\n",
    668                                          qPrintable(yyFileName), yyLineNo);
     683                                yyMsg() << qPrintable(LU::tr("Unterminated C++ comment\n"));
    669684                                break;
    670685                            }
     
    740755                    return Tok_namespace;
    741756                break;
     757            case 'o':
     758                if (yyWord == stroperator) {
     759                    // Operator overload declaration/definition.
     760                    // We need to prevent those characters from confusing the followup
     761                    // parsing. Actually using them does not add value, so just eat them.
     762                    while (isspace(yyCh))
     763                       yyCh = getChar();
     764                    while (yyCh == '+' || yyCh == '-' || yyCh == '*' || yyCh == '/' || yyCh == '%'
     765                           || yyCh == '=' || yyCh == '<' || yyCh == '>' || yyCh == '!'
     766                           || yyCh == '&' || yyCh == '|' || yyCh == '~' || yyCh == '^'
     767                           || yyCh == '[' || yyCh == ']')
     768                        yyCh = getChar();
     769                }
     770                break;
    742771            case 'q':
    743772                if (yyWord == strqtTrId)
     
    796825                        yyCh = getChar();
    797826                        if (yyCh == EOF) {
    798                             qWarning("%s:%d: Unterminated C++ comment\n",
    799                                      qPrintable(yyFileName), yyLineNo);
     827                            yyMsg() << qPrintable(LU::tr("Unterminated C++ comment\n"));
    800828                            break;
    801829                        }
     
    830858
    831859                if (yyCh != '"')
    832                     qWarning("%s:%d: Unterminated C++ string\n",
    833                               qPrintable(yyFileName), yyLineNo);
     860                    yyMsg() << qPrintable(LU::tr("Unterminated C++ string\n"));
    834861                else
    835862                    yyCh = getChar();
     
    868895                forever {
    869896                    if (yyCh == EOF || yyCh == '\n') {
    870                         qWarning("%s:%d: Unterminated C++ character\n",
    871                                   qPrintable(yyFileName), yyLineNo);
     897                        yyMsg() << "Unterminated C++ character\n";
    872898                        break;
    873899                    }
     
    888914                if (yyBraceDepth == yyMinBraceDepth) {
    889915                    if (!inDefine)
    890                         qWarning("%s:%d: Excess closing brace in C++ code"
    891                                   " (or abuse of the C++ preprocessor)\n",
    892                                   qPrintable(yyFileName), yyCurLineNo);
     916                        yyMsg(yyCurLineNo)
     917                            << qPrintable(LU::tr("Excess closing brace in C++ code"
     918                                                 " (or abuse of the C++ preprocessor)\n"));
    893919                    // Avoid things getting messed up even more
    894920                    yyCh = getChar();
     
    906932            case ')':
    907933                if (yyParenDepth == 0)
    908                     qWarning("%s:%d: Excess closing parenthesis in C++ code"
    909                              " (or abuse of the C++ preprocessor)\n",
    910                              qPrintable(yyFileName), yyCurLineNo);
     934                    yyMsg(yyCurLineNo)
     935                        << qPrintable(LU::tr("Excess closing parenthesis in C++ code"
     936                                             " (or abuse of the C++ preprocessor)\n"));
    911937                else
    912938                    yyParenDepth--;
     
    921947            case ']':
    922948                if (yyBracketDepth == 0)
    923                     qWarning("%s:%d: Excess closing bracket in C++ code"
    924                              " (or abuse of the C++ preprocessor)\n",
    925                              qPrintable(yyFileName), yyCurLineNo);
     949                    yyMsg(yyCurLineNo)
     950                        << qPrintable(LU::tr("Excess closing bracket in C++ code"
     951                                             " (or abuse of the C++ preprocessor)\n"));
    926952                else
    927953                    yyBracketDepth--;
     
    12911317
    12921318    if (inclusions.contains(cleanFile)) {
    1293         qWarning("%s:%d: circular inclusion of %s\n",
    1294                  qPrintable(yyFileName), yyLineNo, qPrintable(cleanFile));
     1319        yyMsg() << qPrintable(LU::tr("circular inclusion of %1\n").arg(cleanFile));
    12951320        return;
    12961321    }
     
    13161341    QFile f(cleanFile);
    13171342    if (!f.open(QIODevice::ReadOnly)) {
    1318         qWarning("%s:%d: Cannot open %s: %s\n",
    1319                  qPrintable(yyFileName), yyLineNo,
    1320                  qPrintable(cleanFile), qPrintable(f.errorString()));
     1343        yyMsg() << qPrintable(LU::tr("Cannot open %1: %2\n").arg(cleanFile, f.errorString()));
    13211344        return;
    13221345    }
     
    16571680                    NamespaceList nsl;
    16581681                    if (!fullyQualify(namespaces, quali, true, &nsl, 0)) {
    1659                         qWarning("%s:%d: Ignoring definition of undeclared qualified class\n",
    1660                                  qPrintable(yyFileName), yyLineNo);
     1682                        yyMsg() << "Ignoring definition of undeclared qualified class\n";
    16611683                        break;
    16621684                    }
     
    16721694                prospectiveContext.clear();
    16731695                pendingContext.clear();
     1696
     1697                yyTok = getToken();
    16741698            }
    16751699            break;
     
    16851709                    namespaceDepths.push(namespaces.count());
    16861710                    enterNamespace(&namespaces, ns);
     1711
     1712                    functionContext = namespaces;
     1713                    functionContextUnresolved.clear();
     1714                    prospectiveContext.clear();
     1715                    pendingContext.clear();
    16871716                    yyTok = getToken();
    16881717                } else if (yyTok == Tok_Equals) {
     
    17581787                goto case_default;
    17591788            if (!sourcetext.isEmpty())
    1760                 qWarning("%s:%d: //%% cannot be used with tr() / QT_TR_NOOP(). Ignoring\n",
    1761                          qPrintable(yyFileName), yyLineNo);
     1789                yyMsg() << qPrintable(LU::tr("//% cannot be used with tr() / QT_TR_NOOP(). Ignoring\n"));
    17621790            utf8 = (yyTok == Tok_trUtf8);
    17631791            line = yyLineNo;
     
    17801808                    if (!fullyQualify(namespaces, pendingContext, true, &functionContext, &unresolved)) {
    17811809                        functionContextUnresolved = unresolved.join(strColons);
    1782                         qWarning("%s:%d: Qualifying with unknown namespace/class %s::%s\n",
    1783                                  qPrintable(yyFileName), yyLineNo,
    1784                                  qPrintable(stringifyNamespace(functionContext)),
    1785                                  qPrintable(unresolved.first()));
     1810                        yyMsg() << qPrintable(LU::tr("Qualifying with unknown namespace/class %1::%2\n")
     1811                                              .arg(stringifyNamespace(functionContext)).arg(unresolved.first()));
    17861812                    }
    17871813                    pendingContext.clear();
     
    17911817                        int idx = functionContext.length();
    17921818                        if (idx < 2) {
    1793                             qWarning("%s:%d: tr() cannot be called without context\n",
    1794                                      qPrintable(yyFileName), yyLineNo);
     1819                            yyMsg() << qPrintable(LU::tr("tr() cannot be called without context\n"));
    17951820                            break;
    17961821                        }
     
    18011826                                fctx = findNamespace(functionContext)->classDef;
    18021827                                if (!fctx->complained) {
    1803                                     qWarning("%s:%d: Class '%s' lacks Q_OBJECT macro\n",
    1804                                              qPrintable(yyFileName), yyLineNo,
    1805                                              qPrintable(context));
     1828                                    yyMsg() << qPrintable(LU::tr("Class '%1' lacks Q_OBJECT macro\n")
     1829                                                         .arg(context));
    18061830                                    fctx->complained = true;
    18071831                                }
     
    18311855                    QString className = prefix.mid(last == -1 ? 0 : last + 2);
    18321856                    if (!className.isEmpty() && className == functionName) {
    1833                         qWarning("%s::%d: It is not recommended to call tr() from within a constructor '%s::%s' ",
    1834                                   qPrintable(yyFileName), yyLineNo,
    1835                                   className.constData(), functionName.constData());
     1857                        yyMsg() << qPrintable(LU::tr("It is not recommended to call tr() from within a constructor '%1::%2'\n")
     1858                                .arg(className).arg(functionName));
    18361859                    }
    18371860#endif
     
    18481871                        }
    18491872                        if (!fctx->hasTrFunctions && !fctx->complained) {
    1850                             qWarning("%s:%d: Class '%s' lacks Q_OBJECT macro\n",
    1851                                      qPrintable(yyFileName), yyLineNo,
    1852                                      qPrintable(context));
     1873                            yyMsg() << qPrintable(LU::tr("Class '%1' lacks Q_OBJECT macro\n").arg(context));
    18531874                            fctx->complained = true;
    18541875                        }
     
    18621883                recordMessage(line, context, text, comment, extracomment, msgid, extra, utf8, plural);
    18631884            }
     1885            sourcetext.clear(); // Will have warned about that already
    18641886            extracomment.clear();
    18651887            msgid.clear();
     
    18711893                goto case_default;
    18721894            if (!sourcetext.isEmpty())
    1873                 qWarning("%s:%d: //%% cannot be used with translate() / QT_TRANSLATE_NOOP(). Ignoring\n",
    1874                          qPrintable(yyFileName), yyLineNo);
     1895                yyMsg() << qPrintable(LU::tr("//% cannot be used with translate() / QT_TRANSLATE_NOOP(). Ignoring\n"));
    18751896            utf8 = (yyTok == Tok_translateUtf8);
    18761897            line = yyLineNo;
     
    19181939                recordMessage(line, context, text, comment, extracomment, msgid, extra, utf8, plural);
    19191940            }
     1941            sourcetext.clear(); // Will have warned about that already
    19201942            extracomment.clear();
    19211943            msgid.clear();
     
    19261948                goto case_default;
    19271949            if (!msgid.isEmpty())
    1928                 qWarning("%s:%d: //= cannot be used with qtTrId() / QT_TRID_NOOP(). Ignoring\n",
    1929                          qPrintable(yyFileName), yyLineNo);
     1950                yyMsg() << qPrintable(LU::tr("//= cannot be used with qtTrId() / QT_TRID_NOOP(). Ignoring\n"));
    19301951            //utf8 = false; // Maybe use //%% or something like that
    19311952            line = yyLineNo;
     
    19942015                        continue;
    19952016                    if (c != '"') {
    1996                         qWarning("%s:%d: Unexpected character in meta string\n",
    1997                                  qPrintable(yyFileName), yyLineNo);
     2017                        yyMsg() << qPrintable(LU::tr("Unexpected character in meta string\n"));
    19982018                        break;
    19992019                    }
     
    20012021                        if (p >= yyWord.length()) {
    20022022                          whoops:
    2003                             qWarning("%s:%d: Unterminated meta string\n",
    2004                                      qPrintable(yyFileName), yyLineNo);
     2023                            yyMsg() << qPrintable(LU::tr("Unterminated meta string\n"));
    20052024                            break;
    20062025                        }
     
    20552074            yyTok = getToken();
    20562075            if (yyTok == Tok_tr || yyTok == Tok_trUtf8)
    2057                 qWarning("%s:%d: Cannot invoke tr() like this\n",
    2058                           qPrintable(yyFileName), yyLineNo);
     2076                yyMsg() << qPrintable(LU::tr("Cannot invoke tr() like this\n"));
    20592077            break;
    20602078        case Tok_ColonColon:
     
    20882106            prospectiveContext.clear();
    20892107            prefix.clear();
    2090             extracomment.clear();
    2091             msgid.clear();
    2092             extra.clear();
     2108            if (!sourcetext.isEmpty() || !extracomment.isEmpty() || !msgid.isEmpty() || !extra.isEmpty()) {
     2109                yyMsg() << qPrintable(LU::tr("Discarding unconsumed meta data\n"));
     2110                sourcetext.clear();
     2111                extracomment.clear();
     2112                msgid.clear();
     2113                extra.clear();
     2114            }
    20932115            yyTokColonSeen = false;
    20942116            yyTok = getToken();
     
    21242146
    21252147    if (yyBraceDepth != 0)
    2126         qWarning("%s:%d: Unbalanced opening brace in C++ code"
    2127                   " (or abuse of the C++ preprocessor)\n",
    2128                   qPrintable(yyFileName), yyBraceLineNo);
     2148        yyMsg(yyBraceLineNo)
     2149            << qPrintable(LU::tr("Unbalanced opening brace in C++ code"
     2150                                 " (or abuse of the C++ preprocessor)\n"));
    21292151    else if (yyParenDepth != 0)
    2130         qWarning("%s:%d: Unbalanced opening parenthesis in C++ code"
    2131                  " (or abuse of the C++ preprocessor)\n",
    2132                  qPrintable(yyFileName), yyParenLineNo);
     2152        yyMsg(yyParenLineNo)
     2153            << qPrintable(LU::tr("Unbalanced opening parenthesis in C++ code"
     2154                                 " (or abuse of the C++ preprocessor)\n"));
    21332155    else if (yyBracketDepth != 0)
    2134         qWarning("%s:%d: Unbalanced opening bracket in C++ code"
    2135                  " (or abuse of the C++ preprocessor)\n",
    2136                  qPrintable(yyFileName), yyBracketLineNo);
     2156        yyMsg(yyBracketLineNo)
     2157            << qPrintable(LU::tr("Unbalanced opening bracket in C++ code"
     2158                                 " (or abuse of the C++ preprocessor)\n"));
    21372159}
    21382160
     
    21952217        QFile file(filename);
    21962218        if (!file.open(QIODevice::ReadOnly)) {
    2197             cd.appendError(QString::fromLatin1("Cannot open %1: %2")
    2198                 .arg(filename, file.errorString()));
     2219            cd.appendError(LU::tr("Cannot open %1: %2").arg(filename, file.errorString()));
    21992220            continue;
    22002221        }
  • trunk/tools/linguist/lupdate/java.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5151#include <QtCore/QString>
    5252#include <QtCore/QTextCodec>
     53#include <QtCore/QCoreApplication>
     54
     55#include <iostream>
    5356
    5457#include <ctype.h>
    5558
    5659QT_BEGIN_NAMESPACE
     60
     61class LU {
     62    Q_DECLARE_TR_FUNCTIONS(LUpdate)
     63};
    5764
    5865enum { Tok_Eof, Tok_class, Tok_return, Tok_tr,
     
    107114static QStack<Scope*> yyScope;
    108115static QString yyDefaultContext;
     116
     117std::ostream &yyMsg(int line = 0)
     118{
     119    return std::cerr << qPrintable(yyFileName) << ':' << (line ? line : yyLineNo) << ": ";
     120}
    109121
    110122static QChar getChar()
     
    190202                        yyCh = getChar();
    191203                        if ( yyCh == EOF ) {
    192                             qFatal( "%s: Unterminated Java comment starting at"
    193                                     " line %d\n",
    194                                     qPrintable(yyFileName), yyLineNo );
    195 
     204                            yyMsg() << qPrintable(LU::tr("Unterminated Java comment.\n"));
    196205                            return Tok_Comment;
    197206                        }
     
    229238                                    int sub(yyCh.toLower().toAscii() - 87);
    230239                                    if( sub > 15 || sub < 10) {
    231                                         qFatal( "%s:%d: Invalid Unicode",
    232                                             qPrintable(yyFileName), yyLineNo );
     240                                        yyMsg() << qPrintable(LU::tr("Invalid Unicode value.\n"));
     241                                        break;
    233242                                    }
    234243                                    unicode += sub;
     
    252261
    253262                if ( yyCh != QLatin1Char('"') )
    254                     qFatal( "%s:%d: Unterminated string",
    255                         qPrintable(yyFileName), yyLineNo );
     263                    yyMsg() << qPrintable(LU::tr("Unterminated string.\n"));
    256264
    257265                yyCh = getChar();
     
    366374            s += yyString;
    367375        else {
    368             qWarning( "%s:%d: String used in translation can only contain strings"
    369                 " concatenated with other strings, not expressions or numbers.",
    370                 qPrintable(yyFileName), yyLineNo );
     376            yyMsg() << qPrintable(LU::tr(
     377                "String used in translation can contain only literals"
     378                " concatenated with other literals, not expressions or numbers.\n"));
    371379            return false;
    372380        }
     
    476484            }
    477485            else {
    478                 qFatal( "%s:%d: Class must be followed by a classname",
    479                                           qPrintable(yyFileName), yyLineNo );
     486                yyMsg() << qPrintable(LU::tr("'class' must be followed by a class name.\n"));
     487                break;
    480488            }
    481489            while (!match(Tok_LeftBrace)) {
     
    548556        case Tok_RightBrace:
    549557            if ( yyScope.isEmpty() ) {
    550                 qFatal( "%s:%d: Unbalanced right brace in Java code\n",
    551                         qPrintable(yyFileName), yyLineNo );
     558                yyMsg() << qPrintable(LU::tr("Excess closing brace.\n"));
    552559            }
    553560            else
     
    578585                        break;
    579586                    default:
    580                          qFatal( "%s:%d: Package keyword should be followed by com.package.name;",
    581                                           qPrintable(yyFileName), yyLineNo );
     587                         yyMsg() << qPrintable(LU::tr("'package' must be followed by package name.\n"));
    582588                         break;
    583589                }
     
    592598
    593599    if ( !yyScope.isEmpty() )
    594         qFatal( "%s:%d: Unbalanced braces in Java code\n",
    595                  qPrintable(yyFileName), yyScope.top()->line );
     600        yyMsg(yyScope.top()->line) << qPrintable(LU::tr("Unbalanced opening brace.\n"));
    596601    else if ( yyParenDepth != 0 )
    597         qFatal( "%s:%d: Unbalanced parentheses in Java code\n",
    598                  qPrintable(yyFileName), yyParenLineNo );
     602        yyMsg(yyParenLineNo) << qPrintable(LU::tr("Unbalanced opening parenthesis.\n"));
    599603}
    600604
     
    604608    QFile file(filename);
    605609    if (!file.open(QIODevice::ReadOnly)) {
    606         cd.appendError(QString::fromLatin1("Cannot open %1: %2")
    607             .arg(filename, file.errorString()));
     610        cd.appendError(LU::tr("Cannot open %1: %2").arg(filename, file.errorString()));
    608611        return false;
    609612    }
  • trunk/tools/linguist/lupdate/lupdate.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8080bool loadQScript(Translator &translator, const QString &filename, ConversionData &cd);
    8181bool loadUI(Translator &translator, const QString &filename, ConversionData &cd);
     82bool loadQml(Translator &translator, const QString &filename, ConversionData &cd);
    8283
    8384QT_END_NAMESPACE
  • trunk/tools/linguist/lupdate/lupdate.pro

    r561 r846  
    1616include(../shared/proparser.pri)
    1717
     18include($$QT_SOURCE_TREE/src/declarative/qml/parser/parser.pri)
     19INCLUDEPATH += $$QT_SOURCE_TREE/src/declarative/qml $$QT_BUILD_TREE/include/QtDeclarative
     20
    1821SOURCES += \
    1922    main.cpp \
     
    2427    java.cpp \
    2528    qscript.cpp \
     29    qdeclarative.cpp \
    2630    ui.cpp
    2731
  • trunk/tools/linguist/lupdate/main.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5353#include <QtCore/QStringList>
    5454#include <QtCore/QTextCodec>
     55#include <QtCore/QTranslator>
     56#include <QtCore/QLibraryInfo>
    5557
    5658#include <iostream>
     
    5860static QString m_defaultExtensions;
    5961
    60 static void printErr(const QString & out)
    61 {
    62     qWarning("%s", qPrintable(out));
    63 }
    64 
    6562static void printOut(const QString & out)
    6663{
    6764    std::cerr << qPrintable(out);
    6865}
     66
     67class LU {
     68    Q_DECLARE_TR_FUNCTIONS(LUpdate)
     69};
    6970
    7071static void recursiveFileInfoList(const QDir &dir,
     
    8182static void printUsage()
    8283{
    83     printOut(QObject::tr(
     84    printOut(LU::tr(
    8485        "Usage:\n"
    8586        "    lupdate [options] [project-file]...\n"
    86         "    lupdate [options] [source-file|path]... -ts ts-files\n\n"
     87        "    lupdate [options] [source-file|path|@lst-file]... -ts ts-files|@lst-file\n\n"
    8788        "lupdate is part of Qt's Linguist tool chain. It extracts translatable\n"
    8889        "messages from Qt UI files, C++, Java and JavaScript/QtScript source code.\n"
     
    133134        "    -version\n"
    134135        "           Display the version of lupdate and exit.\n"
     136        "    @lst-file\n"
     137        "           Read additional file names (one per line) from lst-file.\n"
    135138    ).arg(m_defaultExtensions));
    136139}
     
    149152        if (QFile(fileName).exists()) {
    150153            if (!tor.load(fileName, cd, QLatin1String("auto"))) {
    151                 printErr(cd.error());
     154                printOut(cd.error());
    152155                *fail = true;
    153156                continue;
     
    156159            cd.clearErrors();
    157160            if (setCodec && fetchedTor.codec() != tor.codec())
    158                 qWarning("lupdate warning: Codec for tr() '%s' disagrees with "
    159                          "existing file's codec '%s'. Expect trouble.",
    160                          fetchedTor.codecName().constData(), tor.codecName().constData());
     161                printOut(LU::tr("lupdate warning: Codec for tr() '%1' disagrees with"
     162                                " existing file's codec '%2'. Expect trouble.\n")
     163                         .arg(QString::fromLatin1(fetchedTor.codecName()),
     164                              QString::fromLatin1(tor.codecName())));
    161165            if (!targetLanguage.isEmpty() && targetLanguage != tor.languageCode())
    162                 qWarning("lupdate warning: Specified target language '%s' disagrees with "
    163                          "existing file's language '%s'. Ignoring.",
    164                          qPrintable(targetLanguage), qPrintable(tor.languageCode()));
     166                printOut(LU::tr("lupdate warning: Specified target language '%1' disagrees with"
     167                                " existing file's language '%2'. Ignoring.\n")
     168                         .arg(targetLanguage, tor.languageCode()));
    165169            if (!sourceLanguage.isEmpty() && sourceLanguage != tor.sourceLanguageCode())
    166                 qWarning("lupdate warning: Specified source language '%s' disagrees with "
    167                          "existing file's language '%s'. Ignoring.",
    168                          qPrintable(sourceLanguage), qPrintable(tor.sourceLanguageCode()));
     170                printOut(LU::tr("lupdate warning: Specified source language '%1' disagrees with"
     171                                " existing file's language '%2'. Ignoring.\n")
     172                         .arg(sourceLanguage, tor.sourceLanguageCode()));
    169173        } else {
    170174            if (setCodec)
     
    185189            tor.setLocationsType(Translator::AbsoluteLocations);
    186190        if (options & Verbose)
    187             printOut(QObject::tr("Updating '%1'...\n").arg(fn));
     191            printOut(LU::tr("Updating '%1'...\n").arg(fn));
    188192
    189193        UpdateOptions theseOptions = options;
     
    200204        if (options & PluralOnly) {
    201205            if (options & Verbose)
    202                 printOut(QObject::tr("Stripping non plural forms in '%1'...\n").arg(fn));
     206                printOut(LU::tr("Stripping non plural forms in '%1'...\n").arg(fn));
    203207            out.stripNonPluralForms();
    204208        }
     
    209213        out.normalizeTranslations(cd);
    210214        if (!cd.errors().isEmpty()) {
    211             printErr(cd.error());
     215            printOut(cd.error());
    212216            cd.clearErrors();
    213217        }
    214218        if (!out.save(fileName, cd, QLatin1String("auto"))) {
    215             printErr(cd.error());
     219            printOut(cd.error());
    216220            *fail = true;
    217221        }
     
    268272                 || it->endsWith(QLatin1String(".qs"), Qt::CaseInsensitive))
    269273            loadQScript(fetchedTor, *it, cd);
     274        else if (it->endsWith(QLatin1String(".qml"), Qt::CaseInsensitive))
     275            loadQml(fetchedTor, *it, cd);
    270276        else
    271277            sourceFilesCpp << *it;
     
    293299        codecForSource = tmp.last().toLatin1();
    294300        if (!QTextCodec::codecForName(codecForSource)) {
    295             qWarning("lupdate warning: Codec for source '%s' is invalid. "
    296                      "Falling back to codec for tr().", codecForSource.constData());
     301            printOut(LU::tr("lupdate warning: Codec for source '%1' is invalid."
     302                            " Falling back to codec for tr().\n")
     303                     .arg(QString::fromLatin1(codecForSource)));
    297304            codecForSource.clear();
    298305        }
     
    344351        visitor.setVerbose(options & Verbose);
    345352
     353        QHash<QString, QStringList> lupdateConfig;
     354        lupdateConfig.insert(QLatin1String("CONFIG"), QStringList(QLatin1String("lupdate_run")));
     355        visitor.addVariables(lupdateConfig);
     356
    346357        QFileInfo pfi(proFile);
    347358        ProFile pro(pfi.absoluteFilePath());
     
    355366            if (parentTor) {
    356367                if (topLevel) {
    357                     std::cerr << "lupdate warning: TS files from command line "
    358                             "will override TRANSLATIONS in " << qPrintable(proFile) << ".\n";
     368                    std::cerr << qPrintable(LU::tr("lupdate warning: TS files from command line "
     369                                                   "will override TRANSLATIONS in %1.\n").arg(proFile));
    359370                    goto noTrans;
    360371                } else if (nestComplain) {
    361                     std::cerr << "lupdate warning: TS files from command line "
    362                             "prevent recursing into " << qPrintable(proFile) << ".\n";
     372                    std::cerr << qPrintable(LU::tr("lupdate warning: TS files from command line "
     373                                                   "prevent recursing into %1.\n").arg(proFile));
    363374                    continue;
    364375                }
     
    391402        if (!parentTor) {
    392403            if (topLevel)
    393                 std::cerr << "lupdate warning: no TS files specified. Only diagnostics "
    394                         "will be produced for '" << qPrintable(proFile) << "'.\n";
     404                std::cerr << qPrintable(LU::tr("lupdate warning: no TS files specified. Only diagnostics "
     405                                               "will be produced for '%1'.\n").arg(proFile));
    395406            Translator tor;
    396407            processProject(nestComplain, pfi, visitor, options, codecForSource,
     
    406417{
    407418    QCoreApplication app(argc, argv);
    408     m_defaultExtensions = QLatin1String("ui,c,c++,cc,cpp,cxx,ch,h,h++,hh,hpp,hxx");
     419#ifndef Q_OS_WIN32
     420    QTranslator translator;
     421    QTranslator qtTranslator;
     422    QString sysLocale = QLocale::system().name();
     423    QString resourceDir = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
     424    if (translator.load(QLatin1String("linguist_") + sysLocale, resourceDir)
     425        && qtTranslator.load(QLatin1String("qt_") + sysLocale, resourceDir)) {
     426        app.installTranslator(&translator);
     427        app.installTranslator(&qtTranslator);
     428    }
     429#endif // Q_OS_WIN32
     430
     431    m_defaultExtensions = QLatin1String("java,jui,ui,c,c++,cc,cpp,cxx,ch,h,h++,hh,hpp,hxx,js,qs,qml");
    409432
    410433    QStringList args = app.arguments();
     
    449472            ++i;
    450473            if (i == argc) {
    451                 qWarning("The option -target-language requires a parameter.");
     474                printOut(LU::tr("The option -target-language requires a parameter.\n"));
    452475                return 1;
    453476            }
     
    457480            ++i;
    458481            if (i == argc) {
    459                 qWarning("The option -source-language requires a parameter.");
     482                printOut(LU::tr("The option -source-language requires a parameter.\n"));
    460483                return 1;
    461484            }
     
    465488            ++i;
    466489            if (i == argc) {
    467                 qWarning("The option -disable-heuristic requires a parameter.");
     490                printOut(LU::tr("The option -disable-heuristic requires a parameter.\n"));
    468491                return 1;
    469492            }
     
    476499                options &= ~HeuristicNumber;
    477500            } else {
    478                 qWarning("Invalid heuristic name passed to -disable-heuristic.");
     501                printOut(LU::tr("Invalid heuristic name passed to -disable-heuristic.\n"));
    479502                return 1;
    480503            }
     
    483506            ++i;
    484507            if (i == argc) {
    485                 qWarning("The option -locations requires a parameter.");
     508                printOut(LU::tr("The option -locations requires a parameter.\n"));
    486509                return 1;
    487510            }
     
    493516                options |= AbsoluteLocations;
    494517            } else {
    495                 qWarning("Invalid parameter passed to -locations.");
     518                printOut(LU::tr("Invalid parameter passed to -locations.\n"));
    496519                return 1;
    497520            }
     
    519542            ++i;
    520543            if (i == argc) {
    521                 qWarning("The -codecfortr option should be followed by a codec name.");
     544                printOut(LU::tr("The -codecfortr option should be followed by a codec name.\n"));
    522545                return 1;
    523546            }
     
    530553            ++i;
    531554            if (i == argc) {
    532                 qWarning("The -extensions option should be followed by an extension list.");
     555                printOut(LU::tr("The -extensions option should be followed by an extension list.\n"));
    533556                return 1;
    534557            }
     
    538561            ++i;
    539562            if (i == argc) {
    540                 qWarning("The -pro option should be followed by a filename of .pro file.");
     563                printOut(LU::tr("The -pro option should be followed by a filename of .pro file.\n"));
    541564                return 1;
    542565            }
     
    548571                ++i;
    549572                if (i == argc) {
    550                     qWarning("The -I option should be followed by a path.");
     573                    printOut(LU::tr("The -I option should be followed by a path.\n"));
    551574                    return 1;
    552575                }
     
    557580            continue;
    558581        } else if (arg.startsWith(QLatin1String("-")) && arg != QLatin1String("-")) {
    559             qWarning("Unrecognized option '%s'", qPrintable(arg));
     582            printOut(LU::tr("Unrecognized option '%1'.\n").arg(arg));
    560583            return 1;
    561584        }
    562585
     586        QStringList files;
     587        if (arg.startsWith(QLatin1String("@"))) {
     588            QFile lstFile(arg.mid(1));
     589            if (!lstFile.open(QIODevice::ReadOnly)) {
     590                printOut(LU::tr("lupdate error: List file '%1' is not readable.\n")
     591                         .arg(lstFile.fileName()));
     592                return 1;
     593            }
     594            while (!lstFile.atEnd())
     595                files << QString::fromLocal8Bit(lstFile.readLine().trimmed());
     596        } else {
     597            files << arg;
     598        }
    563599        if (metTsFlag) {
    564             bool found = false;
    565             foreach (const Translator::FileFormat &fmt, Translator::registeredFileFormats()) {
    566                 if (arg.endsWith(QLatin1Char('.') + fmt.extension, Qt::CaseInsensitive)) {
    567                     QFileInfo fi(arg);
    568                     if (!fi.exists() || fi.isWritable()) {
    569                         tsFileNames.append(QFileInfo(arg).absoluteFilePath());
    570                     } else {
    571                         qWarning("lupdate warning: For some reason, '%s' is not writable.\n",
    572                                 qPrintable(arg));
     600            foreach (const QString &file, files) {
     601                bool found = false;
     602                foreach (const Translator::FileFormat &fmt, Translator::registeredFileFormats()) {
     603                    if (file.endsWith(QLatin1Char('.') + fmt.extension, Qt::CaseInsensitive)) {
     604                        QFileInfo fi(file);
     605                        if (!fi.exists() || fi.isWritable()) {
     606                            tsFileNames.append(QFileInfo(file).absoluteFilePath());
     607                        } else {
     608                            printOut(LU::tr("lupdate warning: For some reason, '%1' is not writable.\n")
     609                                     .arg(file));
     610                        }
     611                        found = true;
     612                        break;
    573613                    }
    574                     found = true;
    575                     break;
    576614                }
    577             }
    578             if (!found) {
    579                 qWarning("lupdate error: File '%s' has no recognized extension\n",
    580                          qPrintable(arg));
    581                 return 1;
    582             }
    583         } else if (arg.endsWith(QLatin1String(".pro"), Qt::CaseInsensitive)
    584                 || arg.endsWith(QLatin1String(".pri"), Qt::CaseInsensitive)) {
    585             proFiles << arg;
     615                if (!found) {
     616                    printOut(LU::tr("lupdate error: File '%1' has no recognized extension.\n")
     617                             .arg(file));
     618                    return 1;
     619                }
     620            }
    586621            numFiles++;
    587622        } else {
    588             QFileInfo fi(arg);
    589             if (!fi.exists()) {
    590                 qWarning("lupdate error: File '%s' does not exists\n", qPrintable(arg));
    591                 return 1;
    592             } else if (fi.isDir()) {
    593                 if (options & Verbose)
    594                     printOut(QObject::tr("Scanning directory '%1'...").arg(arg));
    595                 QDir dir = QDir(fi.filePath());
    596                 projectRoots.insert(dir.absolutePath() + QLatin1Char('/'));
    597                 if (extensionsNameFilters.isEmpty()) {
    598                     foreach (QString ext, extensions.split(QLatin1Char(','))) {
    599                         ext = ext.trimmed();
    600                         if (ext.startsWith(QLatin1Char('.')))
    601                             ext.remove(0, 1);
    602                         extensionsNameFilters.insert(ext);
     623            foreach (const QString &file, files) {
     624                QFileInfo fi(file);
     625                if (!fi.exists()) {
     626                    printOut(LU::tr("lupdate error: File '%1' does not exist.\n").arg(file));
     627                    return 1;
     628                }
     629                if (file.endsWith(QLatin1String(".pro"), Qt::CaseInsensitive)
     630                    || file.endsWith(QLatin1String(".pri"), Qt::CaseInsensitive)) {
     631                    proFiles << file;
     632                } else if (fi.isDir()) {
     633                    if (options & Verbose)
     634                        printOut(LU::tr("Scanning directory '%1'...\n").arg(file));
     635                    QDir dir = QDir(fi.filePath());
     636                    projectRoots.insert(dir.absolutePath() + QLatin1Char('/'));
     637                    if (extensionsNameFilters.isEmpty()) {
     638                        foreach (QString ext, extensions.split(QLatin1Char(','))) {
     639                            ext = ext.trimmed();
     640                            if (ext.startsWith(QLatin1Char('.')))
     641                                ext.remove(0, 1);
     642                            extensionsNameFilters.insert(ext);
     643                        }
    603644                    }
     645                    QDir::Filters filters = QDir::Files | QDir::NoSymLinks;
     646                    if (recursiveScan)
     647                        filters |= QDir::AllDirs | QDir::NoDotAndDotDot;
     648                    QFileInfoList fileinfolist;
     649                    recursiveFileInfoList(dir, extensionsNameFilters, filters, &fileinfolist);
     650                    int scanRootLen = dir.absolutePath().length();
     651                    foreach (const QFileInfo &fi, fileinfolist) {
     652                        QString fn = QDir::cleanPath(fi.absoluteFilePath());
     653                        sourceFiles << fn;
     654
     655                        if (!fn.endsWith(QLatin1String(".java"))
     656                            && !fn.endsWith(QLatin1String(".jui"))
     657                            && !fn.endsWith(QLatin1String(".ui"))
     658                            && !fn.endsWith(QLatin1String(".js"))
     659                            && !fn.endsWith(QLatin1String(".qs"))
     660                            && !fn.endsWith(QLatin1String(".qml"))) {
     661                            int offset = 0;
     662                            int depth = 0;
     663                            do {
     664                                offset = fn.lastIndexOf(QLatin1Char('/'), offset - 1);
     665                                QString ffn = fn.mid(offset + 1);
     666                                allCSources.insert(ffn, fn);
     667                            } while (++depth < 3 && offset > scanRootLen);
     668                        }
     669                    }
     670                } else {
     671                    sourceFiles << QDir::cleanPath(fi.absoluteFilePath());;
     672                    projectRoots.insert(fi.absolutePath() + QLatin1Char('/'));
    604673                }
    605                 QDir::Filters filters = QDir::Files | QDir::NoSymLinks;
    606                 if (recursiveScan)
    607                     filters |= QDir::AllDirs | QDir::NoDotAndDotDot;
    608                 QFileInfoList fileinfolist;
    609                 recursiveFileInfoList(dir, extensionsNameFilters, filters, &fileinfolist);
    610                 int scanRootLen = dir.absolutePath().length();
    611                 foreach (const QFileInfo &fi, fileinfolist) {
    612                     QString fn = QDir::cleanPath(fi.absoluteFilePath());
    613                     sourceFiles << fn;
    614 
    615                     if (!fn.endsWith(QLatin1String(".java"))
    616                         && !fn.endsWith(QLatin1String(".ui"))
    617                         && !fn.endsWith(QLatin1String(".js"))
    618                         && !fn.endsWith(QLatin1String(".qs"))) {
    619                         int offset = 0;
    620                         int depth = 0;
    621                         do {
    622                             offset = fn.lastIndexOf(QLatin1Char('/'), offset - 1);
    623                             QString ffn = fn.mid(offset + 1);
    624                             allCSources.insert(ffn, fn);
    625                         } while (++depth < 3 && offset > scanRootLen);
    626                     }
    627                 }
    628             } else {
    629                 sourceFiles << QDir::cleanPath(fi.absoluteFilePath());;
    630674            }
    631675            numFiles++;
     
    639683
    640684    if (!targetLanguage.isEmpty() && tsFileNames.count() != 1)
    641         std::cerr << "lupdate warning: -target-language usually only "
    642                      "makes sense with exactly one TS file.\n";
     685        printOut(LU::tr("lupdate warning: -target-language usually only"
     686                        " makes sense with exactly one TS file.\n"));
    643687    if (!codecForTr.isEmpty() && tsFileNames.isEmpty())
    644         std::cerr << "lupdate warning: -codecfortr has no effect without -ts.\n";
     688        printOut(LU::tr("lupdate warning: -codecfortr has no effect without -ts.\n"));
    645689
    646690    bool fail = false;
    647691    if (proFiles.isEmpty()) {
    648692        if (tsFileNames.isEmpty())
    649             std::cerr << "lupdate warning: no TS files specified. "
    650                          "Only diagnostics will be produced.\n";
     693            printOut(LU::tr("lupdate warning:"
     694                            " no TS files specified. Only diagnostics will be produced.\n"));
    651695
    652696        Translator fetchedTor;
     
    662706    } else {
    663707        if (!sourceFiles.isEmpty() || !includePath.isEmpty()) {
    664             qWarning("lupdate error: Both project and source files / include paths specified.\n");
     708            printOut(LU::tr("lupdate error:"
     709                            " Both project and source files / include paths specified.\n"));
    665710            return 1;
    666711        }
  • trunk/tools/linguist/lupdate/merge.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4545#include "translator.h"
    4646
     47#include <QtCore/QCoreApplication>
    4748#include <QtCore/QDebug>
    4849#include <QtCore/QMap>
     
    5152#include <QtCore/QVector>
    5253
    53 
    5454QT_BEGIN_NAMESPACE
     55
     56class LU {
     57    Q_DECLARE_TR_FUNCTIONS(LUpdate)
     58};
    5559
    5660static bool isDigitFriendly(QChar c)
     
    486490    if (options & Verbose) {
    487491        int totalFound = neww + known;
    488         err += QObject::tr("    Found %n source text(s) (%1 new and %2 already existing)\n", 0, totalFound).arg(neww).arg(known);
     492        err += LU::tr("    Found %n source text(s) (%1 new and %2 already existing)\n", 0, totalFound).arg(neww).arg(known);
    489493
    490494        if (obsoleted) {
    491495            if (options & NoObsolete) {
    492                 err += QObject::tr("    Removed %n obsolete entries\n", 0, obsoleted);
     496                err += LU::tr("    Removed %n obsolete entries\n", 0, obsoleted);
    493497            } else {
    494                 err += QObject::tr("    Kept %n obsolete entries\n", 0, obsoleted);
     498                err += LU::tr("    Kept %n obsolete entries\n", 0, obsoleted);
    495499            }
    496500        }
    497501
    498502        if (sameNumberHeuristicCount)
    499             err += QObject::tr("    Number heuristic provided %n translation(s)\n",
     503            err += LU::tr("    Number heuristic provided %n translation(s)\n",
    500504                      0, sameNumberHeuristicCount);
    501505        if (sameTextHeuristicCount)
    502             err += QObject::tr("    Same-text heuristic provided %n translation(s)\n",
     506            err += LU::tr("    Same-text heuristic provided %n translation(s)\n",
    503507                      0, sameTextHeuristicCount);
    504508        if (similarTextHeuristicCount)
    505             err += QObject::tr("    Similar-text heuristic provided %n translation(s)\n",
     509            err += LU::tr("    Similar-text heuristic provided %n translation(s)\n",
    506510                      0, similarTextHeuristicCount);
    507511    }
  • trunk/tools/linguist/lupdate/qscript.cpp

    r651 r846  
    22/****************************************************************************
    33**
    4 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     4** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    55** All rights reserved.
    66** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4040**
    4141****************************************************************************/
     42
     43
     44#define Q_SCRIPT_REGEXPLITERAL_RULE1 7
     45
     46#define Q_SCRIPT_REGEXPLITERAL_RULE2 8
     47
     48#include <translator.h>
     49
     50#include <QtCore/QCoreApplication>
     51#include <QtCore/qdebug.h>
     52#include <QtCore/qnumeric.h>
     53#include <QtCore/qstring.h>
     54#include <QtCore/qtextcodec.h>
     55#include <QtCore/qvariant.h>
     56
     57#include <iostream>
     58
     59#include <ctype.h>
     60#include <stdlib.h>
     61#include <stdio.h>
     62#include <string.h>
     63
     64QT_BEGIN_NAMESPACE
     65
     66class LU {
     67    Q_DECLARE_TR_FUNCTIONS(LUpdate)
     68};
    4269
    4370class QScriptGrammar
     
    174201  }
    175202};
    176 
    177203
    178204const char *const QScriptGrammar::spell [] = {
     
    748774  -1, -1};
    749775
    750 
    751 #define Q_SCRIPT_REGEXPLITERAL_RULE1 7
    752 
    753 #define Q_SCRIPT_REGEXPLITERAL_RULE2 8
    754 
    755 #include <translator.h>
    756 
    757 #include <QtCore/qdebug.h>
    758 #include <QtCore/qnumeric.h>
    759 #include <QtCore/qstring.h>
    760 #include <QtCore/qtextcodec.h>
    761 #include <QtCore/qvariant.h>
    762 
    763 #include <ctype.h>
    764 #include <stdlib.h>
    765 #include <stdio.h>
    766 #include <string.h>
    767 
    768 QT_BEGIN_NAMESPACE
    769 
    770776static void recordMessage(
    771777    Translator *tor, const QString &context, const QString &text, const QString &comment,
    772     const QString &extracomment, bool plural, const QString &fileName, int lineNo)
     778    const QString &extracomment, const QString &msgid, const TranslatorMessage::ExtraData &extra,
     779    bool plural, const QString &fileName, int lineNo)
    773780{
    774781    TranslatorMessage msg(
     
    777784        TranslatorMessage::Unfinished, plural);
    778785    msg.setExtraComment(extracomment.simplified());
     786    msg.setId(msgid);
     787    msg.setExtras(extra);
    779788    tor->extend(msg);
    780789}
     
    784793{
    785794
     795class CommentProcessor
     796{
     797public:
     798    virtual ~CommentProcessor() {}
     799    virtual void processComment(const QChar *chars, int length) = 0;
     800};
     801
    786802class Lexer
    787803{
    788804public:
    789     Lexer();
     805    Lexer(CommentProcessor *);
    790806    ~Lexer();
    791807
    792     void setCode(const QString &c, int lineno);
     808    void setCode(const QString &c, const QString &fileName, int lineno);
    793809    int lex();
    794810
     811    QString fileName() const { return yyfilename; }
    795812    int currentLineNo() const { return yylineno; }
    796813    int currentColumnNo() const { return yycolumn; }
     
    872889
    873890private:
     891    QString yyfilename;
    874892    int yylineno;
    875893    bool done;
     
    925943    void syncProhibitAutomaticSemicolon();
    926944
     945    void processComment(const QChar *, int);
     946
    927947    const QChar *code;
    928948    uint length;
     
    951971    int parenthesesCount;
    952972    bool prohibitAutomaticSemicolon;
     973
     974    CommentProcessor *commentProcessor;
    953975};
    954976
     
    10271049} // namespace QScript
    10281050
    1029 QScript::Lexer::Lexer()
     1051QScript::Lexer::Lexer(QScript::CommentProcessor *proc)
    10301052    :
    10311053      yylineno(0),
     
    10381060      check_reserved(true),
    10391061      parenthesesState(IgnoreParentheses),
    1040       prohibitAutomaticSemicolon(false)
     1062      prohibitAutomaticSemicolon(false),
     1063      commentProcessor(proc)
    10411064{
    10421065    // allocate space for read buffers
     
    10531076}
    10541077
    1055 void QScript::Lexer::setCode(const QString &c, int lineno)
     1078void QScript::Lexer::setCode(const QString &c, const QString &fileName, int lineno)
    10561079{
    10571080    errmsg = QString();
     1081    yyfilename = fileName;
    10581082    yylineno = lineno;
    10591083    yycolumn = 1;
     
    14041428                recordStartPos();
    14051429                shift(1);
     1430                Q_ASSERT(pos16 == 0);
    14061431                state = InSingleLineComment;
    14071432            } else if (current == '/' && next1 == '*') {
    14081433                recordStartPos();
    14091434                shift(1);
     1435                Q_ASSERT(pos16 == 0);
    14101436                state = InMultiLineComment;
    14111437            } else if (current == 0) {
     
    14661492                    setDone(Bad);
    14671493                    err = IllegalCharacter;
    1468                     errmsg = QLatin1String("Illegal character");
     1494                    errmsg = LU::tr("Illegal character");
    14691495                }
    14701496            }
     
    14771503                setDone(Bad);
    14781504                err = UnclosedStringLiteral;
    1479                 errmsg = QLatin1String("Unclosed string at end of line");
     1505                errmsg = LU::tr("Unclosed string at end of line");
    14801506            } else if (current == '\\') {
    14811507                state = InEscapeSequence;
     
    15031529                    setDone(Bad);
    15041530                    err = IllegalEscapeSequence;
    1505                     errmsg = QLatin1String("Illegal escape squence");
     1531                    errmsg = LU::tr("Illegal escape squence");
    15061532                }
    15071533            } else if (current == 'x')
     
    15421568                setDone(Bad);
    15431569                err = IllegalUnicodeEscapeSequence;
    1544                 errmsg = QLatin1String("Illegal unicode escape sequence");
     1570                errmsg = LU::tr("Illegal unicode escape sequence");
    15451571            }
    15461572            break;
    15471573        case InSingleLineComment:
    15481574            if (isLineTerminator()) {
     1575                record16(current); // include newline
     1576                processComment(buffer16, pos16);
    15491577                shiftWindowsLineBreak();
    15501578                yylineno++;
    15511579                yycolumn = 0;
     1580                pos16 = 0;
    15521581                terminator = true;
    15531582                bol = true;
     
    15591588            } else if (current == 0) {
    15601589                setDone(Eof);
     1590            } else {
     1591                record16(current);
    15611592            }
    15621593            break;
     
    15651596                setDone(Bad);
    15661597                err = UnclosedComment;
    1567                 errmsg = QLatin1String("Unclosed comment at end of file");
     1598                errmsg = LU::tr("Unclosed comment at end of file");
    15681599            } else if (isLineTerminator()) {
    15691600                shiftWindowsLineBreak();
    15701601                yylineno++;
    15711602            } else if (current == '*' && next1 == '/') {
     1603                processComment(buffer16, pos16);
     1604                pos16 = 0;
    15721605                state = Start;
    15731606                shift(1);
     1607            } else {
     1608                record16(current);
    15741609            }
    15751610            break;
     
    16491684                setDone(Bad);
    16501685                err = IllegalExponentIndicator;
    1651                 errmsg = QLatin1String("Illegal syntax for exponential number");
     1686                errmsg = LU::tr("Illegal syntax for exponential number");
    16521687            }
    16531688            break;
     
    16751710        state = Bad;
    16761711        err = IllegalIdentifier;
    1677         errmsg = QLatin1String("Identifier cannot start with numeric literal");
     1712        errmsg = LU::tr("Identifier cannot start with numeric literal");
    16781713    }
    16791714
     
    19942029    while (1) {
    19952030        if (isLineTerminator() || current == 0) {
    1996             errmsg = QLatin1String("Unterminated regular expression literal");
     2031            errmsg = LU::tr("Unterminated regular expression literal");
    19972032            return false;
    19982033        }
     
    20332068}
    20342069
     2070void QScript::Lexer::processComment(const QChar *chars, int length)
     2071{
     2072    commentProcessor->processComment(chars, length);
     2073}
     2074
    20352075
    20362076class Translator;
    20372077
    2038 class QScriptParser: protected QScriptGrammar
     2078class QScriptParser: protected QScriptGrammar, public QScript::CommentProcessor
    20392079{
    20402080public:
     
    20522092    ~QScriptParser();
    20532093
    2054     bool parse(QScript::Lexer *lexer,
    2055                const QString &fileName,
    2056                Translator *translator);
    2057 
     2094    void setLexer(QScript::Lexer *);
     2095
     2096    bool parse(Translator *translator);
     2097
     2098    QString fileName() const
     2099    { return lexer->fileName(); }
    20582100    inline QString errorMessage() const
    20592101    { return error_message; }
     
    20712113    inline Location &loc(int index)
    20722114    { return location_stack [tos + index - 2]; }
     2115
     2116    std::ostream &yyMsg(int line = 0);
     2117
     2118    virtual void processComment(const QChar *, int);
    20732119
    20742120protected:
     
    20812127    int error_lineno;
    20822128    int error_column;
     2129
     2130private:
     2131    QScript::Lexer *lexer;
     2132    QString extracomment;
     2133    QString msgid;
     2134    QString sourcetext;
     2135    TranslatorMessage::ExtraData extra;
    20832136};
    20842137
     
    21072160    sym_stack(0),
    21082161    state_stack(0),
    2109     location_stack(0)
     2162    location_stack(0),
     2163    lexer(0)
    21102164{
    21112165}
     
    21292183}
    21302184
    2131 bool QScriptParser::parse(QScript::Lexer *lexer,
    2132                     const QString &fileName,
    2133                     Translator *translator)
    2134 {
     2185void QScriptParser::setLexer(QScript::Lexer *lex)
     2186{
     2187    lexer = lex;
     2188}
     2189
     2190bool QScriptParser::parse(Translator *translator)
     2191{
     2192  Q_ASSERT(lexer != 0);
    21352193  const int INITIAL_STATE = 0;
    21362194
     
    22142272    QString name = sym(1).toString();
    22152273    if ((name == QLatin1String("qsTranslate")) || (name == QLatin1String("QT_TRANSLATE_NOOP"))) {
     2274        if (!sourcetext.isEmpty())
     2275            yyMsg(identLineNo) << qPrintable(LU::tr("//% cannot be used with %1(). Ignoring\n").arg(name));
    22162276        QVariantList args = sym(2).toList();
    22172277        if (args.size() < 2) {
    2218             qWarning("%s:%d: %s() requires at least two arguments",
    2219                      qPrintable(fileName), identLineNo, qPrintable(name));
     2278            yyMsg(identLineNo) << qPrintable(LU::tr("%1() requires at least two arguments.\n").arg(name));
    22202279        } else {
    22212280            if ((args.at(0).type() != QVariant::String)
    22222281                || (args.at(1).type() != QVariant::String)) {
    2223                 qWarning("%s:%d: %s(): both arguments must be literal strings",
    2224                          qPrintable(fileName), identLineNo, qPrintable(name));
     2282                yyMsg(identLineNo) << qPrintable(LU::tr("%1(): both arguments must be literal strings.\n").arg(name));
    22252283            } else {
    22262284                QString context = args.at(0).toString();
    22272285                QString text = args.at(1).toString();
    22282286                QString comment = args.value(2).toString();
    2229                 QString extracomment;
    22302287                bool plural = (args.size() > 4);
    22312288                recordMessage(translator, context, text, comment, extracomment,
    2232                               plural, fileName, identLineNo);
     2289                              msgid, extra, plural, fileName(), identLineNo);
    22332290            }
    22342291        }
     2292        sourcetext.clear();
     2293        extracomment.clear();
     2294        msgid.clear();
     2295        extra.clear();
    22352296    } else if ((name == QLatin1String("qsTr")) || (name == QLatin1String("QT_TR_NOOP"))) {
     2297        if (!sourcetext.isEmpty())
     2298            yyMsg(identLineNo) << qPrintable(LU::tr("//% cannot be used with %1(). Ignoring\n").arg(name));
    22362299        QVariantList args = sym(2).toList();
    22372300        if (args.size() < 1) {
    2238             qWarning("%s:%d: %s() requires at least one argument",
    2239                      qPrintable(fileName), identLineNo, qPrintable(name));
     2301            yyMsg(identLineNo) << qPrintable(LU::tr("%1() requires at least one argument.\n").arg(name));
    22402302        } else {
    22412303            if (args.at(0).type() != QVariant::String) {
    2242                 qWarning("%s:%d: %s(): text to translate must be a literal string",
    2243                          qPrintable(fileName), identLineNo, qPrintable(name));
     2304                yyMsg(identLineNo) << qPrintable(LU::tr("%1(): text to translate must be a literal string.\n").arg(name));
    22442305            } else {
    2245                 QString context = QFileInfo(fileName).baseName();
     2306                QString context = QFileInfo(fileName()).baseName();
    22462307                QString text = args.at(0).toString();
    22472308                QString comment = args.value(1).toString();
    2248                 QString extracomment;
    22492309                bool plural = (args.size() > 2);
    22502310                recordMessage(translator, context, text, comment, extracomment,
    2251                               plural, fileName, identLineNo);
     2311                              msgid, extra, plural, fileName(), identLineNo);
    22522312            }
    22532313        }
     2314        sourcetext.clear();
     2315        extracomment.clear();
     2316        msgid.clear();
     2317        extra.clear();
     2318    } else if ((name == QLatin1String("qsTrId")) || (name == QLatin1String("QT_TRID_NOOP"))) {
     2319        if (!msgid.isEmpty())
     2320            yyMsg(identLineNo) << qPrintable(LU::tr("//= cannot be used with %1(). Ignoring\n").arg(name));
     2321        QVariantList args = sym(2).toList();
     2322        if (args.size() < 1) {
     2323            yyMsg(identLineNo) << qPrintable(LU::tr("%1() requires at least one argument.\n").arg(name));
     2324        } else {
     2325            if (args.at(0).type() != QVariant::String) {
     2326                yyMsg(identLineNo) << qPrintable(LU::tr("%1(): identifier must be a literal string.\n").arg(name));
     2327            } else {
     2328                msgid = args.at(0).toString();
     2329                bool plural = (args.size() > 1);
     2330                recordMessage(translator, QString(), sourcetext, QString(), extracomment,
     2331                              msgid, extra, plural, fileName(), identLineNo);
     2332            }
     2333        }
     2334        sourcetext.clear();
     2335        extracomment.clear();
     2336        msgid.clear();
     2337        extra.clear();
    22542338    }
    22552339} break;
     
    22772361        sym(1) = QVariant();
    22782362} break;
     2363
     2364    case 171:
     2365
     2366    case 172:
     2367
     2368    case 173:
     2369
     2370    case 174:
     2371
     2372    case 175:
     2373
     2374    case 176:
     2375
     2376    case 177:
     2377
     2378    case 178:
     2379
     2380    case 179:
     2381
     2382    case 180:
     2383
     2384    case 181:
     2385
     2386    case 182:
     2387
     2388    case 183:
     2389
     2390    case 184:
     2391
     2392    case 185:
     2393    if (!sourcetext.isEmpty() || !extracomment.isEmpty() || !msgid.isEmpty() || !extra.isEmpty()) {
     2394        yyMsg() << qPrintable(LU::tr("Discarding unconsumed meta data\n"));
     2395        sourcetext.clear();
     2396        extracomment.clear();
     2397        msgid.clear();
     2398        extra.clear();
     2399    }
     2400    break;
    22792401
    22802402          } // switch
     
    23322454                {
    23332455                  if (first)
    2334                     error_message += QLatin1String ("Expected ");
     2456                    //: Beginning of the string that contains
     2457                    //: comma-separated list of expected tokens
     2458                    error_message += LU::tr("Expected ");
    23352459                  else
    23362460                    error_message += QLatin1String (", ");
     
    23562480}
    23572481
     2482std::ostream &QScriptParser::yyMsg(int line)
     2483{
     2484    return std::cerr << qPrintable(fileName()) << ':' << (line ? line : lexer->startLineNo()) << ": ";
     2485}
     2486
     2487void QScriptParser::processComment(const QChar *chars, int length)
     2488{
     2489    if (!length)
     2490        return;
     2491    // Try to match the logic of the C++ parser.
     2492    if (*chars == QLatin1Char(':') && chars[1].isSpace()) {
     2493        extracomment += QString(chars+2, length-2);
     2494    } else if (*chars == QLatin1Char('=') && chars[1].isSpace()) {
     2495        msgid = QString(chars+2, length-2).simplified();
     2496    } else if (*chars == QLatin1Char('~') && chars[1].isSpace()) {
     2497        QString text = QString(chars+2, length-2).trimmed();
     2498        int k = text.indexOf(QLatin1Char(' '));
     2499        if (k > -1)
     2500            extra.insert(text.left(k), text.mid(k + 1).trimmed());
     2501    } else if (*chars == QLatin1Char('%') && chars[1].isSpace()) {
     2502        sourcetext.reserve(sourcetext.length() + length-2);
     2503        ushort *ptr = (ushort *)sourcetext.data() + sourcetext.length();
     2504        int p = 2, c;
     2505        forever {
     2506            if (p >= length)
     2507                break;
     2508            c = chars[p++].unicode();
     2509            if (isspace(c))
     2510                continue;
     2511            if (c != '"') {
     2512                yyMsg() << qPrintable(LU::tr("Unexpected character in meta string\n"));
     2513                break;
     2514            }
     2515            forever {
     2516                if (p >= length) {
     2517                  whoops:
     2518                    yyMsg() << qPrintable(LU::tr("Unterminated meta string\n"));
     2519                    break;
     2520                }
     2521                c = chars[p++].unicode();
     2522                if (c == '"')
     2523                    break;
     2524                if (c == '\\') {
     2525                    if (p >= length)
     2526                        goto whoops;
     2527                    c = chars[p++].unicode();
     2528                    if (c == '\n')
     2529                        goto whoops;
     2530                    *ptr++ = '\\';
     2531                }
     2532                *ptr++ = c;
     2533            }
     2534        }
     2535        sourcetext.resize(ptr - (ushort *)sourcetext.data());
     2536    }
     2537}
     2538
    23582539
    23592540bool loadQScript(Translator &translator, const QString &filename, ConversionData &cd)
     
    23612542    QFile file(filename);
    23622543    if (!file.open(QIODevice::ReadOnly)) {
    2363         cd.appendError(QString::fromLatin1("Cannot open %1: %2")
    2364             .arg(filename, file.errorString()));
     2544        cd.appendError(LU::tr("Cannot open %1: %2").arg(filename, file.errorString()));
    23652545        return false;
    23662546    }
     
    23752555
    23762556    QString code = ts.readAll();
    2377     QScript::Lexer lexer;
    2378     lexer.setCode(code, /*lineNumber=*/1);
    23792557    QScriptParser parser;
    2380     if (!parser.parse(&lexer, filename, &translator)) {
    2381         qWarning("%s:%d: %s", qPrintable(filename), parser.errorLineNumber(),
    2382                  qPrintable(parser.errorMessage()));
     2558    QScript::Lexer lexer(&parser);
     2559    lexer.setCode(code, filename, /*lineNumber=*/1);
     2560    parser.setLexer(&lexer);
     2561    if (!parser.parse(&translator)) {
     2562        std::cerr << qPrintable(filename) << ':' << parser.errorLineNumber() << ": "
     2563                  << qPrintable(parser.errorMessage()) << std::endl;
    23832564        return false;
    23842565    }
  • trunk/tools/linguist/lupdate/qscript.g

    r651 r846  
    11----------------------------------------------------------------------------
    22--
    3 -- Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3-- Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44-- All rights reserved.
    55-- Contact: Nokia Corporation (qt-info@nokia.com)
     
    8585#include <translator.h>
    8686
     87#include <QtCore/QCoreApplication>
    8788#include <QtCore/qdebug.h>
    8889#include <QtCore/qnumeric.h>
     
    9192#include <QtCore/qvariant.h>
    9293
     94#include <iostream>
     95
    9396#include <ctype.h>
    9497#include <stdlib.h>
     
    98101QT_BEGIN_NAMESPACE
    99102
     103class LU {
     104    Q_DECLARE_TR_FUNCTIONS(LUpdate)
     105};
     106
    100107static void recordMessage(
    101108    Translator *tor, const QString &context, const QString &text, const QString &comment,
    102     const QString &extracomment, bool plural, const QString &fileName, int lineNo)
     109    const QString &extracomment, const QString &msgid, const TranslatorMessage::ExtraData &extra,
     110    bool plural, const QString &fileName, int lineNo)
    103111{
    104112    TranslatorMessage msg(
     
    107115        TranslatorMessage::Unfinished, plural);
    108116    msg.setExtraComment(extracomment.simplified());
    109     tor->replace(msg);
     117    msg.setId(msgid);
     118    msg.setExtras(extra);
     119    tor->extend(msg);
    110120}
    111121
     
    114124{
    115125
     126class CommentProcessor
     127{
     128public:
     129    virtual ~CommentProcessor() {}
     130    virtual void processComment(const QChar *chars, int length) = 0;
     131};
     132
    116133class Lexer
    117134{
    118135public:
    119     Lexer();
     136    Lexer(CommentProcessor *);
    120137    ~Lexer();
    121138
    122     void setCode(const QString &c, int lineno);
     139    void setCode(const QString &c, const QString &fileName, int lineno);
    123140    int lex();
    124141
     142    QString fileName() const { return yyfilename; }
    125143    int currentLineNo() const { return yylineno; }
    126144    int currentColumnNo() const { return yycolumn; }
     
    202220
    203221private:
     222    QString yyfilename;
    204223    int yylineno;
    205224    bool done;
     
    255274    void syncProhibitAutomaticSemicolon();
    256275
     276    void processComment(const QChar *, int);
     277
    257278    const QChar *code;
    258279    uint length;
     
    281302    int parenthesesCount;
    282303    bool prohibitAutomaticSemicolon;
     304
     305    CommentProcessor *commentProcessor;
    283306};
    284307
     
    357380} // namespace QScript
    358381
    359 QScript::Lexer::Lexer()
     382QScript::Lexer::Lexer(QScript::CommentProcessor *proc)
    360383    :
    361384      yylineno(0),
     
    368391      check_reserved(true),
    369392      parenthesesState(IgnoreParentheses),
    370       prohibitAutomaticSemicolon(false)
     393      prohibitAutomaticSemicolon(false),
     394      commentProcessor(proc)
    371395{
    372396    // allocate space for read buffers
     
    383407}
    384408
    385 void QScript::Lexer::setCode(const QString &c, int lineno)
     409void QScript::Lexer::setCode(const QString &c, const QString &fileName, int lineno)
    386410{
    387411    errmsg = QString();
     412    yyfilename = fileName;
    388413    yylineno = lineno;
    389414    yycolumn = 1;
     
    734759                recordStartPos();
    735760                shift(1);
     761                Q_ASSERT(pos16 == 0);
    736762                state = InSingleLineComment;
    737763            } else if (current == '/' && next1 == '*') {
    738764                recordStartPos();
    739765                shift(1);
     766                Q_ASSERT(pos16 == 0);
    740767                state = InMultiLineComment;
    741768            } else if (current == 0) {
     
    796823                    setDone(Bad);
    797824                    err = IllegalCharacter;
    798                     errmsg = QLatin1String("Illegal character");
     825                    errmsg = LU::tr("Illegal character");
    799826                }
    800827            }
     
    807834                setDone(Bad);
    808835                err = UnclosedStringLiteral;
    809                 errmsg = QLatin1String("Unclosed string at end of line");
     836                errmsg = LU::tr("Unclosed string at end of line");
    810837            } else if (current == '\\') {
    811838                state = InEscapeSequence;
     
    833860                    setDone(Bad);
    834861                    err = IllegalEscapeSequence;
    835                     errmsg = QLatin1String("Illegal escape squence");
     862                    errmsg = LU::tr("Illegal escape squence");
    836863                }
    837864            } else if (current == 'x')
     
    872899                setDone(Bad);
    873900                err = IllegalUnicodeEscapeSequence;
    874                 errmsg = QLatin1String("Illegal unicode escape sequence");
     901                errmsg = LU::tr("Illegal unicode escape sequence");
    875902            }
    876903            break;
    877904        case InSingleLineComment:
    878905            if (isLineTerminator()) {
     906                record16(current); // include newline
     907                processComment(buffer16, pos16);
    879908                shiftWindowsLineBreak();
    880909                yylineno++;
    881910                yycolumn = 0;
     911                pos16 = 0;
    882912                terminator = true;
    883913                bol = true;
     
    889919            } else if (current == 0) {
    890920                setDone(Eof);
     921            } else {
     922                record16(current);
    891923            }
    892924            break;
     
    895927                setDone(Bad);
    896928                err = UnclosedComment;
    897                 errmsg = QLatin1String("Unclosed comment at end of file");
     929                errmsg = LU::tr("Unclosed comment at end of file");
    898930            } else if (isLineTerminator()) {
    899931                shiftWindowsLineBreak();
    900932                yylineno++;
    901933            } else if (current == '*' && next1 == '/') {
     934                processComment(buffer16, pos16);
     935                pos16 = 0;
    902936                state = Start;
    903937                shift(1);
     938            } else {
     939                record16(current);
    904940            }
    905941            break;
     
    9791015                setDone(Bad);
    9801016                err = IllegalExponentIndicator;
    981                 errmsg = QLatin1String("Illegal syntax for exponential number");
     1017                errmsg = LU::tr("Illegal syntax for exponential number");
    9821018            }
    9831019            break;
     
    10051041        state = Bad;
    10061042        err = IllegalIdentifier;
    1007         errmsg = QLatin1String("Identifier cannot start with numeric literal");
     1043        errmsg = LU::tr("Identifier cannot start with numeric literal");
    10081044    }
    10091045
     
    13241360    while (1) {
    13251361        if (isLineTerminator() || current == 0) {
    1326             errmsg = QLatin1String("Unterminated regular expression literal");
     1362            errmsg = LU::tr("Unterminated regular expression literal");
    13271363            return false;
    13281364        }
     
    13631399}
    13641400
     1401void QScript::Lexer::processComment(const QChar *chars, int length)
     1402{
     1403    commentProcessor->processComment(chars, length);
     1404}
     1405
    13651406
    13661407class Translator;
    13671408
    1368 class QScriptParser: protected $table
     1409class QScriptParser: protected $table, public QScript::CommentProcessor
    13691410{
    13701411public:
     
    13821423    ~QScriptParser();
    13831424
    1384     bool parse(QScript::Lexer *lexer,
    1385                const QString &fileName,
    1386                Translator *translator);
    1387 
     1425    void setLexer(QScript::Lexer *);
     1426
     1427    bool parse(Translator *translator);
     1428
     1429    QString fileName() const
     1430    { return lexer->fileName(); }
    13881431    inline QString errorMessage() const
    13891432    { return error_message; }
     
    14011444    inline Location &loc(int index)
    14021445    { return location_stack [tos + index - 2]; }
     1446
     1447    std::ostream &yyMsg(int line = 0);
     1448
     1449    virtual void processComment(const QChar *, int);
    14031450
    14041451protected:
     
    14111458    int error_lineno;
    14121459    int error_column;
     1460
     1461private:
     1462    QScript::Lexer *lexer;
     1463    QString extracomment;
     1464    QString msgid;
     1465    QString sourcetext;
     1466    TranslatorMessage::ExtraData extra;
    14131467};
    14141468
     
    14371491    sym_stack(0),
    14381492    state_stack(0),
    1439     location_stack(0)
     1493    location_stack(0),
     1494    lexer(0)
    14401495{
    14411496}
     
    14591514}
    14601515
    1461 bool QScriptParser::parse(QScript::Lexer *lexer,
    1462                     const QString &fileName,
    1463                     Translator *translator)
    1464 {
     1516void QScriptParser::setLexer(QScript::Lexer *lex)
     1517{
     1518    lexer = lex;
     1519}
     1520
     1521bool QScriptParser::parse(Translator *translator)
     1522{
     1523  Q_ASSERT(lexer != 0);
    14651524  const int INITIAL_STATE = 0;
    14661525
     
    16291688    QString name = sym(1).toString();
    16301689    if ((name == QLatin1String("qsTranslate")) || (name == QLatin1String("QT_TRANSLATE_NOOP"))) {
     1690        if (!sourcetext.isEmpty())
     1691            yyMsg(identLineNo) << qPrintable(LU::tr("//% cannot be used with %1(). Ignoring\n").arg(name));
    16311692        QVariantList args = sym(2).toList();
    16321693        if (args.size() < 2) {
    1633             qWarning("%s:%d: %s() requires at least two arguments",
    1634                      qPrintable(fileName), identLineNo, qPrintable(name));
     1694            yyMsg(identLineNo) << qPrintable(LU::tr("%1() requires at least two arguments.\n").arg(name));
    16351695        } else {
    16361696            if ((args.at(0).type() != QVariant::String)
    16371697                || (args.at(1).type() != QVariant::String)) {
    1638                 qWarning("%s:%d: %s(): both arguments must be literal strings",
    1639                          qPrintable(fileName), identLineNo, qPrintable(name));
     1698                yyMsg(identLineNo) << qPrintable(LU::tr("%1(): both arguments must be literal strings.\n").arg(name));
    16401699            } else {
    16411700                QString context = args.at(0).toString();
    16421701                QString text = args.at(1).toString();
    16431702                QString comment = args.value(2).toString();
    1644                 QString extracomment;
    16451703                bool plural = (args.size() > 4);
    16461704                recordMessage(translator, context, text, comment, extracomment,
    1647                               plural, fileName, identLineNo);
    1648             }
    1649         }
     1705                              msgid, extra, plural, fileName(), identLineNo);
     1706            }
     1707        }
     1708        sourcetext.clear();
     1709        extracomment.clear();
     1710        msgid.clear();
     1711        extra.clear();
    16501712    } else if ((name == QLatin1String("qsTr")) || (name == QLatin1String("QT_TR_NOOP"))) {
     1713        if (!sourcetext.isEmpty())
     1714            yyMsg(identLineNo) << qPrintable(LU::tr("//% cannot be used with %1(). Ignoring\n").arg(name));
    16511715        QVariantList args = sym(2).toList();
    16521716        if (args.size() < 1) {
    1653             qWarning("%s:%d: %s() requires at least one argument",
    1654                      qPrintable(fileName), identLineNo, qPrintable(name));
     1717            yyMsg(identLineNo) << qPrintable(LU::tr("%1() requires at least one argument.\n").arg(name));
    16551718        } else {
    16561719            if (args.at(0).type() != QVariant::String) {
    1657                 qWarning("%s:%d: %s(): text to translate must be a literal string",
    1658                          qPrintable(fileName), identLineNo, qPrintable(name));
     1720                yyMsg(identLineNo) << qPrintable(LU::tr("%1(): text to translate must be a literal string.\n").arg(name));
    16591721            } else {
    1660                 QString context = QFileInfo(fileName).baseName();
     1722                QString context = QFileInfo(fileName()).baseName();
    16611723                QString text = args.at(0).toString();
    16621724                QString comment = args.value(1).toString();
    1663                 QString extracomment;
    16641725                bool plural = (args.size() > 2);
    16651726                recordMessage(translator, context, text, comment, extracomment,
    1666                               plural, fileName, identLineNo);
    1667             }
    1668         }
     1727                              msgid, extra, plural, fileName(), identLineNo);
     1728            }
     1729        }
     1730        sourcetext.clear();
     1731        extracomment.clear();
     1732        msgid.clear();
     1733        extra.clear();
     1734    } else if ((name == QLatin1String("qsTrId")) || (name == QLatin1String("QT_TRID_NOOP"))) {
     1735        if (!msgid.isEmpty())
     1736            yyMsg(identLineNo) << qPrintable(LU::tr("//= cannot be used with %1(). Ignoring\n").arg(name));
     1737        QVariantList args = sym(2).toList();
     1738        if (args.size() < 1) {
     1739            yyMsg(identLineNo) << qPrintable(LU::tr("%1() requires at least one argument.\n").arg(name));
     1740        } else {
     1741            if (args.at(0).type() != QVariant::String) {
     1742                yyMsg(identLineNo) << qPrintable(LU::tr("%1(): identifier must be a literal string.\n").arg(name));
     1743            } else {
     1744                msgid = args.at(0).toString();
     1745                bool plural = (args.size() > 1);
     1746                recordMessage(translator, QString(), sourcetext, QString(), extracomment,
     1747                              msgid, extra, plural, fileName(), identLineNo);
     1748            }
     1749        }
     1750        sourcetext.clear();
     1751        extracomment.clear();
     1752        msgid.clear();
     1753        extra.clear();
    16691754    }
    16701755} break;
     
    18121897
    18131898Statement: Block ;
     1899/.
     1900    case $rule_number:
     1901./
    18141902Statement: VariableStatement ;
     1903/.
     1904    case $rule_number:
     1905./
    18151906Statement: EmptyStatement ;
     1907/.
     1908    case $rule_number:
     1909./
    18161910Statement: ExpressionStatement ;
     1911/.
     1912    case $rule_number:
     1913./
    18171914Statement: IfStatement ;
     1915/.
     1916    case $rule_number:
     1917./
    18181918Statement: IterationStatement ;
     1919/.
     1920    case $rule_number:
     1921./
    18191922Statement: ContinueStatement ;
     1923/.
     1924    case $rule_number:
     1925./
    18201926Statement: BreakStatement ;
     1927/.
     1928    case $rule_number:
     1929./
    18211930Statement: ReturnStatement ;
     1931/.
     1932    case $rule_number:
     1933./
    18221934Statement: WithStatement ;
     1935/.
     1936    case $rule_number:
     1937./
    18231938Statement: LabelledStatement ;
     1939/.
     1940    case $rule_number:
     1941./
    18241942Statement: SwitchStatement ;
     1943/.
     1944    case $rule_number:
     1945./
    18251946Statement: ThrowStatement ;
     1947/.
     1948    case $rule_number:
     1949./
    18261950Statement: TryStatement ;
     1951/.
     1952    case $rule_number:
     1953./
    18271954Statement: DebuggerStatement ;
     1955/.
     1956    case $rule_number:
     1957    if (!sourcetext.isEmpty() || !extracomment.isEmpty() || !msgid.isEmpty() || !extra.isEmpty()) {
     1958        yyMsg() << qPrintable(LU::tr("Discarding unconsumed meta data\n"));
     1959        sourcetext.clear();
     1960        extracomment.clear();
     1961        msgid.clear();
     1962        extra.clear();
     1963    }
     1964    break;
     1965./
    18281966
    18291967Block: T_LBRACE StatementListOpt T_RBRACE ;
     
    19642102                  if (first)
    19652103                    error_message += QLatin1String ("Expected ");
     2104                    //: Beginning of the string that contains
     2105                    //: comma-separated list of expected tokens
     2106                    error_message += LU::tr("Expected ");
    19662107                  else
    19672108                    error_message += QLatin1String (", ");
     
    19872128}
    19882129
     2130std::ostream &QScriptParser::yyMsg(int line)
     2131{
     2132    return std::cerr << qPrintable(fileName()) << ':' << (line ? line : lexer->startLineNo()) << ": ";
     2133}
     2134
     2135void QScriptParser::processComment(const QChar *chars, int length)
     2136{
     2137    if (!length)
     2138        return;
     2139    // Try to match the logic of the C++ parser.
     2140    if (*chars == QLatin1Char(':') && chars[1].isSpace()) {
     2141        extracomment += QString(chars+2, length-2);
     2142    } else if (*chars == QLatin1Char('=') && chars[1].isSpace()) {
     2143        msgid = QString(chars+2, length-2).simplified();
     2144    } else if (*chars == QLatin1Char('~') && chars[1].isSpace()) {
     2145        QString text = QString(chars+2, length-2).trimmed();
     2146        int k = text.indexOf(QLatin1Char(' '));
     2147        if (k > -1)
     2148            extra.insert(text.left(k), text.mid(k + 1).trimmed());
     2149    } else if (*chars == QLatin1Char('%') && chars[1].isSpace()) {
     2150        sourcetext.reserve(sourcetext.length() + length-2);
     2151        ushort *ptr = (ushort *)sourcetext.data() + sourcetext.length();
     2152        int p = 2, c;
     2153        forever {
     2154            if (p >= length)
     2155                break;
     2156            c = chars[p++].unicode();
     2157            if (isspace(c))
     2158                continue;
     2159            if (c != '"') {
     2160                yyMsg() << qPrintable(LU::tr("Unexpected character in meta string\n"));
     2161                break;
     2162            }
     2163            forever {
     2164                if (p >= length) {
     2165                  whoops:
     2166                    yyMsg() << qPrintable(LU::tr("Unterminated meta string\n"));
     2167                    break;
     2168                }
     2169                c = chars[p++].unicode();
     2170                if (c == '"')
     2171                    break;
     2172                if (c == '\\') {
     2173                    if (p >= length)
     2174                        goto whoops;
     2175                    c = chars[p++].unicode();
     2176                    if (c == '\n')
     2177                        goto whoops;
     2178                    *ptr++ = '\\';
     2179                }
     2180                *ptr++ = c;
     2181            }
     2182        }
     2183        sourcetext.resize(ptr - (ushort *)sourcetext.data());
     2184    }
     2185}
     2186
    19892187
    19902188bool loadQScript(Translator &translator, const QString &filename, ConversionData &cd)
     
    19922190    QFile file(filename);
    19932191    if (!file.open(QIODevice::ReadOnly)) {
    1994         cd.appendError(QString::fromLatin1("Cannot open %1: %2")
    1995             .arg(filename, file.errorString()));
     2192        cd.appendError(LU::tr("Cannot open %1: %2").arg(filename, file.errorString()));
    19962193        return false;
    19972194    }
     
    20062203
    20072204    QString code = ts.readAll();
    2008     QScript::Lexer lexer;
    2009     lexer.setCode(code, /*lineNumber=*/1);
    20102205    QScriptParser parser;
    2011     if (!parser.parse(&lexer, filename, &translator)) {
    2012         qWarning("%s:%d: %s", qPrintable(filename), parser.errorLineNumber(),
    2013                  qPrintable(parser.errorMessage()));
     2206    QScript::Lexer lexer(&parser);
     2207    lexer.setCode(code, filename, /*lineNumber=*/1);
     2208    parser.setLexer(&lexer);
     2209    if (!parser.parse(&translator)) {
     2210        std::cerr << qPrintable(filename) << ':' << parser.errorLineNumber() << ": "
     2211                  << qPrintable(parser.errorMessage()) << std::endl;
    20142212        return false;
    20152213    }
  • trunk/tools/linguist/lupdate/ui.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4444#include <translator.h>
    4545
     46#include <QtCore/QCoreApplication>
    4647#include <QtCore/QDebug>
    4748#include <QtCore/QFile>
     
    5556
    5657QT_BEGIN_NAMESPACE
     58
     59class LU {
     60    Q_DECLARE_TR_FUNCTIONS(LUpdate)
     61};
    5762
    5863class UiReader : public QXmlDefaultHandler
     
    153158bool UiReader::fatalError(const QXmlParseException &exception)
    154159{
    155     QString msg;
    156     msg.sprintf("XML error: Parse error at line %d, column %d (%s).",
    157                  exception.lineNumber(), exception.columnNumber(),
    158                  exception.message().toLatin1().data());
    159     m_cd.appendError(msg);
     160    QString msg = LU::tr("XML error: Parse error at line %1, column %2 (%3).")
     161        .arg(exception.lineNumber()).arg(exception.columnNumber())
     162        .arg(exception.message());
     163    m_cd.appendError(msg);
    160164    return false;
    161165}
     
    182186    QFile file(filename);
    183187    if (!file.open(QIODevice::ReadOnly)) {
    184         cd.appendError(QString::fromLatin1("Cannot open %1: %2")
    185             .arg(filename, file.errorString()));
     188        cd.appendError(LU::tr("Cannot open %1: %2").arg(filename, file.errorString()));
    186189        return false;
    187190    }
     
    197200    bool result = reader.parse(in);
    198201    if (!result)
    199         cd.appendError(QLatin1String("Parse error in UI file"));
     202        cd.appendError(LU::tr("Parse error in UI file"));
    200203    reader.setContentHandler(0);
    201204    reader.setErrorHandler(0);
  • trunk/tools/linguist/phrasebooks/french.qph

    r561 r846  
    802802<phrase>
    803803    <source>Redo</source>
    804     <target>Annuler Annuler</target>
     804    <target>Rétablir</target>
    805805</phrase>
    806806<phrase>
     
    11121112</phrase>
    11131113<phrase>
    1114     <source>&amp;Redo</source>
    1115     <target>Re&amp;faire</target>
    1116 </phrase>
    1117 <phrase>
    11181114    <source>debugger</source>
    11191115    <target>débogueur</target>
     
    14391435    <target>&amp;Déboguer</target>
    14401436</phrase>
     1437<phrase>
     1438    <source>Slider</source>
     1439    <target>Barre de défilement</target>
     1440</phrase>
     1441<phrase>
     1442    <source>&amp;Restore</source>
     1443    <target>&amp;Restaurer</target>
     1444</phrase>
     1445<phrase>
     1446    <source>&amp;Move</source>
     1447    <target>&amp;Déplacer</target>
     1448</phrase>
     1449<phrase>
     1450    <source>New</source>
     1451    <target>Créer</target>
     1452</phrase>
     1453<phrase>
     1454    <source>Play</source>
     1455    <target>Lecture</target>
     1456</phrase>
     1457<phrase>
     1458    <source>Slider</source>
     1459    <target>Barre de défilement</target>
     1460</phrase>
     1461<phrase>
     1462    <source>&amp;Restore</source>
     1463    <target>&amp;Restaurer</target>
     1464</phrase>
     1465<phrase>
     1466    <source>&amp;Move</source>
     1467    <target>&amp;Déplacer</target>
     1468</phrase>
     1469<phrase>
     1470    <source>New</source>
     1471    <target>Créer</target>
     1472</phrase>
     1473<phrase>
     1474    <source>Play</source>
     1475    <target>Lecture</target>
     1476</phrase>
     1477<phrase>
     1478    <source>&amp;Redo</source>
     1479    <target>&amp;Refaire</target>
     1480</phrase>
     1481<phrase>
     1482    <source>Raised</source>
     1483    <target>Bombé</target>
     1484</phrase>
     1485<phrase>
     1486    <source>Sunken</source>
     1487    <target>Enfoncé</target>
     1488</phrase>
     1489<phrase>
     1490    <source>Run:</source>
     1491    <target>Exécution :</target>
     1492</phrase>
    14411493</QPH>
  • trunk/tools/linguist/phrasebooks/russian.qph

    r769 r846  
    504504<phrase>
    505505    <source>Next</source>
    506     <target>СлеЎующОй</target>
     506    <target>Далее</target>
    507507</phrase>
    508508<phrase>
     
    837837<phrase>
    838838    <source>slider</source>
    839     <target>пПлзуМПк</target>
     839    <target>регулятПр</target>
    840840</phrase>
    841841<phrase>
     
    10811081<phrase>
    10821082    <source>Next</source>
    1083     <target>Далее</target>
     1083    <target>СлеЎующОй</target>
    10841084</phrase>
    10851085<phrase>
     
    12161216    <target>ДПступ запрещёМ</target>
    12171217</phrase>
     1218<phrase>
     1219    <source>Previous</source>
     1220    <target>ПреЎыЎущОй</target>
     1221</phrase>
     1222<phrase>
     1223    <source>Next</source>
     1224    <target>СлеЎующее</target>
     1225</phrase>
     1226<phrase>
     1227    <source>Previous</source>
     1228    <target>ПреЎыЎущее</target>
     1229</phrase>
    12181230</QPH>
  • trunk/tools/linguist/shared/abstractproitemvisitor.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/shared/numerus.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6565    { Q_EQ, 1, Q_NEWRULE,
    6666      Q_EQ, 2 };
    67 static const uchar slovakRules[] =
     67static const uchar slovakStyleRules[] =
    6868    { Q_EQ, 1, Q_NEWRULE,
    6969      Q_BETWEEN, 2, 4 };
     
    101101      Q_EQ, 2, Q_NEWRULE,
    102102      Q_MOD_100 | Q_BETWEEN, 3, 10, Q_NEWRULE,
    103       Q_MOD_100 | Q_NOT | Q_BETWEEN, 0, 2 };
     103      Q_MOD_100 | Q_GEQ, 11 };
    104104static const uchar tagalogRules[] =
    105105    { Q_LEQ, 1, Q_NEWRULE,
     
    115115static const char * const latvianForms[] = { "Singular", "Plural", "Nullar", 0 };
    116116static const char * const irishStyleForms[] = { "Singular", "Dual", "Plural", 0 };
    117 static const char * const slovakForms[] = { "Singular", "Paucal", "Plural", 0 };
     117static const char * const slovakStyleForms[] = { "Singular", "Paucal", "Plural", 0 };
    118118static const char * const macedonianForms[] = { "Singular", "Dual", "Plural", 0 };
    119119static const char * const lithuanianForms[] = { "Singular", "Paucal", "Plural", 0 };
     
    280280    EOL
    281281};
    282 static const QLocale::Language slovakLanguages[] = { QLocale::Slovak, QLocale::Czech, EOL };
     282static const QLocale::Language slovakStyleLanguages[] = { QLocale::Slovak, QLocale::Czech, EOL };
    283283static const QLocale::Language macedonianLanguage[] = { QLocale::Macedonian, EOL };
    284284static const QLocale::Language lithuanianLanguage[] = { QLocale::Lithuanian, EOL };
     
    319319    const QLocale::Language *languages;
    320320    const QLocale::Country *countries;
     321    const char * const gettextRules;
    321322};
    322323
    323324static const NumerusTableEntry numerusTable[] = {
    324     { 0, 0, japaneseStyleForms, japaneseStyleLanguages, 0 },
    325     { englishStyleRules, sizeof(englishStyleRules), englishStyleForms, englishStyleLanguages, 0 },
     325    { 0, 0, japaneseStyleForms, japaneseStyleLanguages, 0, "nplurals=1; plural=0;" },
     326    { englishStyleRules, sizeof(englishStyleRules), englishStyleForms, englishStyleLanguages, 0,
     327      "nplurals=2; plural=(n != 1);" },
    326328    { frenchStyleRules, sizeof(frenchStyleRules), frenchStyleForms, frenchStyleLanguages,
    327       frenchStyleCountries },
    328     { latvianRules, sizeof(latvianRules), latvianForms, latvianLanguage, 0 },
    329     { icelandicRules, sizeof(icelandicRules), icelandicForms, icelandicLanguage, 0 },
    330     { irishStyleRules, sizeof(irishStyleRules), irishStyleForms, irishStyleLanguages, 0 },
    331     { slovakRules, sizeof(slovakRules), slovakForms, slovakLanguages, 0 },
    332     { macedonianRules, sizeof(macedonianRules), macedonianForms, macedonianLanguage, 0 },
    333     { lithuanianRules, sizeof(lithuanianRules), lithuanianForms, lithuanianLanguage, 0 },
    334     { russianStyleRules, sizeof(russianStyleRules), russianStyleForms, russianStyleLanguages, 0 },
    335     { polishRules, sizeof(polishRules), polishForms, polishLanguage, 0 },
    336     { romanianRules, sizeof(romanianRules), romanianForms, romanianLanguages, 0 },
    337     { slovenianRules, sizeof(slovenianRules), slovenianForms, slovenianLanguage, 0 },
    338     { malteseRules, sizeof(malteseRules), malteseForms, malteseLanguage, 0 },
    339     { welshRules, sizeof(welshRules), welshForms, welshLanguage, 0 },
    340     { arabicRules, sizeof(arabicRules), arabicForms, arabicLanguage, 0 },
    341     { tagalogRules, sizeof(tagalogRules), tagalogForms, tagalogLanguage, 0 },
    342     { catalanRules, sizeof(catalanRules), catalanForms, catalanLanguage, 0 }
     329      frenchStyleCountries, "nplurals=2; plural=(n > 1);" },
     330    { latvianRules, sizeof(latvianRules), latvianForms, latvianLanguage, 0,
     331      "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);" },
     332    { icelandicRules, sizeof(icelandicRules), icelandicForms, icelandicLanguage, 0,
     333      "nplurals=2; plural=(n%10==1 && n%100!=11 ? 0 : 1);" },
     334    { irishStyleRules, sizeof(irishStyleRules), irishStyleForms, irishStyleLanguages, 0,
     335      "nplurals=3; plural=(n==1 ? 0 : n==2 ? 1 : 2);" },
     336    { slovakStyleRules, sizeof(slovakStyleRules), slovakStyleForms, slovakStyleLanguages, 0,
     337      "nplurals=3; plural=((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2);" },
     338    { macedonianRules, sizeof(macedonianRules), macedonianForms, macedonianLanguage, 0,
     339      "nplurals=3; plural=(n%100==1 ? 0 : n%100==2 ? 1 : 2);" },
     340    { lithuanianRules, sizeof(lithuanianRules), lithuanianForms, lithuanianLanguage, 0,
     341      "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);" },
     342    { russianStyleRules, sizeof(russianStyleRules), russianStyleForms, russianStyleLanguages, 0,
     343      "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" },
     344    { polishRules, sizeof(polishRules), polishForms, polishLanguage, 0,
     345      "nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" },
     346    { romanianRules, sizeof(romanianRules), romanianForms, romanianLanguages, 0,
     347      "nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2);" },
     348    { slovenianRules, sizeof(slovenianRules), slovenianForms, slovenianLanguage, 0,
     349      "nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);" },
     350    { malteseRules, sizeof(malteseRules), malteseForms, malteseLanguage, 0,
     351      "nplurals=4; plural=(n==1 ? 0 : (n==0 || (n%100>=1 && n%100<=10)) ? 1 : (n%100>=11 && n%100<=19) ? 2 : 3);" },
     352    { welshRules, sizeof(welshRules), welshForms, welshLanguage, 0,
     353      "nplurals=5; plural=(n==0 ? 0 : n==1 ? 1 : (n>=2 && n<=5) ? 2 : n==6 ? 3 : 4);" },
     354    { arabicRules, sizeof(arabicRules), arabicForms, arabicLanguage, 0,
     355      "nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : (n%100>=3 && n%100<=10) ? 3 : n%100>=11 ? 4 : 5);" },
     356    { tagalogRules, sizeof(tagalogRules), tagalogForms, tagalogLanguage, 0,
     357      "nplurals=3; plural=(n==1 ? 0 : (n%10==4 || n%10==6 || n%10== 9) ? 1 : 2);" },
     358    { catalanRules, sizeof(catalanRules), catalanForms, catalanLanguage, 0,
     359      "nplurals=3; plural=(n==1 ? 0 : (n==11 || n/1000==11 || n/1000000==11 || n/1000000000==11) ? 1 : 2);" },
    343360};
    344361
     
    353370
    354371bool getNumerusInfo(QLocale::Language language, QLocale::Country country,
    355                            QByteArray *rules, QStringList *forms)
     372                    QByteArray *rules, QStringList *forms, const char **gettextRules)
    356373{
    357374    while (true) {
     
    366383                                                    entry.rulesSize);
    367384                    }
     385                    if (gettextRules)
     386                        *gettextRules = entry.gettextRules;
    368387                    if (forms) {
    369388                        forms->clear();
  • trunk/tools/linguist/shared/po.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4646#include <QtCore/QHash>
    4747#include <QtCore/QString>
     48#include <QtCore/QTextCodec>
    4849#include <QtCore/QTextStream>
    4950
    5051#include <ctype.h>
    51 
    52 #define MAGIC_OBSOLETE_REFERENCE "Obsolete_PO_entries"
    5352
    5453// Uncomment if you wish to hard wrap long lines in .po files. Note that this
     
    202201
    203202public:
    204     QString id;
    205     QString context;
    206     QString tscomment;
    207     QString oldTscomment;
    208     QString lineNumber;
    209     QString fileName;
    210     QString references;
    211     QString translatorComments;
    212     QString automaticComments;
    213     QString msgId;
    214     QString oldMsgId;
    215     QStringList msgStr;
     203    QByteArray id;
     204    QByteArray context;
     205    QByteArray tscomment;
     206    QByteArray oldTscomment;
     207    QByteArray lineNumber;
     208    QByteArray fileName;
     209    QByteArray references;
     210    QByteArray translatorComments;
     211    QByteArray automaticComments;
     212    QByteArray msgId;
     213    QByteArray oldMsgId;
     214    QList<QByteArray> msgStr;
    216215    bool isPlural;
    217216    bool isFuzzy;
     
    220219
    221220
    222 static bool isTranslationLine(const QString &line)
    223 {
    224     return line.startsWith(QLatin1String("#~ msgstr"))
    225            || line.startsWith(QLatin1String("msgstr"));
    226 }
    227 
    228 static QString slurpEscapedString(const QStringList &lines, int & l,
    229         int offset, const QString &prefix, ConversionData &cd)
    230 {
    231     QString msg;
     221static bool isTranslationLine(const QByteArray &line)
     222{
     223    return line.startsWith("#~ msgstr") || line.startsWith("msgstr");
     224}
     225
     226static QByteArray slurpEscapedString(const QList<QByteArray> &lines, int &l,
     227        int offset, const QByteArray &prefix, ConversionData &cd)
     228{
     229    QByteArray msg;
    232230    int stoff;
    233231
    234232    for (; l < lines.size(); ++l) {
    235         const QString &line = lines.at(l);
     233        const QByteArray &line = lines.at(l);
    236234        if (line.isEmpty() || !line.startsWith(prefix))
    237235            break;
    238         while (line[offset].isSpace()) // No length check, as string has no trailing spaces.
     236        while (isspace(line[offset])) // No length check, as string has no trailing spaces.
    239237            offset++;
    240         if (line[offset].unicode() != '"')
     238        if (line[offset] != '"')
    241239            break;
    242240        offset++;
     
    244242            if (offset == line.length())
    245243                goto premature_eol;
    246             ushort c = line[offset++].unicode();
     244            uchar c = line[offset++];
    247245            if (c == '"') {
    248246                if (offset == line.length())
    249247                    break;
    250                 while (line[offset].isSpace())
     248                while (isspace(line[offset]))
    251249                    offset++;
    252                 if (line[offset++].unicode() != '"') {
     250                if (line[offset++] != '"') {
    253251                    cd.appendError(QString::fromLatin1(
    254252                            "PO parsing error: extra characters on line %1.")
     
    261259                if (offset == line.length())
    262260                    goto premature_eol;
    263                 c = line[offset++].unicode();
     261                c = line[offset++];
    264262                switch (c) {
    265263                case 'r':
    266                     msg += QLatin1Char('\r'); // Maybe just throw it away?
     264                    msg += '\r'; // Maybe just throw it away?
    267265                    break;
    268266                case 'n':
    269                     msg += QLatin1Char('\n');
     267                    msg += '\n';
    270268                    break;
    271269                case 't':
    272                     msg += QLatin1Char('\t');
     270                    msg += '\t';
    273271                    break;
    274272                case 'v':
    275                     msg += QLatin1Char('\v');
     273                    msg += '\v';
    276274                    break;
    277275                case 'a':
    278                     msg += QLatin1Char('\a');
     276                    msg += '\a';
    279277                    break;
    280278                case 'b':
    281                     msg += QLatin1Char('\b');
     279                    msg += '\b';
    282280                    break;
    283281                case 'f':
    284                     msg += QLatin1Char('\f');
     282                    msg += '\f';
    285283                    break;
    286284                case '"':
    287                     msg += QLatin1Char('"');
     285                    msg += '"';
    288286                    break;
    289287                case '\\':
    290                     msg += QLatin1Char('\\');
     288                    msg += '\\';
    291289                    break;
    292290                case '0':
     
    299297                case '7':
    300298                    stoff = offset - 1;
    301                     while ((c = line[offset].unicode()) >= '0' && c <= '7')
     299                    while ((c = line[offset]) >= '0' && c <= '7')
    302300                        if (++offset == line.length())
    303301                            goto premature_eol;
    304                     msg += QChar(line.mid(stoff, offset - stoff).toUInt(0, 8));
     302                    msg += line.mid(stoff, offset - stoff).toUInt(0, 8);
    305303                    break;
    306304                case 'x':
    307305                    stoff = offset;
    308                     while (isxdigit(line[offset].unicode()))
     306                    while (isxdigit(line[offset]))
    309307                        if (++offset == line.length())
    310308                            goto premature_eol;
    311                     msg += QChar(line.mid(stoff, offset - stoff).toUInt(0, 16));
     309                    msg += line.mid(stoff, offset - stoff).toUInt(0, 16);
    312310                    break;
    313311                default:
    314312                    cd.appendError(QString::fromLatin1(
    315313                            "PO parsing error: invalid escape '\\%1' (line %2).")
    316                             .arg(QChar(c)).arg(l + 1));
    317                     msg += QLatin1Char('\\');
    318                     msg += QChar(c);
     314                            .arg(QChar((uint)c)).arg(l + 1));
     315                    msg += '\\';
     316                    msg += c;
    319317                    break;
    320318                }
    321319            } else {
    322                 msg += QChar(c);
     320                msg += c;
    323321            }
    324322        }
     
    331329    cd.appendError(QString::fromLatin1(
    332330            "PO parsing error: premature end of line %1.").arg(l + 1));
    333     return QString();
    334 }
    335 
    336 static void slurpComment(QString &msg, const QStringList &lines, int & l)
    337 {
    338     const QChar newline = QLatin1Char('\n');
    339     QString prefix = lines.at(l);
     331    return QByteArray();
     332}
     333
     334static void slurpComment(QByteArray &msg, const QList<QByteArray> &lines, int & l)
     335{
     336    QByteArray prefix = lines.at(l);
    340337    for (int i = 1; ; i++) {
    341         if (prefix.at(i).unicode() != ' ') {
     338        if (prefix.at(i) != ' ') {
    342339            prefix.truncate(i);
    343340            break;
     
    345342    }
    346343    for (; l < lines.size(); ++l) {
    347         const QString &line = lines.at(l);
     344        const QByteArray &line = lines.at(l);
    348345        if (line.startsWith(prefix))
    349346            msg += line.mid(prefix.size());
    350         else if (line != QLatin1String("#"))
    351             break;
    352         msg += newline;
     347        else if (line != "#")
     348            break;
     349        msg += '\n';
    353350    }
    354351    --l;
    355352}
    356353
     354static void splitContext(QByteArray *comment, QByteArray *context)
     355{
     356    char *data = comment->data();
     357    int len = comment->size();
     358    int sep = -1, j = 0;
     359
     360    for (int i = 0; i < len; i++, j++) {
     361        if (data[i] == '~' && i + 1 < len)
     362            i++;
     363        else if (data[i] == '|')
     364            sep = j;
     365        data[j] = data[i];
     366    }
     367    if (sep >= 0) {
     368        QByteArray tmp = comment->mid(sep + 1, j - sep - 1);
     369        comment->truncate(sep);
     370        *context = *comment;
     371        *comment = tmp;
     372    } else {
     373        comment->truncate(j);
     374    }
     375}
     376
     377static QString makePoHeader(const QString &str)
     378{
     379    return QLatin1String("po-header-") + str.toLower().replace(QLatin1Char('-'), QLatin1Char('_'));
     380}
     381
     382static QByteArray QByteArrayList_join(const QList<QByteArray> &that, char sep)
     383{
     384    int totalLength = 0;
     385    const int size = that.size();
     386
     387    for (int i = 0; i < size; ++i)
     388        totalLength += that.at(i).size();
     389
     390    if (size > 0)
     391        totalLength += size - 1;
     392
     393    QByteArray res;
     394    if (totalLength == 0)
     395        return res;
     396    res.reserve(totalLength);
     397    for (int i = 0; i < that.size(); ++i) {
     398        if (i)
     399            res += sep;
     400        res += that.at(i);
     401    }
     402    return res;
     403}
     404
    357405bool loadPO(Translator &translator, QIODevice &dev, ConversionData &cd)
    358406{
    359     const QChar quote = QLatin1Char('"');
    360     const QChar newline = QLatin1Char('\n');
    361     QTextStream in(&dev);
    362     in.setCodec(cd.m_codecForSource.isEmpty() ? QByteArray("UTF-8") : cd.m_codecForSource);
     407    QTextCodec *codec = QTextCodec::codecForName(
     408            cd.m_codecForSource.isEmpty() ? QByteArray("UTF-8") : cd.m_codecForSource);
    363409    bool error = false;
    364410
     
    381427
    382428    // we need line based lookahead below.
    383     QStringList lines;
    384     while (!in.atEnd())
    385         lines.append(in.readLine().trimmed());
    386     lines.append(QString());
    387 
    388     int l = 0;
     429    QList<QByteArray> lines;
     430    while (!dev.atEnd())
     431        lines.append(dev.readLine().trimmed());
     432    lines.append(QByteArray());
     433
     434    int l = 0, lastCmtLine = -1;
     435    bool qtContexts = false;
    389436    PoItem item;
    390437    for (; l != lines.size(); ++l) {
    391         QString line = lines.at(l);
     438        QByteArray line = lines.at(l);
    392439        if (line.isEmpty())
    393440           continue;
    394441        if (isTranslationLine(line)) {
    395             bool isObsolete = line.startsWith(QLatin1String("#~ msgstr"));
    396             const QString prefix = QLatin1String(isObsolete ? "#~ " : "");
     442            bool isObsolete = line.startsWith("#~ msgstr");
     443            const QByteArray prefix = isObsolete ? "#~ " : "";
    397444            while (true) {
    398                 int idx = line.indexOf(QLatin1Char(' '), prefix.length());
    399                 QString str = slurpEscapedString(lines, l, idx, prefix, cd);
     445                int idx = line.indexOf(' ', prefix.length());
     446                QByteArray str = slurpEscapedString(lines, l, idx, prefix, cd);
     447                item.msgStr.append(str);
     448                if (l + 1 >= lines.size() || !isTranslationLine(lines.at(l + 1)))
     449                    break;
     450                ++l;
     451                line = lines.at(l);
     452            }
     453            if (item.msgId.isEmpty()) {
     454                QHash<QString, QByteArray> extras;
     455                QList<QByteArray> hdrOrder;
     456                QByteArray pluralForms;
     457                foreach (const QByteArray &hdr, item.msgStr.first().split('\n')) {
     458                    if (hdr.isEmpty())
     459                        continue;
     460                    int idx = hdr.indexOf(':');
     461                    if (idx < 0) {
     462                        cd.appendError(QString::fromLatin1("Unexpected PO header format '%1'")
     463                            .arg(QString::fromLatin1(hdr)));
     464                        error = true;
     465                        break;
     466                    }
     467                    QByteArray hdrName = hdr.left(idx).trimmed();
     468                    QByteArray hdrValue = hdr.mid(idx + 1).trimmed();
     469                    hdrOrder << hdrName;
     470                    if (hdrName == "X-Language") {
     471                        translator.setLanguageCode(QString::fromLatin1(hdrValue));
     472                    } else if (hdrName == "X-Source-Language") {
     473                        translator.setSourceLanguageCode(QString::fromLatin1(hdrValue));
     474                    } else if (hdrName == "X-Qt-Contexts") {
     475                        qtContexts = (hdrValue == "true");
     476                    } else if (hdrName == "Plural-Forms") {
     477                        pluralForms  = hdrValue;
     478                    } else if (hdrName == "MIME-Version") {
     479                        // just assume it is 1.0
     480                    } else if (hdrName == "Content-Type") {
     481                        if (cd.m_codecForSource.isEmpty()) {
     482                            if (!hdrValue.startsWith("text/plain; charset=")) {
     483                                cd.appendError(QString::fromLatin1("Unexpected Content-Type header '%1'")
     484                                    .arg(QString::fromLatin1(hdrValue)));
     485                                error = true;
     486                                // This will avoid a flood of conversion errors.
     487                                codec = QTextCodec::codecForName("latin1");
     488                            } else {
     489                                QByteArray cod = hdrValue.mid(20);
     490                                QTextCodec *cdc = QTextCodec::codecForName(cod);
     491                                if (!cdc) {
     492                                    cd.appendError(QString::fromLatin1("Unsupported codec '%1'")
     493                                            .arg(QString::fromLatin1(cod)));
     494                                    error = true;
     495                                    // This will avoid a flood of conversion errors.
     496                                    codec = QTextCodec::codecForName("latin1");
     497                                } else {
     498                                    codec = cdc;
     499                                }
     500                            }
     501                        }
     502                    } else if (hdrName == "Content-Transfer-Encoding") {
     503                        if (hdrValue != "8bit") {
     504                            cd.appendError(QString::fromLatin1("Unexpected Content-Transfer-Encoding '%1'")
     505                                .arg(QString::fromLatin1(hdrValue)));
     506                            return false;
     507                        }
     508                    } else if (hdrName == "X-Virgin-Header") {
     509                        // legacy
     510                    } else {
     511                        extras[makePoHeader(QString::fromLatin1(hdrName))] = hdrValue;
     512                    }
     513                }
     514                if (!pluralForms.isEmpty()) {
     515                    if (translator.languageCode().isEmpty()) {
     516                        extras[makePoHeader(QLatin1String("Plural-Forms"))] = pluralForms;
     517                    } else {
     518                         // FIXME: have fun with making a consistency check ...
     519                    }
     520                }
     521                // Eliminate the field if only headers we added are present in standard order.
     522                // Keep in sync with savePO
     523                static const char * const dfltHdrs[] = {
     524                    "MIME-Version", "Content-Type", "Content-Transfer-Encoding",
     525                    "Plural-Forms", "X-Language", "X-Source-Language", "X-Qt-Contexts"
     526                };
     527                uint cdh = 0;
     528                for (int cho = 0; cho < hdrOrder.length(); cho++) {
     529                    for (;; cdh++) {
     530                        if (cdh == sizeof(dfltHdrs)/sizeof(dfltHdrs[0])) {
     531                            extras[QLatin1String("po-headers")] =
     532                                    QByteArrayList_join(hdrOrder, ',');
     533                            goto doneho;
     534                        }
     535                        if (hdrOrder.at(cho) == dfltHdrs[cdh]) {
     536                            cdh++;
     537                            break;
     538                        }
     539                    }
     540                }
     541              doneho:
     542                if (lastCmtLine != -1)
     543                    extras[QLatin1String("po-header_comment")] =
     544                            QByteArrayList_join(lines.mid(0, lastCmtLine + 1), '\n');
     545                for (QHash<QString, QByteArray>::ConstIterator it = extras.constBegin(),
     546                                                               end = extras.constEnd();
     547                     it != end; ++it)
     548                    translator.setExtra(it.key(), codec->toUnicode(it.value()));
     549                item = PoItem();
     550                continue;
     551            }
     552            // build translator message
     553            TranslatorMessage msg;
     554            msg.setContext(codec->toUnicode(item.context));
     555            if (!item.references.isEmpty()) {
     556                QString xrefs;
     557                foreach (const QString &ref,
     558                         codec->toUnicode(item.references).split(
     559                                 QRegExp(QLatin1String("\\s")), QString::SkipEmptyParts)) {
     560                    int pos = ref.indexOf(QLatin1Char(':'));
     561                    int lpos = ref.lastIndexOf(QLatin1Char(':'));
     562                    if (pos != -1 && pos == lpos) {
     563                        bool ok;
     564                        int lno = ref.mid(pos + 1).toInt(&ok);
     565                        if (ok) {
     566                            msg.addReference(ref.left(pos), lno);
     567                            continue;
     568                        }
     569                    }
     570                    if (!xrefs.isEmpty())
     571                        xrefs += QLatin1Char(' ');
     572                    xrefs += ref;
     573                }
     574                if (!xrefs.isEmpty())
     575                    item.extra[QLatin1String("po-references")] = xrefs;
     576            }
     577            msg.setId(codec->toUnicode(item.id));
     578            msg.setSourceText(codec->toUnicode(item.msgId));
     579            msg.setOldSourceText(codec->toUnicode(item.oldMsgId));
     580            msg.setComment(codec->toUnicode(item.tscomment));
     581            msg.setOldComment(codec->toUnicode(item.oldTscomment));
     582            msg.setExtraComment(codec->toUnicode(item.automaticComments));
     583            msg.setTranslatorComment(codec->toUnicode(item.translatorComments));
     584            msg.setPlural(item.isPlural || item.msgStr.size() > 1);
     585            QStringList translations;
     586            foreach (const QByteArray &bstr, item.msgStr) {
     587                QString str = codec->toUnicode(bstr);
    400588                str.replace(QChar(Translator::TextVariantSeparator),
    401589                            QChar(Translator::BinaryVariantSeparator));
    402                 item.msgStr.append(str);
    403                 if (l + 1 >= lines.size() || !isTranslationLine(lines.at(l + 1)))
    404                     break;
    405                 ++l;
    406                 line = lines.at(l);
    407             }
    408             if (item.msgId.isEmpty()) {
    409                 QRegExp rx(QLatin1String("\\bX-Language: ([^\n]*)\n"));
    410                 int idx = rx.indexIn(item.msgStr.first());
    411                 if (idx >= 0) {
    412                     translator.setLanguageCode(rx.cap(1));
    413                     item.msgStr.first().remove(idx, rx.matchedLength());
    414                 }
    415                 QRegExp rx2(QLatin1String("\\bX-Source-Language: ([^\n]*)\n"));
    416                 int idx2 = rx2.indexIn(item.msgStr.first());
    417                 if (idx2 >= 0) {
    418                     translator.setSourceLanguageCode(rx2.cap(1));
    419                     item.msgStr.first().remove(idx2, rx2.matchedLength());
    420                 }
    421                 if (item.msgStr.first().indexOf(
    422                         QRegExp(QLatin1String("\\bX-Virgin-Header:[^\n]*\n"))) >= 0) {
    423                     item = PoItem();
    424                     continue;
    425                 }
    426             }
    427             // build translator message
    428             TranslatorMessage msg;
    429             msg.setContext(item.context);
    430             if (!item.references.isEmpty()) {
    431                 foreach (const QString &ref,
    432                          item.references.split(QRegExp(QLatin1String("\\s")),
    433                                                QString::SkipEmptyParts)) {
    434                     int pos = ref.lastIndexOf(QLatin1Char(':'));
    435                     if (pos != -1)
    436                         msg.addReference(ref.left(pos), ref.mid(pos + 1).toInt());
    437                 }
    438             } else if (isObsolete) {
    439                 msg.setFileName(QLatin1String(MAGIC_OBSOLETE_REFERENCE));
    440             }
    441             msg.setId(item.id);
    442             msg.setSourceText(item.msgId);
    443             msg.setOldSourceText(item.oldMsgId);
    444             msg.setComment(item.tscomment);
    445             msg.setOldComment(item.oldTscomment);
    446             msg.setExtraComment(item.automaticComments);
    447             msg.setTranslatorComment(item.translatorComments);
    448             msg.setPlural(item.isPlural || item.msgStr.size() > 1);
    449             msg.setTranslations(item.msgStr);
     590                translations << str;
     591            }
     592            msg.setTranslations(translations);
    450593            if (isObsolete)
    451594                msg.setType(TranslatorMessage::Obsolete);
    452             else if (item.isFuzzy)
     595            else if (item.isFuzzy || (!msg.sourceText().isEmpty() && !msg.isTranslated()))
    453596                msg.setType(TranslatorMessage::Unfinished);
    454597            else
     
    461604            translator.append(msg);
    462605            item = PoItem();
    463         } else if (line.startsWith(QLatin1Char('#'))) {
    464             switch(line.size() < 2 ? 0 : line.at(1).unicode()) {
     606        } else if (line.startsWith('#')) {
     607            switch (line.size() < 2 ? 0 : line.at(1)) {
    465608                case ':':
    466609                    item.references += line.mid(3);
    467                     item.references += newline;
     610                    item.references += '\n';
    468611                    break;
    469612                case ',': {
    470613                    QStringList flags =
    471                             line.mid(2).split(QRegExp(QLatin1String("[, ]")),
    472                                               QString::SkipEmptyParts);
     614                            QString::fromLatin1(line.mid(2)).split(
     615                                    QRegExp(QLatin1String("[, ]")), QString::SkipEmptyParts);
    473616                    if (flags.removeOne(QLatin1String("fuzzy")))
    474617                        item.isFuzzy = true;
     618                    flags.removeOne(QLatin1String("qt-format"));
    475619                    TranslatorMessage::ExtraData::const_iterator it =
    476620                            item.extra.find(QLatin1String("po-flags"));
     
    482626                }
    483627                case 0:
    484                     item.translatorComments += newline;
     628                    item.translatorComments += '\n';
    485629                    break;
    486630                case ' ':
     
    488632                    break;
    489633                case '.':
    490                     if (line.startsWith(QLatin1String("#. ts-context "))) {
     634                    if (line.startsWith("#. ts-context ")) { // legacy
    491635                        item.context = line.mid(14);
    492                     } else if (line.startsWith(QLatin1String("#. ts-id "))) {
     636                    } else if (line.startsWith("#. ts-id ")) {
    493637                        item.id = line.mid(9);
    494638                    } else {
    495639                        item.automaticComments += line.mid(3);
    496                         item.automaticComments += newline;
     640                        item.automaticComments += '\n';
    497641                    }
    498642                    break;
    499643                case '|':
    500                     if (line.startsWith(QLatin1String("#| msgid "))) {
    501                         item.oldMsgId = slurpEscapedString(lines, l, 9, QLatin1String("#| "), cd);
    502                     } else if (line.startsWith(QLatin1String("#| msgid_plural "))) {
    503                         QString extra = slurpEscapedString(lines, l, 16, QLatin1String("#| "), cd);
     644                    if (line.startsWith("#| msgid ")) {
     645                        item.oldMsgId = slurpEscapedString(lines, l, 9, "#| ", cd);
     646                    } else if (line.startsWith("#| msgid_plural ")) {
     647                        QByteArray extra = slurpEscapedString(lines, l, 16, "#| ", cd);
    504648                        if (extra != item.oldMsgId)
    505                             item.extra[QLatin1String("po-old_msgid_plural")] = extra;
    506                     } else if (line.startsWith(QLatin1String("#| msgctxt "))) {
    507                         item.oldTscomment = slurpEscapedString(lines, l, 11, QLatin1String("#| "), cd);
     649                            item.extra[QLatin1String("po-old_msgid_plural")] =
     650                                    codec->toUnicode(extra);
     651                    } else if (line.startsWith("#| msgctxt ")) {
     652                        item.oldTscomment = slurpEscapedString(lines, l, 11, "#| ", cd);
     653                        if (qtContexts)
     654                            splitContext(&item.oldTscomment, &item.context);
    508655                    } else {
    509                         cd.appendError(QString(QLatin1String("PO-format parse error in line %1: '%2'\n"))
    510                             .arg(l + 1).arg(lines[l]));
     656                        cd.appendError(QString(QLatin1String("PO-format parse error in line %1: '%2'"))
     657                            .arg(l + 1).arg(codec->toUnicode(lines[l])));
    511658                        error = true;
    512659                    }
    513660                    break;
    514661                case '~':
    515                     if (line.startsWith(QLatin1String("#~ msgid "))) {
    516                         item.msgId = slurpEscapedString(lines, l, 9, QLatin1String("#~ "), cd);
    517                     } else if (line.startsWith(QLatin1String("#~ msgid_plural "))) {
    518                         QString extra = slurpEscapedString(lines, l, 16, QLatin1String("#~ "), cd);
     662                    if (line.startsWith("#~ msgid ")) {
     663                        item.msgId = slurpEscapedString(lines, l, 9, "#~ ", cd);
     664                    } else if (line.startsWith("#~ msgid_plural ")) {
     665                        QByteArray extra = slurpEscapedString(lines, l, 16, "#~ ", cd);
    519666                        if (extra != item.msgId)
    520                             item.extra[QLatin1String("po-msgid_plural")] = extra;
     667                            item.extra[QLatin1String("po-msgid_plural")] =
     668                                    codec->toUnicode(extra);
    521669                        item.isPlural = true;
    522                     } else if (line.startsWith(QLatin1String("#~ msgctxt "))) {
    523                         item.tscomment = slurpEscapedString(lines, l, 11, QLatin1String("#~ "), cd);
     670                    } else if (line.startsWith("#~ msgctxt ")) {
     671                        item.tscomment = slurpEscapedString(lines, l, 11, "#~ ", cd);
     672                        if (qtContexts)
     673                            splitContext(&item.tscomment, &item.context);
    524674                    } else {
    525                         cd.appendError(QString(QLatin1String("PO-format parse error in line %1: '%2'\n"))
    526                             .arg(l + 1).arg(lines[l]));
     675                        cd.appendError(QString(QLatin1String("PO-format parse error in line %1: '%2'"))
     676                            .arg(l + 1).arg(codec->toUnicode(lines[l])));
    527677                        error = true;
    528678                    }
    529679                    break;
    530680                default:
    531                     cd.appendError(QString(QLatin1String("PO-format parse error in line %1: '%2'\n"))
    532                         .arg(l + 1).arg(lines[l]));
     681                    cd.appendError(QString(QLatin1String("PO-format parse error in line %1: '%2'"))
     682                        .arg(l + 1).arg(codec->toUnicode(lines[l])));
    533683                    error = true;
    534684                    break;
    535685            }
    536         } else if (line.startsWith(QLatin1String("msgctxt "))) {
    537             item.tscomment = slurpEscapedString(lines, l, 8, QString(), cd);
    538         } else if (line.startsWith(QLatin1String("msgid "))) {
    539             item.msgId = slurpEscapedString(lines, l, 6, QString(), cd);
    540         } else if (line.startsWith(QLatin1String("msgid_plural "))) {
    541             QString extra = slurpEscapedString(lines, l, 13, QString(), cd);
     686            lastCmtLine = l;
     687        } else if (line.startsWith("msgctxt ")) {
     688            item.tscomment = slurpEscapedString(lines, l, 8, QByteArray(), cd);
     689            if (qtContexts)
     690                splitContext(&item.tscomment, &item.context);
     691        } else if (line.startsWith("msgid ")) {
     692            item.msgId = slurpEscapedString(lines, l, 6, QByteArray(), cd);
     693        } else if (line.startsWith("msgid_plural ")) {
     694            QByteArray extra = slurpEscapedString(lines, l, 13, QByteArray(), cd);
    542695            if (extra != item.msgId)
    543                 item.extra[QLatin1String("po-msgid_plural")] = extra;
     696                item.extra[QLatin1String("po-msgid_plural")] = codec->toUnicode(extra);
    544697            item.isPlural = true;
    545698        } else {
    546             cd.appendError(QString(QLatin1String("PO-format error in line %1: '%2'\n"))
    547                 .arg(l + 1).arg(lines[l]));
     699            cd.appendError(QString(QLatin1String("PO-format error in line %1: '%2'"))
     700                .arg(l + 1).arg(codec->toUnicode(lines[l])));
    548701            error = true;
    549702        }
     
    552705}
    553706
     707static void addPoHeader(Translator::ExtraData &headers, QStringList &hdrOrder,
     708                        const char *name, const QString &value)
     709{
     710    QString qName = QLatin1String(name);
     711    if (!hdrOrder.contains(qName))
     712        hdrOrder << qName;
     713    headers[makePoHeader(qName)] = value;
     714}
     715
     716static QString escapeComment(const QString &in, bool escape)
     717{
     718    QString out = in;
     719    if (escape) {
     720        out.replace(QLatin1Char('~'), QLatin1String("~~"));
     721        out.replace(QLatin1Char('|'), QLatin1String("~|"));
     722    }
     723    return out;
     724}
     725
    554726bool savePO(const Translator &translator, QIODevice &dev, ConversionData &cd)
    555727{
     728    QString str_format = QLatin1String("-format");
     729
    556730    bool ok = true;
    557731    QTextStream out(&dev);
    558732    out.setCodec(cd.m_outputCodec.isEmpty() ? QByteArray("UTF-8") : cd.m_outputCodec);
    559733
    560     bool first = true;
    561     if (translator.messages().isEmpty() || !translator.messages().first().sourceText().isEmpty()) {
    562         out <<
    563             "# SOME DESCRIPTIVE TITLE.\n"
    564             "# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER\n"
    565             "# This file is distributed under the same license as the PACKAGE package.\n"
    566             "# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.\n"
    567             "#\n"
    568             "#, fuzzy\n"
    569             "msgid \"\"\n"
    570             "msgstr \"\"\n"
    571             "\"X-Virgin-Header: remove this line if you change anything in the header.\\n\"\n";
    572         if (!translator.languageCode().isEmpty())
    573             out << "\"X-Language: " << translator.languageCode() << "\\n\"\n";
    574         if (!translator.sourceLanguageCode().isEmpty())
    575             out << "\"X-Source-Language: " << translator.sourceLanguageCode() << "\\n\"\n";
    576         first = false;
    577     }
     734    bool qtContexts = false;
     735    foreach (const TranslatorMessage &msg, translator.messages())
     736        if (!msg.context().isEmpty()) {
     737            qtContexts = true;
     738            break;
     739        }
     740
     741    QString cmt = translator.extra(QLatin1String("po-header_comment"));
     742    if (!cmt.isEmpty())
     743        out << cmt << '\n';
     744    out << "msgid \"\"\n";
     745    Translator::ExtraData headers = translator.extras();
     746    QStringList hdrOrder = translator.extra(QLatin1String("po-headers")).split(
     747            QLatin1Char(','), QString::SkipEmptyParts);
     748    // Keep in sync with loadPO
     749    addPoHeader(headers, hdrOrder, "MIME-Version", QLatin1String("1.0"));
     750    addPoHeader(headers, hdrOrder, "Content-Type",
     751                QLatin1String("text/plain; charset=" + out.codec()->name()));
     752    addPoHeader(headers, hdrOrder, "Content-Transfer-Encoding", QLatin1String("8bit"));
     753    if (!translator.languageCode().isEmpty()) {
     754        QLocale::Language l;
     755        QLocale::Country c;
     756        Translator::languageAndCountry(translator.languageCode(), &l, &c);
     757        const char *gettextRules;
     758        if (getNumerusInfo(l, c, 0, 0, &gettextRules))
     759            addPoHeader(headers, hdrOrder, "Plural-Forms", QLatin1String(gettextRules));
     760        addPoHeader(headers, hdrOrder, "X-Language", translator.languageCode());
     761    }
     762    if (!translator.sourceLanguageCode().isEmpty())
     763        addPoHeader(headers, hdrOrder, "X-Source-Language", translator.sourceLanguageCode());
     764    if (qtContexts)
     765        addPoHeader(headers, hdrOrder, "X-Qt-Contexts", QLatin1String("true"));
     766    QString hdrStr;
     767    foreach (const QString &hdr, hdrOrder) {
     768        hdrStr += hdr;
     769        hdrStr += QLatin1String(": ");
     770        hdrStr += headers.value(makePoHeader(hdr));
     771        hdrStr += QLatin1Char('\n');
     772    }
     773    out << poEscapedString(QString(), QString::fromLatin1("msgstr"), true, hdrStr);
     774
    578775    foreach (const TranslatorMessage &msg, translator.messages()) {
    579         if (!first)
    580             out << endl;
     776        out << endl;
    581777
    582778        if (!msg.translatorComment().isEmpty())
     
    586782            out << poEscapedLines(QLatin1String("#."), true, msg.extraComment());
    587783
    588         if (!msg.context().isEmpty())
    589             out << QLatin1String("#. ts-context ") << msg.context() << '\n';
    590784        if (!msg.id().isEmpty())
    591785            out << QLatin1String("#. ts-id ") << msg.id() << '\n';
    592786
    593         if (!msg.fileName().isEmpty() && msg.fileName() != QLatin1String(MAGIC_OBSOLETE_REFERENCE)) {
     787        QString xrefs = msg.extra(QLatin1String("po-references"));
     788        if (!msg.fileName().isEmpty() || !xrefs.isEmpty()) {
    594789            QStringList refs;
    595790            foreach (const TranslatorMessage::Reference &ref, msg.allReferences())
    596791                refs.append(QString(QLatin1String("%2:%1"))
    597792                                    .arg(ref.lineNumber()).arg(ref.fileName()));
     793            if (!xrefs.isEmpty())
     794                refs << xrefs;
    598795            out << poWrappedEscapedLines(QLatin1String("#:"), true, refs.join(QLatin1String(" ")));
    599796        }
    600797
    601798        bool noWrap = false;
     799        bool skipFormat = false;
    602800        QStringList flags;
    603         if (msg.type() == TranslatorMessage::Unfinished)
     801        if (msg.type() == TranslatorMessage::Unfinished && msg.isTranslated())
    604802            flags.append(QLatin1String("fuzzy"));
    605803        TranslatorMessage::ExtraData::const_iterator itr =
    606804                msg.extras().find(QLatin1String("po-flags"));
    607805        if (itr != msg.extras().end()) {
    608             if (itr->split(QLatin1String(", ")).contains(QLatin1String("no-wrap")))
     806            QStringList atoms = itr->split(QLatin1String(", "));
     807            foreach (const QString &atom, atoms)
     808                if (atom.endsWith(str_format)) {
     809                    skipFormat = true;
     810                    break;
     811                }
     812            if (atoms.contains(QLatin1String("no-wrap")))
    609813                noWrap = true;
    610814            flags.append(*itr);
    611815        }
     816        if (!skipFormat) {
     817            QString source = msg.sourceText();
     818            // This is fuzzy logic, as we don't know whether the string is
     819            // actually used with QString::arg().
     820            for (int off = 0; (off = source.indexOf(QLatin1Char('%'), off)) >= 0; ) {
     821                if (++off >= source.length())
     822                    break;
     823                if (source.at(off) == QLatin1Char('n') || source.at(off).isDigit()) {
     824                    flags.append(QLatin1String("qt-format"));
     825                    break;
     826                }
     827            }
     828        }
    612829        if (!flags.isEmpty())
    613830            out << "#, " << flags.join(QLatin1String(", ")) << '\n';
     
    615832        QString prefix = QLatin1String("#| ");
    616833        if (!msg.oldComment().isEmpty())
    617             out << poEscapedString(prefix, QLatin1String("msgctxt"), noWrap, msg.oldComment());
     834            out << poEscapedString(prefix, QLatin1String("msgctxt"), noWrap,
     835                                   escapeComment(msg.oldComment(), qtContexts));
    618836        if (!msg.oldSourceText().isEmpty())
    619837            out << poEscapedString(prefix, QLatin1String("msgid"), noWrap, msg.oldSourceText());
     
    622840            out << poEscapedString(prefix, QLatin1String("msgid_plural"), noWrap, plural);
    623841        prefix = QLatin1String((msg.type() == TranslatorMessage::Obsolete) ? "#~ " : "");
    624         if (!msg.comment().isEmpty())
    625             out << poEscapedString(prefix, QLatin1String("msgctxt"), noWrap, msg.comment());
     842        if (!msg.context().isEmpty())
     843            out << poEscapedString(prefix, QLatin1String("msgctxt"), noWrap,
     844                                   escapeComment(msg.context(), true) + QLatin1Char('|')
     845                                   + escapeComment(msg.comment(), true));
     846        else if (!msg.comment().isEmpty())
     847            out << poEscapedString(prefix, QLatin1String("msgctxt"), noWrap,
     848                                   escapeComment(msg.comment(), qtContexts));
    626849        out << poEscapedString(prefix, QLatin1String("msgid"), noWrap, msg.sourceText());
    627850        if (!msg.isPlural()) {
    628851            QString transl = msg.translation();
    629             if (first) {
    630                 transl.remove(QRegExp(QLatin1String("\\bX-Language:[^\n]*\n")));
    631                 if (!translator.languageCode().isEmpty())
    632                     transl += QLatin1String("X-Language: ") + translator.languageCode() + QLatin1Char('\n');
    633             }
     852            transl.replace(QChar(Translator::BinaryVariantSeparator),
     853                           QChar(Translator::TextVariantSeparator));
    634854            out << poEscapedString(prefix, QLatin1String("msgstr"), noWrap, transl);
    635855        } else {
     
    647867            }
    648868        }
    649         first = false;
    650869    }
    651870    return ok;
     871}
     872
     873static bool savePOT(const Translator &translator, QIODevice &dev, ConversionData &cd)
     874{
     875    Translator ttor = translator;
     876    ttor.dropTranslations();
     877    return savePO(ttor, dev, cd);
    652878}
    653879
     
    662888    format.priority = 1;
    663889    Translator::registerFileFormat(format);
     890    format.extension = QLatin1String("pot");
     891    format.description = QObject::tr("GNU Gettext localization template files");
     892    format.loader = &loadPO;
     893    format.saver = &savePOT;
     894    format.fileType = Translator::FileFormat::TranslationSource;
     895    format.priority = -1;
     896    Translator::registerFileFormat(format);
    664897    return 1;
    665898}
  • trunk/tools/linguist/shared/profileevaluator.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    26082608{
    26092609    if (d->m_verbose && !d->m_skipLevel)
    2610         qWarning("%s", qPrintable(message));
     2610        fprintf(stderr, "%s\n", qPrintable(message));
    26112611}
    26122612
     
    26142614{
    26152615    if (!d->m_skipLevel)
    2616         qWarning("%s", qPrintable(message));
     2616        fprintf(stderr, "%s\n", qPrintable(message));
    26172617}
    26182618
     
    26202620{
    26212621    if (!d->m_skipLevel)
    2622         qWarning("%s", qPrintable(message));
     2622        fprintf(stderr, "%s\n", qPrintable(message));
    26232623}
    26242624
  • trunk/tools/linguist/shared/profileevaluator.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/shared/proitems.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/shared/proitems.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/shared/proparserutils.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/shared/qm.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    565565    QStringList numerusForms;
    566566    bool guessPlurals = true;
    567     if (getNumerusInfo(l, c, 0, &numerusForms))
     567    if (getNumerusInfo(l, c, 0, &numerusForms, 0))
    568568        guessPlurals = (numerusForms.count() == 1);
    569569
     
    705705    Translator::languageAndCountry(translator.languageCode(), &l, &c);
    706706    QByteArray rules;
    707     if (getNumerusInfo(l, c, &rules, 0))
     707    if (getNumerusInfo(l, c, &rules, 0, 0))
    708708        releaser.setNumerusRules(rules);
    709709    releaser.setCodecName(translator.codecName());
     
    774774        int generatedCount = finished + unfinished;
    775775        cd.appendError(QCoreApplication::translate("LRelease",
    776             "    Generated %n translation(s) (%1 finished and %2 unfinished)\n", 0,
     776            "    Generated %n translation(s) (%1 finished and %2 unfinished)", 0,
    777777            QCoreApplication::CodecForTr, generatedCount).arg(finished).arg(unfinished));
    778778        if (untranslated)
    779779            cd.appendError(QCoreApplication::translate("LRelease",
    780                 "    Ignored %n untranslated source text(s)\n", 0,
     780                "    Ignored %n untranslated source text(s)", 0,
    781781                QCoreApplication::CodecForTr, untranslated));
    782782    }
  • trunk/tools/linguist/shared/qph.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/shared/simtexth.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/shared/simtexth.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/shared/translator.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4444#include "simtexth.h"
    4545
     46#include <iostream>
     47
    4648#include <stdio.h>
    4749#ifdef Q_OS_WIN
    48 #include <io.h> // required for _setmode, to avoid _O_TEXT streams...
    49 #include <fcntl.h> // for _O_BINARY
     50// required for _setmode, to avoid _O_TEXT streams...
     51# ifdef Q_OS_WINCE
     52#  include <stdlib.h>
     53# else
     54#  include <io.h> // for _setmode
     55#  include <fcntl.h> // for _O_BINARY
     56# endif
    5057#endif
    5158
     
    214221#ifdef Q_OS_WIN
    215222        // QFile is broken for text files
     223# ifdef Q_OS_WINCE
     224        ::_setmode(stdin, _O_BINARY);
     225# else
    216226        ::_setmode(0, _O_BINARY);
     227# endif
    217228#endif
    218229        if (!file.open(stdin, QIODevice::ReadOnly)) {
     
    254265#ifdef Q_OS_WIN
    255266        // QFile is broken for text files
     267# ifdef Q_OS_WINCE
     268        ::_setmode(stdout, _O_BINARY);
     269# else
    256270        ::_setmode(1, _O_BINARY);
     271# endif
    257272#endif
    258273        if (!file.open(stdout, QIODevice::WriteOnly)) {
     
    574589{
    575590    if (!dupes.byId.isEmpty() || !dupes.byContents.isEmpty()) {
     591        std::cerr << "Warning: dropping duplicate messages in '" << qPrintable(fileName);
    576592        if (!verbose) {
    577             qWarning("Warning: dropping duplicate messages in '%s'\n(try -verbose for more info).",
    578                      qPrintable(fileName));
     593            std::cerr << "'\n(try -verbose for more info).\n";
    579594        } else {
    580             qWarning("Warning: dropping duplicate messages in '%s':", qPrintable(fileName));
     595            std::cerr << "':\n";
    581596            foreach (int i, dupes.byId)
    582                 qWarning("\n* ID: %s", qPrintable(message(i).id()));
     597                std::cerr << "\n* ID: " << qPrintable(message(i).id()) << std::endl;
    583598            foreach (int j, dupes.byContents) {
    584599                const TranslatorMessage &msg = message(j);
    585                 qWarning("\n* Context: %s\n* Source: %s",
    586                         qPrintable(msg.context()),
    587                         qPrintable(msg.sourceText()));
     600                std::cerr << "\n* Context: " << qPrintable(msg.context())
     601                          << "\n* Source: " << qPrintable(msg.sourceText()) << std::endl;
    588602                if (!msg.comment().isEmpty())
    589                     qWarning("* Comment: %s", qPrintable(msg.comment()));
     603                    std::cerr << "* Comment: " << qPrintable(msg.comment()) << std::endl;
    590604            }
    591             qWarning();
     605            std::cerr << std::endl;
    592606        }
    593607    }
     
    653667    if (l != QLocale::C) {
    654668        QStringList forms;
    655         if (getNumerusInfo(l, c, 0, &forms))
     669        if (getNumerusInfo(l, c, 0, &forms, 0))
    656670            numPlurals = forms.count(); // includes singular
    657671    }
     
    676690            "Removed plural forms as the target language has less "
    677691            "forms.\nIf this sounds wrong, possibly the target language is "
    678             "not set or recognized.\n"));
     692            "not set or recognized."));
    679693}
    680694
     
    725739    if (!codec) {
    726740        if (!name.isEmpty())
    727             qWarning("No QTextCodec for %s available. Using Latin1\n", name.constData());
     741            std::cerr << "No QTextCodec for " << name.constData() << " available. Using Latin1.\n";
    728742        m_codec = QTextCodec::codecForName("ISO-8859-1");
    729743    } else {
  • trunk/tools/linguist/shared/translator.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    9393
    9494    void appendError(const QString &error) { m_errors.append(error); }
    95     QString error() const { return  m_errors.join(QLatin1String("\n")); }
     95    QString error() const { return m_errors.isEmpty() ? QString() : m_errors.join(QLatin1String("\n")) + QLatin1Char('\n'); }
    9696    QStringList errors() const { return  m_errors; }
    9797    void clearErrors() { m_errors.clear(); }
     
    124124    Translator();
    125125
    126     bool load(const QString &filename, ConversionData &err, const QString &format /*= "auto"*/);
    127     bool save(const QString &filename, ConversionData &err, const QString &format /*= "auto"*/) const;
     126    bool load(const QString &filename, ConversionData &err, const QString &format /* = "auto" */);
     127    bool save(const QString &filename, ConversionData &err, const QString &format /* = "auto" */) const;
    128128    bool release(QFile *iod, ConversionData &cd) const;
    129129
     
    234234
    235235bool getNumerusInfo(QLocale::Language language, QLocale::Country country,
    236                            QByteArray *rules, QStringList *forms);
     236                    QByteArray *rules, QStringList *forms, const char **gettextRules);
    237237
    238238/*
  • trunk/tools/linguist/shared/translatormessage.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/shared/translatormessage.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/shared/ts.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/tools/linguist/shared/ts.dtd

    r561 r846  
    55 ! The location element is set as optional since it was introduced first in Qt 4.2.
    66 ! The userdata element is set as optional since it was introduced first in Qt 4.4.
    7  ! The source and translation elements are optional starting with version 3.0
    8  ! (Qt 4.6) to support S60 blank messages.
    97 !
    108  -->
     
    3735<!-- The encoding to use in the QM file by default. Default is ISO-8859-1. -->
    3836<!ELEMENT defaultcodec (#PCDATA) >
    39 <!ELEMENT context (name?, comment?, (context|message)+) >
     37<!ELEMENT context (name, comment?, (context|message)+) >
    4038<!ATTLIST context
    4139          encoding CDATA #IMPLIED>
    4240<!ELEMENT name %evilstring; >
    43 <!-- If "no", then the context nesting is for informational puposes only -->
    44 <!ATTLIST name
    45           nest (yes|no) "yes">
    4641<!-- This is "disambiguation" in the (new) API, or "msgctxt" in gettext speak -->
    4742<!ELEMENT comment %evilstring; >
     
    5449<!ELEMENT message (location*, source?, oldsource?, comment?, oldcomment?, extracomment?, translatorcomment?, translation?, userdata?, extra-**) >
    5550<!--
    56  ! If utf8 is true, the defaultcodec is overridden and the message is encoded
    57  ! in UTF-8 in the QM file.
     51 ! If utf8 is "true", the defaultcodec is overridden and the message is encoded
     52 ! in UTF-8 in the QM file. If it is "both", both source encodings are stored
     53 ! in the QM file.
    5854  -->
    5955<!ATTLIST message
    6056          id CDATA #IMPLIED
    61           utf8 (true|false) "false"
     57          utf8 (true|false|both) "false"
    6258          numerus (yes|no) "no">
    6359<!ELEMENT location EMPTY>
     
    10197<!ELEMENT numerusform (#PCDATA|byte|lengthvariant)* >
    10298<!ATTLIST numerusform
    103           plurality (nullar|singular|dual|trial|paucal|greaterpaucal|plural|greaterplural) #IMPLIED>
    10499          variants (yes|no) "no">
    105100<!ELEMENT lengthvariant %evilstring; >
    106 <!--
    107  ! The translation variants have a priority between 1 ("highest") and 9 ("lowest")
    108  ! Typically longer translations get a higher priority.
    109  ! If omitted, the order of appearance of the variants in the TS files is used.
    110   -->
    111 <!ATTLIST lengthvariant
    112           priority (1|2|3|4|5|6|7|8|9) #IMPLIED>
    113          
  • trunk/tools/linguist/shared/xliff.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5454
    5555
     56// The string value is historical and reflects the main purpose: Keeping
     57// obsolete entries separate from the magic file message (which both have
     58// no location information, but typically reside at opposite ends of the file).
     59#define MAGIC_OBSOLETE_REFERENCE "Obsolete_PO_entries"
     60
    5661QT_BEGIN_NAMESPACE
    5762
     
    504509        m_sourceLanguage = atts.value(QLatin1String("source-language"));
    505510        m_sourceLanguage.replace(QLatin1Char('-'), QLatin1Char('_'));
     511        if (m_sourceLanguage == QLatin1String("en"))
     512            m_sourceLanguage.clear();
    506513    } else if (localName == QLatin1String("group")) {
    507514        if (atts.value(QLatin1String("restype")) == QLatin1String(restypeContext)) {
     
    691698        return false;
    692699    }
     700    if (m_type == TranslatorMessage::Obsolete && m_refs.size() == 1
     701        && m_refs.at(0).fileName() == QLatin1String(MAGIC_OBSOLETE_REFERENCE))
     702        m_refs.clear();
    693703    TranslatorMessage msg(m_context, m_sources[0],
    694704                          m_comment, QString(), QString(), -1,
     
    760770    QList<QString> fileOrder;
    761771    foreach (const TranslatorMessage &msg, translator.messages()) {
    762         QHash<QString, QList<TranslatorMessage> > &file = messageOrder[msg.fileName()];
     772        QString fn = msg.fileName();
     773        if (fn.isEmpty() && msg.type() == TranslatorMessage::Obsolete)
     774            fn = QLatin1String(MAGIC_OBSOLETE_REFERENCE);
     775        QHash<QString, QList<TranslatorMessage> > &file = messageOrder[fn];
    763776        if (file.isEmpty())
    764             fileOrder.append(msg.fileName());
     777            fileOrder.append(fn);
    765778        QList<TranslatorMessage> &context = file[msg.context()];
    766779        if (context.isEmpty())
    767             contextOrder[msg.fileName()].append(msg.context());
     780            contextOrder[fn].append(msg.context());
    768781        context.append(msg);
    769782    }
Note: See TracChangeset for help on using the changeset viewer.