summaryrefslogtreecommitdiffstats
path: root/src/linguist
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2019-04-24 10:52:39 +0200
committerLiang Qi <liang.qi@qt.io>2019-04-24 11:55:36 +0200
commit4399a1683a016794e22ecdd03eafca07b93af4e2 (patch)
treed1a4da3ad9a57d60da2c7c71ae03a13701c67f16 /src/linguist
parentd91ecc26252f42641a23e25f6a6a18495e0e7700 (diff)
parent97075ce49ee73609330804b8bbbc12fabbb30766 (diff)
Merge remote-tracking branch 'origin/5.12' into 5.13
Conflicts: .qmake.conf src/qdoc/qmlmarkupvisitor.h src/qdoc/qmlvisitor.h tests/auto/qtattributionsscanner/testdata/good/expected.json Done-With: Kai Koehne <kai.koehne@qt.io> Change-Id: I180ee214d1e5999fc1279b092bd9214b6bf8f858
Diffstat (limited to 'src/linguist')
-rw-r--r--src/linguist/Qt5LinguistToolsMacros.cmake3
-rw-r--r--src/linguist/lupdate/cpp.cpp91
-rw-r--r--src/linguist/lupdate/lupdate.h5
-rw-r--r--src/linguist/lupdate/main.cpp64
-rw-r--r--src/linguist/lupdate/qdeclarative.cpp14
-rw-r--r--src/linguist/shared/translator.cpp11
-rw-r--r--src/linguist/shared/translator.h1
-rw-r--r--src/linguist/shared/ts.cpp2
8 files changed, 121 insertions, 70 deletions
diff --git a/src/linguist/Qt5LinguistToolsMacros.cmake b/src/linguist/Qt5LinguistToolsMacros.cmake
index b99597304..5c357a152 100644
--- a/src/linguist/Qt5LinguistToolsMacros.cmake
+++ b/src/linguist/Qt5LinguistToolsMacros.cmake
@@ -74,7 +74,8 @@ function(QT5_CREATE_TRANSLATION _qm_files)
add_custom_command(OUTPUT ${_ts_file}
COMMAND ${Qt5_LUPDATE_EXECUTABLE}
ARGS ${_lupdate_options} "@${_ts_lst_file}" -ts ${_ts_file}
- DEPENDS ${_my_sources} ${_ts_lst_file} VERBATIM)
+ DEPENDS ${_my_sources}
+ BYPRODUCTS ${_ts_lst_file} VERBATIM)
endforeach()
qt5_add_translation(${_qm_files} ${_my_tsfiles})
set(${_qm_files} ${${_qm_files}} PARENT_SCOPE)
diff --git a/src/linguist/lupdate/cpp.cpp b/src/linguist/lupdate/cpp.cpp
index aac9a90ff..e96e102af 100644
--- a/src/linguist/lupdate/cpp.cpp
+++ b/src/linguist/lupdate/cpp.cpp
@@ -239,6 +239,7 @@ private:
std::ostream &yyMsg(int line = 0);
int getChar();
+ TokenType lookAheadToSemicolonOrLeftBrace();
TokenType getToken();
void processComment();
@@ -249,7 +250,6 @@ private:
bool matchStringOrNull(QString *s);
bool matchExpression();
- QString transcode(const QString &str);
void recordMessage(
int line, const QString &context, const QString &text, const QString &comment,
const QString &extracomment, const QString &msgid, const TranslatorMessage::ExtraData &extra,
@@ -450,6 +450,23 @@ int CppParser::getChar()
}
}
+CppParser::TokenType CppParser::lookAheadToSemicolonOrLeftBrace()
+{
+ if (*yyInPtr == 0)
+ return Tok_Eof;
+ const ushort *uc = yyInPtr + 1;
+ forever {
+ ushort c = *uc;
+ if (!c)
+ return Tok_Eof;
+ if (c == ';')
+ return Tok_Semicolon;
+ if (c == '{')
+ return Tok_LeftBrace;
+ ++uc;
+ }
+}
+
STRING(Q_OBJECT);
STRING(class);
STRING(final);
@@ -1451,7 +1468,7 @@ bool CppParser::matchString(QString *s)
return matches;
matches = true;
if (yyTok == Tok_String)
- *s += transcode(yyWord);
+ *s += ParserTool::transcode(yyWord);
else
*s += yyWord;
s->detach();
@@ -1532,65 +1549,14 @@ bool CppParser::matchExpression()
return true;
}
-QString CppParser::transcode(const QString &str)
-{
- static const char tab[] = "abfnrtv";
- static const char backTab[] = "\a\b\f\n\r\t\v";
- // This function has to convert back to bytes, as C's \0* sequences work at that level.
- const QByteArray in = str.toUtf8();
- QByteArray out;
-
- out.reserve(in.length());
- for (int i = 0; i < in.length();) {
- uchar c = in[i++];
- if (c == '\\') {
- if (i >= in.length())
- break;
- c = in[i++];
-
- if (c == '\n')
- continue;
-
- if (c == 'x' || c == 'u' || c == 'U') {
- const bool unicode = (c != 'x');
- QByteArray hex;
- while (i < in.length() && isxdigit((c = in[i]))) {
- hex += c;
- i++;
- }
- if (unicode)
- out += QString(QChar(hex.toUInt(nullptr, 16))).toUtf8();
- else
- out += hex.toUInt(nullptr, 16);
- } else if (c >= '0' && c < '8') {
- QByteArray oct;
- int n = 0;
- oct += c;
- while (n < 2 && i < in.length() && (c = in[i]) >= '0' && c < '8') {
- i++;
- n++;
- oct += c;
- }
- out += oct.toUInt(0, 8);
- } else {
- const char *p = strchr(tab, c);
- out += !p ? c : backTab[p - tab];
- }
- } else {
- out += c;
- }
- }
- return QString::fromUtf8(out.constData(), out.length());
-}
-
void CppParser::recordMessage(int line, const QString &context, const QString &text, const QString &comment,
const QString &extracomment, const QString &msgid, const TranslatorMessage::ExtraData &extra, bool plural)
{
TranslatorMessage msg(
- transcode(context), text, transcode(comment), QString(),
+ ParserTool::transcode(context), text, ParserTool::transcode(comment), QString(),
yyFileName, line, QStringList(),
TranslatorMessage::Unfinished, plural);
- msg.setExtraComment(transcode(extracomment.simplified()));
+ msg.setExtraComment(ParserTool::transcode(extracomment.simplified()));
msg.setId(msgid);
msg.setExtras(extra);
tor->append(msg);
@@ -1760,7 +1726,7 @@ void CppParser::handleTrId(bool plural)
yyTok = getToken();
if (matchString(&msgid) && !msgid.isEmpty()) {
plural |= match(Tok_Comma);
- recordMessage(line, QString(), transcode(sourcetext), QString(), extracomment,
+ recordMessage(line, QString(), ParserTool::transcode(sourcetext), QString(), extracomment,
msgid, extra, plural);
}
sourcetext.clear();
@@ -2182,8 +2148,11 @@ void CppParser::parseInternal(ConversionData &cd, const QStringList &includeStac
pendingContext = prospectiveContext;
prospectiveContext.clear();
}
- if (yyTok == Tok_Colon)
- yyTokColonSeen = true;
+ //ignore colons for bitfields (are usually followed by a semicolon)
+ if (yyTok == Tok_Colon) {
+ if (lookAheadToSemicolonOrLeftBrace() != Tok_Semicolon)
+ yyTokColonSeen = true;
+ }
}
metaExpected = true;
yyTok = getToken();
@@ -2314,11 +2283,11 @@ void CppParser::processComment()
context = comment.left(k);
comment.remove(0, k + 1);
TranslatorMessage msg(
- transcode(context), QString(),
- transcode(comment), QString(),
+ ParserTool::transcode(context), QString(),
+ ParserTool::transcode(comment), QString(),
yyFileName, yyLineNo, QStringList(),
TranslatorMessage::Finished, false);
- msg.setExtraComment(transcode(extracomment.simplified()));
+ msg.setExtraComment(ParserTool::transcode(extracomment.simplified()));
extracomment.clear();
tor->append(msg);
tor->setExtras(extra);
diff --git a/src/linguist/lupdate/lupdate.h b/src/linguist/lupdate/lupdate.h
index 0d98379d0..bb58cbd1e 100644
--- a/src/linguist/lupdate/lupdate.h
+++ b/src/linguist/lupdate/lupdate.h
@@ -99,6 +99,11 @@ bool loadQml(Translator &translator, const QString &filename, ConversionData &cd
UNARY_MACRO(qsTranslate) \
/*end*/
+class ParserTool
+{
+public:
+ static QString transcode(const QString &str);
+};
class TrFunctionAliasManager {
public:
diff --git a/src/linguist/lupdate/main.cpp b/src/linguist/lupdate/main.cpp
index eb81ee9e8..d9c6f7966 100644
--- a/src/linguist/lupdate/main.cpp
+++ b/src/linguist/lupdate/main.cpp
@@ -134,6 +134,57 @@ QStringList TrFunctionAliasManager::availableFunctionsWithAliases() const
TrFunctionAliasManager trFunctionAliasManager;
+QString ParserTool::transcode(const QString &str)
+{
+ static const char tab[] = "abfnrtv";
+ static const char backTab[] = "\a\b\f\n\r\t\v";
+ // This function has to convert back to bytes, as C's \0* sequences work at that level.
+ const QByteArray in = str.toUtf8();
+ QByteArray out;
+
+ out.reserve(in.length());
+ for (int i = 0; i < in.length();) {
+ uchar c = in[i++];
+ if (c == '\\') {
+ if (i >= in.length())
+ break;
+ c = in[i++];
+
+ if (c == '\n')
+ continue;
+
+ if (c == 'x' || c == 'u' || c == 'U') {
+ const bool unicode = (c != 'x');
+ QByteArray hex;
+ while (i < in.length() && isxdigit((c = in[i]))) {
+ hex += c;
+ i++;
+ }
+ if (unicode)
+ out += QString(QChar(hex.toUInt(nullptr, 16))).toUtf8();
+ else
+ out += hex.toUInt(nullptr, 16);
+ } else if (c >= '0' && c < '8') {
+ QByteArray oct;
+ int n = 0;
+ oct += c;
+ while (n < 2 && i < in.length() && (c = in[i]) >= '0' && c < '8') {
+ i++;
+ n++;
+ oct += c;
+ }
+ out += oct.toUInt(0, 8);
+ } else {
+ const char *p = strchr(tab, c);
+ out += !p ? c : backTab[p - tab];
+ }
+ } else {
+ out += c;
+ }
+ }
+ return QString::fromUtf8(out.constData(), out.length());
+}
+
static QString m_defaultExtensions;
static void printOut(const QString & out)
@@ -314,6 +365,19 @@ static void updateTsFiles(const Translator &fetchedTor, const QStringList &tsFil
printErr(LU::tr("lupdate warning: Specified source language '%1' disagrees with"
" existing file's language '%2'. Ignoring.\n")
.arg(sourceLanguage, tor.sourceLanguageCode()));
+ // If there is translation in the file, the language should be recognized
+ // (when the language is not recognized, plural translations are lost)
+ if (tor.translationsExist()) {
+ QLocale::Language l;
+ QLocale::Country c;
+ tor.languageAndCountry(tor.languageCode(), &l, &c);
+ QStringList forms;
+ if (!getNumerusInfo(l, c, 0, &forms, 0)) {
+ printErr(LU::tr("File %1 won't be updated: it contains translation but the"
+ " target language is not recognized\n").arg(fileName));
+ continue;
+ }
+ }
} else {
if (!targetLanguage.isEmpty())
tor.setLanguageCode(targetLanguage);
diff --git a/src/linguist/lupdate/qdeclarative.cpp b/src/linguist/lupdate/qdeclarative.cpp
index 0938b86e8..fa8ad260e 100644
--- a/src/linguist/lupdate/qdeclarative.cpp
+++ b/src/linguist/lupdate/qdeclarative.cpp
@@ -130,11 +130,11 @@ protected:
if (!sourcetext.isEmpty())
yyMsg(identLineNo) << qPrintable(LU::tr("//% cannot be used with %1(). Ignoring\n").arg(name));
- TranslatorMessage msg(m_component, source,
+ TranslatorMessage msg(m_component, ParserTool::transcode(source),
comment, QString(), m_fileName,
node->firstSourceLocation().startLine, QStringList(),
TranslatorMessage::Unfinished, plural);
- msg.setExtraComment(extracomment.simplified());
+ msg.setExtraComment(ParserTool::transcode(extracomment.simplified()));
msg.setId(msgid);
msg.setExtras(extra);
m_translator->extend(msg, m_cd);
@@ -171,11 +171,11 @@ protected:
plural = true;
}
- TranslatorMessage msg(context, source,
+ TranslatorMessage msg(context, ParserTool::transcode(source),
comment, QString(), m_fileName,
node->firstSourceLocation().startLine, QStringList(),
TranslatorMessage::Unfinished, plural);
- msg.setExtraComment(extracomment.simplified());
+ msg.setExtraComment(ParserTool::transcode(extracomment.simplified()));
msg.setId(msgid);
msg.setExtras(extra);
m_translator->extend(msg, m_cd);
@@ -199,11 +199,11 @@ protected:
bool plural = node->arguments->next;
- TranslatorMessage msg(QString(), sourcetext,
+ TranslatorMessage msg(QString(), ParserTool::transcode(sourcetext),
QString(), QString(), m_fileName,
node->firstSourceLocation().startLine, QStringList(),
TranslatorMessage::Unfinished, plural);
- msg.setExtraComment(extracomment.simplified());
+ msg.setExtraComment(ParserTool::transcode(extracomment.simplified()));
msg.setId(id);
msg.setExtras(extra);
m_translator->extend(msg, m_cd);
@@ -221,7 +221,7 @@ private:
return std::cerr << qPrintable(m_fileName) << ':' << line << ": ";
}
- void throwRecursionDepthError()
+ void throwRecursionDepthError() final
{
std::cerr << qPrintable(m_fileName) << ": "
<< qPrintable(LU::tr("Maximum statement or expression depth exceeded"));
diff --git a/src/linguist/shared/translator.cpp b/src/linguist/shared/translator.cpp
index af669e235..db28ea396 100644
--- a/src/linguist/shared/translator.cpp
+++ b/src/linguist/shared/translator.cpp
@@ -433,6 +433,17 @@ void Translator::stripUntranslatedMessages()
m_indexOk = false;
}
+bool Translator::translationsExist()
+{
+ for (TMM::Iterator it = m_messages.begin(); it != m_messages.end(); ) {
+ if (it->isTranslated())
+ return true;
+ else
+ ++it;
+ }
+ return false;
+}
+
void Translator::stripEmptyContexts()
{
for (TMM::Iterator it = m_messages.begin(); it != m_messages.end();)
diff --git a/src/linguist/shared/translator.h b/src/linguist/shared/translator.h
index 8919a13df..5b5d12250 100644
--- a/src/linguist/shared/translator.h
+++ b/src/linguist/shared/translator.h
@@ -135,6 +135,7 @@ public:
void dropTranslations();
void dropUiLines();
void makeFileNamesAbsolute(const QDir &originalPath);
+ bool translationsExist();
struct Duplicates { QSet<int> byId, byContents; };
Duplicates resolveDuplicates();
diff --git a/src/linguist/shared/ts.cpp b/src/linguist/shared/ts.cpp
index 5914319c9..153f9708b 100644
--- a/src/linguist/shared/ts.cpp
+++ b/src/linguist/shared/ts.cpp
@@ -464,7 +464,7 @@ static QString protect(const QString &str)
result += QLatin1String("&apos;");
break;
default:
- if ((c < 0x20 || (ch > 0x7f && ch.isSpace())) && c != '\r' && c != '\n' && c != '\t')
+ if ((c < 0x20 || (ch > 0x7f && ch.isSpace())) && c != '\n' && c != '\t')
result += numericEntity(c);
else // this also covers surrogates
result += QChar(c);