Accept full-width parentheses in removeMnemonics()

QPlatformTheme::removeMnemonics() removes any match to /\s*\(&[^&]\)/
from the text it is given (a menu entry). It transpires that
translators are apt to use the full-width parentheses (compatible with
some far-eastern scripts) instead of the plain ASCII ones. This leads
to their translated mnemonics don't match the same pattern unless we
treat the full-width parentheses as a match for the ASCII ones;
consequently, they don't get removed, which this function exists to
do. So teach it to recognize the full-width versions, too.

In the process, break out the pattern-matching (aside from the leading
space) to a lambda to make it easier to read and document.

Fixes: QTBUG-110829
Pick-to: 6.5 6.4 6.2 5.15
Change-Id: I7335d0bd8dbba66e1fe58fc3eec93caaaf6ec140
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
Edward Welbourne 2023-02-01 15:47:13 +01:00
parent 52ce4d2d29
commit 86b930f073

View File

@ -810,6 +810,19 @@ QString QPlatformTheme::defaultStandardButtonText(int button)
QString QPlatformTheme::removeMnemonics(const QString &original)
{
const auto mnemonicInParentheses = [](QStringView text) {
/* Format of mnemonics to remove is /\(&[^&]\)/ but accept full-width
forms of ( and ) as equivalent, for cross-platform compatibility with
MS (and consequent behavior of translators, see QTBUG-110829).
*/
Q_ASSERT(text.size() == 4); // Caller's responsibility.
constexpr QChar wideOpen = u'\uff08', wideClose = u'\uff09';
if (!text.startsWith(u'(') && !text.startsWith(wideOpen))
return false;
if (text[1] != u'&' || text[2] == u'&')
return false;
return text.endsWith(u')') || text.endsWith(wideClose);
};
QString returnText(original.size(), u'\0');
int finalDest = 0;
int currPos = 0;
@ -820,11 +833,8 @@ QString QPlatformTheme::removeMnemonics(const QString &original)
--l;
if (l == 0)
break;
} else if (original.at(currPos) == u'(' && l >= 4 &&
original.at(currPos + 1) == u'&' &&
original.at(currPos + 2) != u'&' &&
original.at(currPos + 3) == u')') {
/* remove mnemonics its format is "\s*(&X)" */
} else if (l >= 4 && mnemonicInParentheses(QStringView{original}.sliced(currPos, 4))) {
// Also strip any leading space before the mnemonic:
int n = 0;
while (finalDest > n && returnText.at(finalDest - n - 1).isSpace())
++n;