summaryrefslogtreecommitdiffstats
path: root/src/linguist/lupdate/merge.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/linguist/lupdate/merge.cpp')
-rw-r--r--src/linguist/lupdate/merge.cpp258
1 files changed, 10 insertions, 248 deletions
diff --git a/src/linguist/lupdate/merge.cpp b/src/linguist/lupdate/merge.cpp
index 9db8826c8..f204fc73d 100644
--- a/src/linguist/lupdate/merge.cpp
+++ b/src/linguist/lupdate/merge.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Linguist of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "lupdate.h"
@@ -39,210 +14,6 @@
QT_BEGIN_NAMESPACE
-static bool isDigitFriendly(QChar c)
-{
- return c.isPunct() || c.isSpace();
-}
-
-static int numberLength(const QString &s, int i)
-{
- if (i >= s.size() || !s.at(i).isDigit())
- return 0;
-
- int pos = i;
- do {
- ++i;
- } while (i < s.size()
- && (s.at(i).isDigit()
- || (isDigitFriendly(s[i])
- && i + 1 < s.size()
- && (s[i + 1].isDigit()
- || (isDigitFriendly(s[i + 1])
- && i + 2 < s.size()
- && s[i + 2].isDigit())))));
- return i - pos;
-}
-
-
-/*
- Returns a version of 'key' where all numbers have been replaced by zeroes. If
- there were none, returns "".
-*/
-static QString zeroKey(const QString &key)
-{
- QString zeroed;
- bool metSomething = false;
-
- for (int i = 0; i < key.size(); ++i) {
- int len = numberLength(key, i);
- if (len > 0) {
- i += len;
- zeroed.append(QLatin1Char('0'));
- metSomething = true;
- } else {
- zeroed.append(key.at(i));
- }
- }
- return metSomething ? zeroed : QString();
-}
-
-static QString translationAttempt(const QString &oldTranslation,
- const QString &oldSource, const QString &newSource)
-{
- int p = zeroKey(oldSource).count(QLatin1Char('0'));
- QString attempt;
- QStringList oldNumbers;
- QStringList newNumbers;
- QList<bool> met(p);
- QList<int> matchedYet(p);
- int i, j;
- int k = 0, ell, best;
- int m, n;
- int pass;
-
- /*
- This algorithm is hard to follow, so we'll consider an example
- all along: oldTranslation is "XeT 3.0", oldSource is "TeX 3.0"
- and newSource is "XeT 3.1".
-
- First, we set up two tables: oldNumbers and newNumbers. In our
- example, oldNumber[0] is "3.0" and newNumber[0] is "3.1".
- */
- for (i = 0, j = 0; i < oldSource.size(); i++, j++) {
- m = numberLength(oldSource, i);
- n = numberLength(newSource, j);
- if (m > 0) {
- oldNumbers.append(oldSource.mid(i, m + 1));
- newNumbers.append(newSource.mid(j, n + 1));
- i += m;
- j += n;
- met[k] = false;
- matchedYet[k] = 0;
- k++;
- }
- }
-
- /*
- We now go over the old translation, "XeT 3.0", one letter at a
- time, looking for numbers found in oldNumbers. Whenever such a
- number is met, it is replaced with its newNumber equivalent. In
- our example, the "3.0" of "XeT 3.0" becomes "3.1".
- */
- for (i = 0; i < oldTranslation.length(); i++) {
- attempt += oldTranslation[i];
- for (k = 0; k < p; k++) {
- if (oldTranslation[i] == oldNumbers[k][matchedYet[k]])
- matchedYet[k]++;
- else
- matchedYet[k] = 0;
- }
-
- /*
- Let's find out if the last character ended a match. We make
- two passes over the data. In the first pass, we try to
- match only numbers that weren't matched yet; if that fails,
- the second pass does the trick. This is useful in some
- suspicious cases, flagged below.
- */
- for (pass = 0; pass < 2; pass++) {
- best = p; // an impossible value
- for (k = 0; k < p; k++) {
- if ((!met[k] || pass > 0) &&
- matchedYet[k] == oldNumbers[k].length() &&
- numberLength(oldTranslation, i + 1 - matchedYet[k]) == matchedYet[k]) {
- // the longer the better
- if (best == p || matchedYet[k] > matchedYet[best])
- best = k;
- }
- }
- if (best != p) {
- attempt.truncate(attempt.length() - matchedYet[best]);
- attempt += newNumbers[best];
- met[best] = true;
- for (k = 0; k < p; k++)
- matchedYet[k] = 0;
- break;
- }
- }
- }
-
- /*
- We flag two kinds of suspicious cases. They are identified as
- such with comments such as "{2000?}" at the end.
-
- Example of the first kind: old source text "TeX 3.0" translated
- as "XeT 2.0" is flagged "TeX 2.0 {3.0?}", no matter what the
- new text is.
- */
- for (k = 0; k < p; k++) {
- if (!met[k])
- attempt += QLatin1String(" {") + newNumbers[k] + QLatin1String("?}");
- }
-
- /*
- Example of the second kind: "1 of 1" translated as "1 af 1",
- with new source text "1 of 2", generates "1 af 2 {1 or 2?}"
- because it's not clear which of "1 af 2" and "2 af 1" is right.
- */
- for (k = 0; k < p; k++) {
- for (ell = 0; ell < p; ell++) {
- if (k != ell && oldNumbers[k] == oldNumbers[ell] &&
- newNumbers[k] < newNumbers[ell])
- attempt += QLatin1String(" {") + newNumbers[k] + QLatin1String(" or ") +
- newNumbers[ell] + QLatin1String("?}");
- }
- }
- return attempt;
-}
-
-
-/*
- Augments a Translator with translations easily derived from
- similar existing (probably obsolete) translations.
-
- For example, if "TeX 3.0" is translated as "XeT 3.0" and "TeX 3.1"
- has no translation, "XeT 3.1" is added to the translator and is
- marked Unfinished.
-
- Returns the number of additional messages that this heuristic translated.
-*/
-int applyNumberHeuristic(Translator &tor)
-{
- QMap<QString, QPair<QString, QString> > translated;
- QList<bool> untranslated(tor.messageCount());
- int inserted = 0;
-
- for (int i = 0; i < tor.messageCount(); ++i) {
- const TranslatorMessage &msg = tor.message(i);
- bool hasTranslation = msg.isTranslated();
- if (msg.type() == TranslatorMessage::Unfinished) {
- if (!hasTranslation)
- untranslated[i] = true;
- } else if (hasTranslation && msg.translations().count() == 1) {
- const QString &key = zeroKey(msg.sourceText());
- if (!key.isEmpty())
- translated.insert(key, qMakePair(msg.sourceText(), msg.translation()));
- }
- }
-
- for (int i = 0; i < tor.messageCount(); ++i) {
- if (untranslated[i]) {
- TranslatorMessage &msg = tor.message(i);
- const QString &key = zeroKey(msg.sourceText());
- if (!key.isEmpty()) {
- const auto t = translated.constFind(key);
- if (t != translated.constEnd() && t->first != msg.sourceText()) {
- msg.setTranslation(translationAttempt(t->second, t->first,
- msg.sourceText()));
- inserted++;
- }
- }
- }
- }
- return inserted;
-}
-
-
/*
Augments a Translator with trivially derived translations.
@@ -516,34 +287,25 @@ Translator merge(
*/
int sameTextHeuristicCount = (options & HeuristicSameText) ? applySameTextHeuristic(outTor) : 0;
- /*
- The number heuristic handles cases where a message has an
- obsolete counterpart with mostly numbers differing in the
- source text.
- */
- int sameNumberHeuristicCount = (options & HeuristicNumber) ? applyNumberHeuristic(outTor) : 0;
-
if (options & Verbose) {
int totalFound = neww + known;
- err += LU::tr(" Found %n source text(s) (%1 new and %2 already existing)\n", 0, totalFound).arg(neww).arg(known);
+ err += QStringLiteral(" Found %1 source text(s) (%2 new and %3 already existing)\n")
+ .arg(totalFound).arg(neww).arg(known);
if (obsoleted) {
if (options & NoObsolete) {
- err += LU::tr(" Removed %n obsolete entries\n", 0, obsoleted);
+ err += QStringLiteral(" Removed %1 obsolete entries\n").arg(obsoleted);
} else {
- err += LU::tr(" Kept %n obsolete entries\n", 0, obsoleted);
+ err += QStringLiteral(" Kept %1 obsolete entries\n").arg(obsoleted);
}
}
- if (sameNumberHeuristicCount)
- err += LU::tr(" Number heuristic provided %n translation(s)\n",
- 0, sameNumberHeuristicCount);
if (sameTextHeuristicCount)
- err += LU::tr(" Same-text heuristic provided %n translation(s)\n",
- 0, sameTextHeuristicCount);
+ err += QStringLiteral(" Same-text heuristic provided %1 translation(s)\n")
+ .arg(sameTextHeuristicCount);
if (similarTextHeuristicCount)
- err += LU::tr(" Similar-text heuristic provided %n translation(s)\n",
- 0, similarTextHeuristicCount);
+ err += QStringLiteral(" Similar-text heuristic provided %1 translation(s)\n")
+ .arg(similarTextHeuristicCount);
}
return outTor;
}