kdecore: magic bits for numbers formatting

people really messed up the precisions, look at what kcalc does with the
constants:
kde-extraapps/kcalc/kcalcdisplay.cpp

zero precision is essentially rounding the constants! also setlocale() no
longer has effect on Katie and thus Katana so updated the method to
override locale in KLocalizedString test while at it (tests pass after one
adjustment for the french locale case)

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2023-07-28 04:49:28 +03:00
parent b7e54f8e21
commit 5e95db910f
3 changed files with 145 additions and 114 deletions

View file

@ -243,16 +243,21 @@ QLocale::MeasurementSystem KLocale::measureSystem() const
QString KLocale::formatNumber(double num, int precision) const
{
return d->locale.toString(num, 'f', qMax(precision, 0));
if (precision <= 0) {
// NOTE: kcalc for example passes 0 for precision but the constants should no be round
// otherwise the whole meaning of Pi (3.14) being non-rounded number is lost so instead of
// forcing a number rounding the precision is automatically chosen here
return d->locale.toString(num, 'f', qRound(num) == num ? 0 : 2);
}
return d->locale.toString(num, 'f', precision);
}
QString KLocale::formatNumber(const QString &numStr, bool round, int precision) const
{
const double numdbl = d->locale.toDouble(numStr);
if (round) {
return QString::number(qRound(numdbl));
return formatNumber(qRound(numStr.toDouble()), 0);
}
return QString::number(numdbl, 'f', qMax(precision, 0));
return formatNumber(numStr.toDouble(), precision);
}
QString KLocale::formatLong(long num) const

View file

@ -228,8 +228,8 @@ public:
* equivalent.
*
* Given 123456.78F, returns "123,456.78" (for some European country). If precision isn't
* specified or is < 0, then the precision is zero. This function is a wrapper that is provided
* for convenience.
* specified or is < 0, then the precision is automatically chosen based on the number. This
* function is a wrapper that is provided for convenience.
*
* @param num The number to convert
* @param precision Number of decimal places used.

View file

