aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <[email protected]>2025-04-10 17:11:42 +0200
committerUlf Hermann <[email protected]>2025-04-11 15:50:24 +0200
commit916f5b51c8ec3595e054e4bf8e62949258a552ee (patch)
tree46ca2654d47ad1314318f414b42786cbcaf4d42c
parentf181086eeb370f7ba7fabc8434c77b2768a0afee (diff)
qmltc: Properly escape translation strings
We have QQmlJSUtils::toLiteral() for that. Extend it to handle byte arrays in addition to strings and use it. Fixes: QTBUG-134726 Change-Id: Ibde1f56b25794fc8c49b796303c4f39933aedb42 Reviewed-by: Olivier De Cannière <[email protected]>
-rw-r--r--src/qmlcompiler/qqmljsutils_p.h21
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/newLineTranslation.qml6
-rw-r--r--tests/auto/qml/qmltc/tst_qmltc.cpp9
-rw-r--r--tests/auto/qml/qmltc/tst_qmltc.h2
-rw-r--r--tools/qmltc/qmltccompilerpieces.cpp32
6 files changed, 49 insertions, 23 deletions
diff --git a/src/qmlcompiler/qqmljsutils_p.h b/src/qmlcompiler/qqmljsutils_p.h
index 56aec3dd78..1b4a5b707d 100644
--- a/src/qmlcompiler/qqmljsutils_p.h
+++ b/src/qmlcompiler/qqmljsutils_p.h
@@ -73,13 +73,13 @@ struct Q_QMLCOMPILER_EXPORT QQmlJSUtils
Returns escaped version of \a s. This function is mostly useful for code
generators.
*/
- static QString escapeString(QString s)
+ template<typename String, typename CharacterLiteral, typename StringView>
+ static String escapeString(String s)
{
- using namespace Qt::StringLiterals;
- return s.replace('\\'_L1, "\\\\"_L1)
- .replace('"'_L1, "\\\""_L1)
- .replace('\n'_L1, "\\n"_L1)
- .replace('?'_L1, "\\?"_L1);
+ return s.replace(CharacterLiteral('\\'), StringView("\\\\"))
+ .replace(CharacterLiteral('"'), StringView("\\\""))
+ .replace(CharacterLiteral('\n'), StringView("\\n"))
+ .replace(CharacterLiteral('?'), StringView("\\?"));
}
/*! \internal
@@ -89,9 +89,14 @@ struct Q_QMLCOMPILER_EXPORT QQmlJSUtils
\note This function escapes \a s before wrapping it.
*/
- static QString toLiteral(const QString &s, QStringView ctor = u"QStringLiteral")
+ template<
+ typename String = QString,
+ typename CharacterLiteral = QLatin1Char,
+ typename StringView = QLatin1StringView>
+ static String toLiteral(const String &s, StringView ctor = StringView("QStringLiteral"))
{
- return ctor % u"(\"" % escapeString(s) % u"\")";
+ return ctor % StringView("(\"")
+ % escapeString<String, CharacterLiteral, StringView>(s) % StringView("\")");
}
/*! \internal
diff --git a/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt b/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt
index 7472aa8d37..3eab68a7e7 100644
--- a/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt
+++ b/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt
@@ -143,6 +143,8 @@ set(qml_sources
attachedComponentProperty.qml
attachedNamespacedProperty.qml
+
+ newLineTranslation.qml
)
set(js_sources
diff --git a/tests/auto/qml/qmltc/QmltcTests/newLineTranslation.qml b/tests/auto/qml/qmltc/QmltcTests/newLineTranslation.qml
new file mode 100644
index 0000000000..99899e37d4
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/newLineTranslation.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ objectName: qsTr("Hello World \n")
+}
+
diff --git a/tests/auto/qml/qmltc/tst_qmltc.cpp b/tests/auto/qml/qmltc/tst_qmltc.cpp
index 268e213841..73ef03eaaf 100644
--- a/tests/auto/qml/qmltc/tst_qmltc.cpp
+++ b/tests/auto/qml/qmltc/tst_qmltc.cpp
@@ -97,6 +97,8 @@
#include "attachedcomponentproperty.h"
#include "attachednamespacedproperty.h"
+#include "newlinetranslation.h"
+
// Qt:
#include <QtCore/qstring.h>
#include <QtCore/qbytearray.h>
@@ -3455,4 +3457,11 @@ void tst_qmltc::attachedNamespacedProperty()
checkOverlayAttached(&createdByQmltc);
}
+void tst_qmltc::newLineTranslation()
+{
+ QQmlEngine e;
+ PREPEND_NAMESPACE(newLineTranslation) createdByQmltc(&e);
+ QCOMPARE(createdByQmltc.objectName(), "Hello World \n"_L1);
+}
+
QTEST_MAIN(tst_qmltc)
diff --git a/tests/auto/qml/qmltc/tst_qmltc.h b/tests/auto/qml/qmltc/tst_qmltc.h
index df97a4ec0e..99abb60dc5 100644
--- a/tests/auto/qml/qmltc/tst_qmltc.h
+++ b/tests/auto/qml/qmltc/tst_qmltc.h
@@ -110,4 +110,6 @@ private slots:
void attachedComponentProperty();
void attachedNamespacedProperty();
+
+ void newLineTranslation();
};
diff --git a/tools/qmltc/qmltccompilerpieces.cpp b/tools/qmltc/qmltccompilerpieces.cpp
index 318712999c..ce29045142 100644
--- a/tools/qmltc/qmltccompilerpieces.cpp
+++ b/tools/qmltc/qmltccompilerpieces.cpp
@@ -253,29 +253,31 @@ void QmltcCodeGenerator::generate_createBindingOnProperty(
}
}
+static QByteArray toLiteral(const QByteArray &utf8)
+{
+ return QQmlJSUtils::toLiteral<QByteArray, char, QByteArrayView>(utf8);
+}
+
static QString serializeTranslation(const QQmlTranslation::QsTrIdData &data)
{
- QString result = QStringLiteral(R"(QQmlTranslation(QQmlTranslation::QsTrIdData(
- QStringLiteral("%1"),
+ return QStringLiteral(R"(QQmlTranslation(QQmlTranslation::QsTrIdData(
+ %1,
%4)))")
- .arg(QString::fromUtf8(data.id()))
- .arg(data.number());
-
- return result;
+ .arg(toLiteral(data.id()))
+ .arg(data.number());
}
static QString serializeTranslation(const QQmlTranslation::QsTrData &data)
{
- QString result = QStringLiteral(R"(QQmlTranslation(QQmlTranslation::QsTrData(
- QStringLiteral("%1"),
- QStringLiteral("%2"),
- QStringLiteral("%3"),
+ return QStringLiteral(R"(QQmlTranslation(QQmlTranslation::QsTrData(
+ %1,
+ %2,
+ %3,
%4)))")
- .arg(QString::fromUtf8(data.context()), QString::fromUtf8(data.text()),
- QString::fromUtf8(data.comment()))
- .arg(data.number());
-
- return result;
+ .arg(toLiteral(data.context()),
+ toLiteral(data.text()),
+ toLiteral(data.comment()))
+ .arg(data.number());
}
static QString serializeTranslation(const QQmlTranslation &translation)