From 058ba4d19b296464f87504bdc2a2076ee1368e57 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Mon, 12 Apr 2010 16:55:37 +0200 Subject: Make qsTr work in global scope Search up the call stack to find the first non-empty source URL. Also and add an autotest for the QtScript translator functions since there was none (their presence was checked, but not their behavior...). Task-number: QTBUG-9775 Reviewed-by: Olivier Goffart --- src/script/api/qscriptengine.cpp | 16 +++++++-- tests/auto/qscriptengine/qscriptengine.pro | 1 + tests/auto/qscriptengine/qscriptengine.qrc | 5 +++ tests/auto/qscriptengine/translatable.js | 7 ++++ .../qscriptengine/translations/translatable_la.qm | Bin 0 -> 241 bytes .../qscriptengine/translations/translatable_la.ts | 34 ++++++++++++++++++ tests/auto/qscriptengine/tst_qscriptengine.cpp | 40 +++++++++++++++++++++ 7 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 tests/auto/qscriptengine/qscriptengine.qrc create mode 100644 tests/auto/qscriptengine/translatable.js create mode 100644 tests/auto/qscriptengine/translations/translatable_la.qm create mode 100644 tests/auto/qscriptengine/translations/translatable_la.ts diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 2422108..ccd3e56 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -41,6 +41,7 @@ #include #include +#include "CodeBlock.h" #include "Error.h" #include "JSArray.h" #include "JSLock.h" @@ -699,9 +700,18 @@ JSC::JSValue JSC_HOST_CALL functionQsTr(JSC::ExecState *exec, JSC::JSObject*, JS return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): third argument (n) must be a number"); #ifndef QT_NO_QOBJECT QString context; - QScriptContext *ctx = QScriptEnginePrivate::contextForFrame(exec); - if (ctx && ctx->parentContext()) - context = QFileInfo(QScriptContextInfo(ctx->parentContext()).fileName()).baseName(); + // The first non-empty source URL in the call stack determines the translation context. + { + JSC::ExecState *frame = exec->removeHostCallFrameFlag(); + while (frame) { + if (frame->codeBlock() && frame->codeBlock()->source() + && !frame->codeBlock()->source()->url().isEmpty()) { + context = QFileInfo(frame->codeBlock()->source()->url()).baseName(); + break; + } + frame = frame->callerFrame()->removeHostCallFrameFlag(); + } + } #endif QString text(args.at(0).toString(exec)); #ifndef QT_NO_QOBJECT diff --git a/tests/auto/qscriptengine/qscriptengine.pro b/tests/auto/qscriptengine/qscriptengine.pro index dd058a4..7d0f5d0 100644 --- a/tests/auto/qscriptengine/qscriptengine.pro +++ b/tests/auto/qscriptengine/qscriptengine.pro @@ -1,6 +1,7 @@ load(qttest_p4) QT = core gui script SOURCES += tst_qscriptengine.cpp +RESOURCES += qscriptengine.qrc wince* { DEFINES += SRCDIR=\\\"./\\\" diff --git a/tests/auto/qscriptengine/qscriptengine.qrc b/tests/auto/qscriptengine/qscriptengine.qrc new file mode 100644 index 0000000..b87f985 --- /dev/null +++ b/tests/auto/qscriptengine/qscriptengine.qrc @@ -0,0 +1,5 @@ + + + translations/translatable_la.qm + + diff --git a/tests/auto/qscriptengine/translatable.js b/tests/auto/qscriptengine/translatable.js new file mode 100644 index 0000000..0c948e7 --- /dev/null +++ b/tests/auto/qscriptengine/translatable.js @@ -0,0 +1,7 @@ +qsTr("One"); +qsTranslate("FooContext", "Two"); + +var greeting_strings = [ + QT_TR_NOOP("Hello"), + QT_TRANSLATE_NOOP("FooContext", "Goodbye") +]; diff --git a/tests/auto/qscriptengine/translations/translatable_la.qm b/tests/auto/qscriptengine/translations/translatable_la.qm new file mode 100644 index 0000000..03fcc52 Binary files /dev/null and b/tests/auto/qscriptengine/translations/translatable_la.qm differ diff --git a/tests/auto/qscriptengine/translations/translatable_la.ts b/tests/auto/qscriptengine/translations/translatable_la.ts new file mode 100644 index 0000000..3f631de --- /dev/null +++ b/tests/auto/qscriptengine/translations/translatable_la.ts @@ -0,0 +1,34 @@ + + + + + FooContext + + + Two + To + + + + Goodbye + Farvel + + + + translatable + + + One + En + + + + Hello + Hallo + + + Goodbye + Farvel + + + diff --git a/tests/auto/qscriptengine/tst_qscriptengine.cpp b/tests/auto/qscriptengine/tst_qscriptengine.cpp index f556fa1..aa5c85d 100644 --- a/tests/auto/qscriptengine/tst_qscriptengine.cpp +++ b/tests/auto/qscriptengine/tst_qscriptengine.cpp @@ -154,6 +154,7 @@ private slots: void incDecNonObjectProperty(); void installTranslatorFunctions_data(); void installTranslatorFunctions(); + void translateScript(); void functionScopes(); void nativeFunctionScopes(); void evaluateProgram(); @@ -4314,6 +4315,45 @@ void tst_QScriptEngine::installTranslatorFunctions() } } +void tst_QScriptEngine::translateScript() +{ + QScriptEngine engine; + + QTranslator translator; + translator.load(":/translations/translatable_la"); + QCoreApplication::instance()->installTranslator(&translator); + engine.installTranslatorFunctions(); + + QString fileName = QString::fromLatin1("translatable.js"); + // Top-level + QCOMPARE(engine.evaluate("qsTr('One')", fileName).toString(), QString::fromLatin1("En")); + QCOMPARE(engine.evaluate("qsTr('Hello')", fileName).toString(), QString::fromLatin1("Hallo")); + // From function + QCOMPARE(engine.evaluate("(function() { return qsTr('One'); })()", fileName).toString(), QString::fromLatin1("En")); + QCOMPARE(engine.evaluate("(function() { return qsTr('Hello'); })()", fileName).toString(), QString::fromLatin1("Hallo")); + // From eval + QCOMPARE(engine.evaluate("eval('qsTr(\\'One\\')')", fileName).toString(), QString::fromLatin1("En")); + QCOMPARE(engine.evaluate("eval('qsTr(\\'Hello\\')')", fileName).toString(), QString::fromLatin1("Hallo")); + + QCOMPARE(engine.evaluate("qsTranslate('FooContext', 'Two')", fileName).toString(), QString::fromLatin1("To")); + QCOMPARE(engine.evaluate("qsTranslate('FooContext', 'Goodbye')", fileName).toString(), QString::fromLatin1("Farvel")); + // From eval + QCOMPARE(engine.evaluate("eval('qsTranslate(\\'FooContext\\', \\'Two\\')')", fileName).toString(), QString::fromLatin1("To")); + QCOMPARE(engine.evaluate("eval('qsTranslate(\\'FooContext\\', \\'Goodbye\\')')", fileName).toString(), QString::fromLatin1("Farvel")); + + // Don't exist in translation + QCOMPARE(engine.evaluate("qsTr('Three')", fileName).toString(), QString::fromLatin1("Three")); + QCOMPARE(engine.evaluate("qsTranslate('FooContext', 'So long')", fileName).toString(), QString::fromLatin1("So long")); + QCOMPARE(engine.evaluate("qsTranslate('BarContext', 'Goodbye')", fileName).toString(), QString::fromLatin1("Goodbye")); + + // From C++ + // There is no context, but it shouldn't crash + QCOMPARE(engine.globalObject().property("qsTr").call( + QScriptValue(), QScriptValueList() << "One").toString(), QString::fromLatin1("One")); + + QCoreApplication::instance()->removeTranslator(&translator); +} + void tst_QScriptEngine::functionScopes() { QScriptEngine eng; -- cgit v0.12