@ -30,18 +30,14 @@
#include "kconfiggroup.h"
#include <QtCore/QString>
#include <locale.h>
#include <stdlib.h>
#include <future>
void KLocalizedStringTest::initTestCase ()
{
m_hasFrench = !KStandardDirs::locate("locale", "fr/kdelibs4.tr").isEmpty();
if (m_hasFrench) {
setlocale(LC_ALL, "fr_FR.utf8");
if (setlocale(LC_ALL, NULL) != QByteArray("fr_FR.utf8")) {
kDebug() << "Setting locale to fr_FR.utf8 failed";
m_hasFrench = false;
}
::setenv("LC_ALL", "fr_FR.UTF-8", 1);
}
QCOMPARE(KGlobal::locale()->isApplicationTranslatedInto("en_US"), true);
@ -55,154 +51,184 @@ void KLocalizedStringTest::initTestCase ()
void KLocalizedStringTest::correctSubs ()
{
// Warm up.
QCOMPARE(i18n("Daisies, daisies"),
QString("Daisies, daisies"));
QCOMPARE(i18n("Daisies, daisies"), QString("Daisies, daisies"));
// Placeholder in the middle.
QCOMPARE(i18n("Fault in %1 unit", QString("AE35")),
QString("Fault in AE35 unit"));
QCOMPARE(
i18n("Fault in %1 unit", QString("AE35")),
QString("Fault in AE35 unit")
);
// Placeholder at the start.
QCOMPARE(i18n("%1, Tycho Magnetic Anomaly 1", QString("TMA-1")),
QString("TMA-1, Tycho Magnetic Anomaly 1"));
QCOMPARE(
i18n("%1, Tycho Magnetic Anomaly 1", QString("TMA-1")),
QString("TMA-1, Tycho Magnetic Anomaly 1")
);
// Placeholder at the end.
QCOMPARE(i18n("...odd things happening at %1", QString("Clavius")),
QString("...odd things happening at Clavius"));
QCOMPARE(i18n("Group %1", 1),
QString("Group 1"));
QCOMPARE(
i18n("...odd things happening at %1", QString("Clavius")),
QString("...odd things happening at Clavius")
);
QCOMPARE(i18n("Group %1", 1), QString("Group 1"));
// Two placeholders.
QCOMPARE(i18n("%1 and %2", QString("Bowman"), QString("Poole")),
QString("Bowman and Poole"));
QCOMPARE(
i18n("%1 and %2", QString("Bowman"), QString("Poole")),
QString("Bowman and Poole")
);
// Two placeholders in inverted order.
QCOMPARE(i18n("%2 and %1", QString("Poole"), QString("Bowman")),
QString("Bowman and Poole"));
QCOMPARE(
i18n("%2 and %1", QString("Poole"), QString("Bowman")),
QString("Bowman and Poole")
);
// % which is not of placeholder.
QCOMPARE(i18n("It's going to go %1% failure in 72 hours.", 100),
QString("It's going to go 100% failure in 72 hours."));
QCOMPARE(
i18n("It's going to go %1% failure in 72 hours.", 100),
QString("It's going to go 100% failure in 72 hours.")
);
// Usual plural.
QCOMPARE(i18np("%1 pod", "%1 pods", 1),
QString("1 pod"));
QCOMPARE(i18np("%1 pod", "%1 pods", 10),
QString("10 pods"));
QCOMPARE(i18np("%1 pod", "%1 pods", 1), QString("1 pod"));
QCOMPARE(i18np("%1 pod", "%1 pods", 10), QString("10 pods"));
// No plural-number in singular.
QCOMPARE(i18np("A pod", "%1 pods", 1),
QString("A pod"));
QCOMPARE(i18np("A pod", "%1 pods", 10),
QString("10 pods"));
QCOMPARE(i18np("A pod", "%1 pods", 1), QString("A pod"));
QCOMPARE(i18np("A pod", "%1 pods", 10), QString("10 pods"));
// No plural-number in singular or plural.
QCOMPARE(i18np("A pod", "Few pods", 1),
QString("A pod"));
QCOMPARE(i18np("A pod", "Few pods", 10),
QString("Few pods"));
QCOMPARE(i18np("A pod", "Few pods", 1), QString("A pod"));
QCOMPARE(i18np("A pod", "Few pods", 10), QString("Few pods"));
// First of two arguments as plural-number.
QCOMPARE(i18np("A pod left on %2", "%1 pods left on %2",
1, QString("Discovery")),
QString("A pod left on Discovery"));
QCOMPARE(i18np("A pod left on %2", "%1 pods left on %2",
2, QString("Discovery")),
QString("2 pods left on Discovery"));
QCOMPARE(
i18np("A pod left on %2", "%1 pods left on %2", 1, QString("Discovery")),
QString("A pod left on Discovery")
);
QCOMPARE(
i18np("A pod left on %2", "%1 pods left on %2", 2, QString("Discovery")),
QString("2 pods left on Discovery")
);
// Second of two arguments as plural-number.
QCOMPARE(i18np("%1 has a pod left", "%1 has %2 pods left",
QString("Discovery"), 1),
QString("Discovery has a pod left"));
QCOMPARE(i18np("%1 has a pod left", "%1 has %2 pods left",
QString("Discovery"), 2),
QString("Discovery has 2 pods left"));
QCOMPARE(
i18np("%1 has a pod left", "%1 has %2 pods left", QString("Discovery"), 1),
QString("Discovery has a pod left")
);
QCOMPARE(
i18np("%1 has a pod left", "%1 has %2 pods left", QString("Discovery"), 2),
QString("Discovery has 2 pods left")
);
// No plural-number in singular or plural, but another argument present.
QCOMPARE(i18np("A pod left on %2", "Some pods left on %2",
1, QString("Discovery")),
QString("A pod left on Discovery"));
QCOMPARE(i18np("A pod left on %2", "Some pods left on %2",
2, QString("Discovery")),
QString("Some pods left on Discovery"));
QCOMPARE(
i18np("A pod left on %2", "Some pods left on %2", 1, QString("Discovery")),
QString("A pod left on Discovery")
);
QCOMPARE(
i18np("A pod left on %2", "Some pods left on %2", 2, QString("Discovery")),
QString("Some pods left on Discovery")
);
// Visual formatting.
QCOMPARE(i18n("E = mc^2"),
QString("E = mc^2"));
QCOMPARE(i18n("E &lt; mc^2"),
QString("E < mc^2"));
QCOMPARE(i18n("E &lt; mc^2<br/>"),
QString("E &lt; mc^2<br/>"));
QCOMPARE(i18n("<b>E</b> &lt; mc^2"),
QString("<b>E</b> &lt; mc^2"));
QCOMPARE(i18n("<html>E &lt; mc^2</html>"),
QString("<html>E &lt; mc^2</html>"));
QCOMPARE(i18n("E ? <emphasis>mc^2</emphasis>"),
QString("E ? *mc^2*"));
QCOMPARE(i18n("E &lt; <emphasis>mc^2</emphasis>"),
QString("E < *mc^2*"));
QCOMPARE(i18n("<html>E &lt; <emphasis>mc^2</emphasis></html>"),
QString("<html>E &lt; <i>mc^2</i></html>"));
QCOMPARE(i18n("<b>E</b> &lt; <emphasis>mc^2</emphasis>"),
QString("<b>E</b> &lt; <i>mc^2</i>"));
QCOMPARE(i18n("<emphasis>E</emphasis> &lt; <b>mc^2</b>"),
QString("<i>E</i> &lt; <b>mc^2</b>"));
QCOMPARE(i18nc("@label", "E &lt; <emphasis>mc^2</emphasis>"),
QString("E < *mc^2*"));
QCOMPARE(i18nc("@info", "E &lt; <emphasis>mc^2</emphasis>"),
QString("<html>E &lt; <i>mc^2</i></html>"));
QCOMPARE(i18n("E = mc^&#x0032;"),
QString("E = mc^2"));
QCOMPARE(i18n("E = mc^&#0050;"),
QString("E = mc^2"));
QCOMPARE(i18n("E = mc^2"), QString("E = mc^2"));
QCOMPARE(i18n("E &lt; mc^2"), QString("E < mc^2"));
QCOMPARE(
i18n("E &lt; mc^2<br/>"),
QString("E &lt; mc^2<br/>")
);
QCOMPARE(
i18n("<b>E</b> &lt; mc^2"),
QString("<b>E</b> &lt; mc^2")
);
QCOMPARE(
i18n("<html>E &lt; mc^2</html>"),
QString("<html>E &lt; mc^2</html>")
);
QCOMPARE(
i18n("E ? <emphasis>mc^2</emphasis>"),
QString("E ? *mc^2*")
);
QCOMPARE(
i18n("E &lt; <emphasis>mc^2</emphasis>"),
QString("E < *mc^2*")
);
QCOMPARE(
i18n("<html>E &lt; <emphasis>mc^2</emphasis></html>"),
QString("<html>E &lt; <i>mc^2</i></html>")
);
QCOMPARE(
i18n("<b>E</b> &lt; <emphasis>mc^2</emphasis>"),
QString("<b>E</b> &lt; <i>mc^2</i>")
);
QCOMPARE(
i18n("<emphasis>E</emphasis> &lt; <b>mc^2</b>"),
QString("<i>E</i> &lt; <b>mc^2</b>")
);
QCOMPARE(
i18nc("@label", "E &lt; <emphasis>mc^2</emphasis>"),
QString("E < *mc^2*")
);
QCOMPARE(
i18nc("@info", "E &lt; <emphasis>mc^2</emphasis>"),
QString("<html>E &lt; <i>mc^2</i></html>")
);
QCOMPARE(i18n("E = mc^&#x0032;"), QString("E = mc^2"));
QCOMPARE(i18n("E = mc^&#0050;"), QString("E = mc^2"));
// Number formatting.
QCOMPARE(ki18n("%1").subs(42).toString(),
QString("42"));
QCOMPARE(ki18n("%1").subs(42, 5).toString(),
QString(" 42"));
QCOMPARE(ki18n("%1").subs(42, -5, 10, QChar('_')).toString(),
QString("42___"));
QCOMPARE(ki18n("%1").subs(4.2, 5, 'f', 2).toString(),
QString(" 4.20"));
QCOMPARE(ki18n("%1").subs(42).toString(), QString("42"));
QCOMPARE(ki18n("%1").subs(42, 5).toString(), QString(" 42"));
QCOMPARE(ki18n("%1").subs(42, -5, 10, QChar('_')).toString(), QString("42___"));
if (m_hasFrench) {
QCOMPARE(ki18n("%1").subs(4.2, 5, 'f', 2).toString(), QString(" 4,20"));
} else {
QCOMPARE(ki18n("%1").subs(4.2, 5, 'f', 2).toString(), QString(" 4.20"));
}
}
void KLocalizedStringTest::correctButIllFormed()
{
// ...and some ill-formed i18n, to test markup salvage.
// (prevent debug info about bad markup).
KConfig dc( "kdebugrc", KConfig::SimpleConfig );
KConfig dc("kdebugrc", KConfig::SimpleConfig );
dc.group(QString::number(173)).writeEntry("InfoOutput", 4);
dc.sync();
QCOMPARE(i18n("E < %1 * mc^2", 10),
QString("E < 10 * mc^2"));
QCOMPARE(i18n("<emphasis>%1</emphasis> &lt; mc^2", QString("<E>")),
QString("*<E>* &lt; mc^2"));
QCOMPARE(i18n("<emphasis>%1</emphasis> &lt; <b>mc^2</b>", QString("<E>")),
QString("<i><E></i> &lt; <b>mc^2</b>"));
QCOMPARE(i18n("E < %1 * mc^2", 10), QString("E < 10 * mc^2"));
QCOMPARE(
i18n("<emphasis>%1</emphasis> &lt; mc^2", QString("<E>")),
QString("*<E>* &lt; mc^2")
);
QCOMPARE(
i18n("<emphasis>%1</emphasis> &lt; <b>mc^2</b>", QString("<E>")),
QString("<i><E></i> &lt; <b>mc^2</b>")
);
}
void KLocalizedStringTest::wrongSubs ()
{
#ifndef NDEBUG
#ifndef NDEBUG
// Too many arguments.
QVERIFY(i18n("Europa", 1)
!= QString("Europa"));
QVERIFY(i18n("Europa", 1) != QString("Europa"));
// Too few arguments.
QVERIFY(i18n("%1, %2 and %3", QString("Hunter"), QString("Kimball"))
!= QString("Hunter, Kimball and %3"));
QVERIFY(
i18n("%1, %2 and %3", QString("Hunter"), QString("Kimball"))
!= QString("Hunter, Kimball and %3")
);
// Gaps in placheholder numbering.
QVERIFY(ki18n("Beyond the %2").subs("infinity").toString()
!= QString("Beyond the infinity"));
QVERIFY(
ki18n("Beyond the %2").subs("infinity").toString()
!= QString("Beyond the infinity")
);
// Plural argument not supplied.
QVERIFY(ki18np("1 pod", "%1 pods").toString()
!= QString("1 pod"));
QVERIFY(ki18np("1 pod", "%1 pods").toString()
!= QString("%1 pods"));
#endif
QVERIFY(ki18np("1 pod", "%1 pods").toString() != QString("1 pod"));
QVERIFY(ki18np("1 pod", "%1 pods").toString() != QString("%1 pods"));
#endif
}
void KLocalizedStringTest::miscMethods ()
void KLocalizedStringTest::miscMethods()
{
KLocalizedString k;
QVERIFY(k.isEmpty());