From 9e06896a9a49685dc97eb2aafdf55eef33a75507 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Mon, 22 Nov 2010 15:40:25 +0100 Subject: Make lupdate recognize TRANSLATOR comments in QtScript files - Made the output translator a member of the parser, since the processComment() callback needs it now. - Made the context for tr()/TR_NOOP() a member of the parser, since it should persist for subsequent tr calls. - The comment processing logic should match that of cpp.cpp, as usual. Task-number: QTBUG-15502 Reviewed-by: Oswald Buddenhagen --- .../lupdate/testdata/good/parsejscontexts/main.js | 29 ++++++++ .../testdata/good/parsejscontexts/project.pro | 3 + .../good/parsejscontexts/project.ts.result | 81 ++++++++++++++++++++++ tools/linguist/lupdate/qscript.cpp | 52 ++++++++++++-- tools/linguist/lupdate/qscript.g | 52 ++++++++++++-- 5 files changed, 205 insertions(+), 12 deletions(-) create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsejscontexts/main.js create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsejscontexts/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsejscontexts/project.ts.result diff --git a/tests/auto/linguist/lupdate/testdata/good/parsejscontexts/main.js b/tests/auto/linguist/lupdate/testdata/good/parsejscontexts/main.js new file mode 100644 index 0000000..aa510c1 --- /dev/null +++ b/tests/auto/linguist/lupdate/testdata/good/parsejscontexts/main.js @@ -0,0 +1,29 @@ +// No context specified, default should be used. +qsTr("One"); +QT_TR_NOOP("Two"); + +// TRANSLATOR Foo +qsTr("Three"); +QT_TR_NOOP("Four"); + +// TRANSLATOR Bar +qsTr("Five"); + +/* + TRANSLATOR Baz + This is a comment to the translator. +*/ +QT_TR_NOOP("Six"); + +// TRANSLATOR Foo.Bar +qsTr("Seven"); + +/* TRANSLATOR Bar::Baz */ +QT_TR_NOOP("Eight"); + +// qsTranslate() context is not affected. +qsTranslate("Foo", "Nine"); + +// Empty context. +// TRANSLATOR +qsTr("Ten"); diff --git a/tests/auto/linguist/lupdate/testdata/good/parsejscontexts/project.pro b/tests/auto/linguist/lupdate/testdata/good/parsejscontexts/project.pro new file mode 100644 index 0000000..d549039 --- /dev/null +++ b/tests/auto/linguist/lupdate/testdata/good/parsejscontexts/project.pro @@ -0,0 +1,3 @@ +SOURCES += main.js + +TRANSLATIONS = project.ts diff --git a/tests/auto/linguist/lupdate/testdata/good/parsejscontexts/project.ts.result b/tests/auto/linguist/lupdate/testdata/good/parsejscontexts/project.ts.result new file mode 100644 index 0000000..18407b2 --- /dev/null +++ b/tests/auto/linguist/lupdate/testdata/good/parsejscontexts/project.ts.result @@ -0,0 +1,81 @@ + + + + + + + + Ten + + + + + Bar + + + Five + + + + + Bar::Baz + + + Eight + + + + + Baz + + + + This is a comment to the translator. + + + + + Six + + + + + Foo + + + Three + + + + + Four + + + + + Nine + + + + + Foo.Bar + + + Seven + + + + + main + + + One + + + + + Two + + + + diff --git a/tools/linguist/lupdate/qscript.cpp b/tools/linguist/lupdate/qscript.cpp index 5323022..f9aff34 100644 --- a/tools/linguist/lupdate/qscript.cpp +++ b/tools/linguist/lupdate/qscript.cpp @@ -67,6 +67,8 @@ class LU { Q_DECLARE_TR_FUNCTIONS(LUpdate) }; +static QString MagicComment(QLatin1String("TRANSLATOR")); + class QScriptGrammar { public: @@ -2092,8 +2094,9 @@ public: ~QScriptParser(); void setLexer(QScript::Lexer *); + void setTranslator(Translator *); - bool parse(Translator *translator); + bool parse(); QString fileName() const { return lexer->fileName(); } @@ -2129,6 +2132,8 @@ protected: private: QScript::Lexer *lexer; + Translator *translator; + QString trcontext; QString extracomment; QString msgid; QString sourcetext; @@ -2160,7 +2165,8 @@ QScriptParser::QScriptParser(): sym_stack(0), state_stack(0), location_stack(0), - lexer(0) + lexer(0), + translator(0) { } @@ -2187,9 +2193,17 @@ void QScriptParser::setLexer(QScript::Lexer *lex) lexer = lex; } -bool QScriptParser::parse(Translator *translator) +void QScriptParser::setTranslator(Translator *tor) +{ + translator = tor; +} + +bool QScriptParser::parse() { Q_ASSERT(lexer != 0); + Q_ASSERT(translator != 0); + trcontext = QFileInfo(fileName()).baseName(); + const int INITIAL_STATE = 0; int yytoken = -1; @@ -2303,11 +2317,10 @@ case 66: { if (args.at(0).type() != QVariant::String) { yyMsg(identLineNo) << qPrintable(LU::tr("%1(): text to translate must be a literal string.\n").arg(name)); } else { - QString context = QFileInfo(fileName()).baseName(); QString text = args.at(0).toString(); QString comment = args.value(1).toString(); bool plural = (args.size() > 2); - recordMessage(translator, context, text, comment, extracomment, + recordMessage(translator, trcontext, text, comment, extracomment, msgid, extra, plural, fileName(), identLineNo); } } @@ -2533,6 +2546,32 @@ void QScriptParser::processComment(const QChar *chars, int length) } } sourcetext.resize(ptr - (ushort *)sourcetext.data()); + } else { + int idx = 0; + ushort c; + while ((c = chars[idx].unicode()) == ' ' || c == '\t' || c == '\n') + ++idx; + if (!memcmp(chars + idx, MagicComment.unicode(), MagicComment.length() * 2)) { + idx += MagicComment.length(); + QString comment = QString(chars + idx, length - idx).simplified(); + int k = comment.indexOf(QLatin1Char(' ')); + if (k == -1) { + trcontext = comment; + } else { + trcontext = comment.left(k); + comment.remove(0, k + 1); + TranslatorMessage msg( + trcontext, QString(), + comment, QString(), + fileName(), lexer->startLineNo(), QStringList(), + TranslatorMessage::Finished, /*plural=*/false); + msg.setExtraComment(extracomment.simplified()); + extracomment.clear(); + translator->append(msg); + translator->setExtras(extra); + extra.clear(); + } + } } } @@ -2558,7 +2597,8 @@ bool loadQScript(Translator &translator, const QString &filename, ConversionData QScript::Lexer lexer(&parser); lexer.setCode(code, filename, /*lineNumber=*/1); parser.setLexer(&lexer); - if (!parser.parse(&translator)) { + parser.setTranslator(&translator); + if (!parser.parse()) { std::cerr << qPrintable(filename) << ':' << parser.errorLineNumber() << ": " << qPrintable(parser.errorMessage()) << std::endl; return false; diff --git a/tools/linguist/lupdate/qscript.g b/tools/linguist/lupdate/qscript.g index 3655f2e..1335f55 100644 --- a/tools/linguist/lupdate/qscript.g +++ b/tools/linguist/lupdate/qscript.g @@ -104,6 +104,8 @@ class LU { Q_DECLARE_TR_FUNCTIONS(LUpdate) }; +static QString MagicComment(QLatin1String("TRANSLATOR")); + static void recordMessage( Translator *tor, const QString &context, const QString &text, const QString &comment, const QString &extracomment, const QString &msgid, const TranslatorMessage::ExtraData &extra, @@ -1423,8 +1425,9 @@ public: ~QScriptParser(); void setLexer(QScript::Lexer *); + void setTranslator(Translator *); - bool parse(Translator *translator); + bool parse(); QString fileName() const { return lexer->fileName(); } @@ -1460,6 +1463,8 @@ protected: private: QScript::Lexer *lexer; + Translator *translator; + QString trcontext; QString extracomment; QString msgid; QString sourcetext; @@ -1491,7 +1496,8 @@ QScriptParser::QScriptParser(): sym_stack(0), state_stack(0), location_stack(0), - lexer(0) + lexer(0), + translator(0) { } @@ -1518,9 +1524,17 @@ void QScriptParser::setLexer(QScript::Lexer *lex) lexer = lex; } -bool QScriptParser::parse(Translator *translator) +void QScriptParser::setTranslator(Translator *tor) +{ + translator = tor; +} + +bool QScriptParser::parse() { Q_ASSERT(lexer != 0); + Q_ASSERT(translator != 0); + trcontext = QFileInfo(fileName()).baseName(); + const int INITIAL_STATE = 0; int yytoken = -1; @@ -1719,11 +1733,10 @@ case $rule_number: { if (args.at(0).type() != QVariant::String) { yyMsg(identLineNo) << qPrintable(LU::tr("%1(): text to translate must be a literal string.\n").arg(name)); } else { - QString context = QFileInfo(fileName()).baseName(); QString text = args.at(0).toString(); QString comment = args.value(1).toString(); bool plural = (args.size() > 2); - recordMessage(translator, context, text, comment, extracomment, + recordMessage(translator, trcontext, text, comment, extracomment, msgid, extra, plural, fileName(), identLineNo); } } @@ -2181,6 +2194,32 @@ void QScriptParser::processComment(const QChar *chars, int length) } } sourcetext.resize(ptr - (ushort *)sourcetext.data()); + } else { + int idx = 0; + ushort c; + while ((c = chars[idx].unicode()) == ' ' || c == '\t' || c == '\n') + ++idx; + if (!memcmp(chars + idx, MagicComment.unicode(), MagicComment.length() * 2)) { + idx += MagicComment.length(); + QString comment = QString(chars + idx, length - idx).simplified(); + int k = comment.indexOf(QLatin1Char(' ')); + if (k == -1) { + trcontext = comment; + } else { + trcontext = comment.left(k); + comment.remove(0, k + 1); + TranslatorMessage msg( + trcontext, QString(), + comment, QString(), + fileName(), lexer->startLineNo(), QStringList(), + TranslatorMessage::Finished, /*plural=*/false); + msg.setExtraComment(extracomment.simplified()); + extracomment.clear(); + translator->append(msg); + translator->setExtras(extra); + extra.clear(); + } + } } } @@ -2206,7 +2245,8 @@ bool loadQScript(Translator &translator, const QString &filename, ConversionData QScript::Lexer lexer(&parser); lexer.setCode(code, filename, /*lineNumber=*/1); parser.setLexer(&lexer); - if (!parser.parse(&translator)) { + parser.setTranslator(&translator); + if (!parser.parse()) { std::cerr << qPrintable(filename) << ':' << parser.errorLineNumber() << ": " << qPrintable(parser.errorMessage()) << std::endl; return false; -- cgit v0.12