Split out of #574, which listed it as one of two "smaller fixes while there" and whose PR (#581) deliberately did not take it: it is an API change to both control edges and all their call sites, and unlike the group-separator defect it does not produce a wrong value — it rejects a valid entry. Filing it so closing #574 does not lose it.
Verification status: reproduced
Revision: fix-574-quantity-provenance-locale @ 3a1effd0 (PR #581), i.e. after the group-separator fix. The sign behaviour is unchanged by that PR.
morph::render::normalizeLocaleNumber(text, decimalSeparator, groupSeparator) takes both separators as std::string_view precisely because a real locale's separator is not always one byte (fr-FR groups with U+202F). The sign got no such treatment: it is matched as the literal byte '-', in include/morph/render/locale_format.hpp:
char const chr = text[i];
if (chr == '-') {
So a locale whose minus sign is U+2212 MINUS SIGN (−, 3 UTF-8 bytes) cannot round-trip:
normalize("−5", dec=".", grp="") = NULLOPT
— the first byte of U+2212 is not a digit, not '-', and matches neither separator, so the entry is reported malformed. formatCanonicalNumber, the display-direction inverse, has the mirror-image problem: it emits a literal '-' whatever the locale.
The same is true of the QML mirror in src/qt/forms/qml/DynamicForm.qml, which compares ch === "-".
Why it matters, and why it is smaller than #574 was
This one rejects, it does not silently mis-convert. A user who types −5 is told the entry is malformed, which is wrong but visible and recoverable — the opposite of "1.5" → 15, which was the whole reason #574 was a defect. So the cost is a usability failure in a locale that uses the typographic minus, not a wrong number on the wire.
Qt's QLocale::negativeSign() returns U+2212 for several locales, and DynamicForm.qml reads the rest of its separators straight off Qt.locale(), so a renderer that passed qtLocale.negativeSign through would be handing this function something it cannot accept today.
Suggested shape
A fourth parameter, std::string_view negativeSign = "-", matched as a whole string the way the separators already are, and the same on formatCanonicalNumber so the pair stays inverse. Both edges must change together — docs/spec/forms/forms.md, "Locale data formatting", records that a divergence between the C++ function and its QML mirror is a divergence in what the product accepts.
Not verified
- Which locales Qt actually reports U+2212 for on each platform, and whether any application in this repository configures one. The claim above is about
QLocale's documented behaviour, not a measurement.
- Whether a
positiveSign parameter is wanted for symmetry. Neither edge accepts a leading + today at all, in any locale, which is a separate question.
What would change the verdict
Close this if the control edge is deliberately restricted to ASCII - on entry, with the renderer expected to normalise the sign before calling — but nothing says that today, and the separators set the opposite precedent in the same function.
Split out of #574, which listed it as one of two "smaller fixes while there" and whose PR (#581) deliberately did not take it: it is an API change to both control edges and all their call sites, and unlike the group-separator defect it does not produce a wrong value — it rejects a valid entry. Filing it so closing #574 does not lose it.
Verification status: reproduced
Revision:
fix-574-quantity-provenance-locale@3a1effd0(PR #581), i.e. after the group-separator fix. The sign behaviour is unchanged by that PR.morph::render::normalizeLocaleNumber(text, decimalSeparator, groupSeparator)takes both separators asstd::string_viewprecisely because a real locale's separator is not always one byte (fr-FR groups with U+202F). The sign got no such treatment: it is matched as the literal byte'-', ininclude/morph/render/locale_format.hpp:So a locale whose minus sign is U+2212 MINUS SIGN (
−, 3 UTF-8 bytes) cannot round-trip:— the first byte of U+2212 is not a digit, not
'-', and matches neither separator, so the entry is reported malformed.formatCanonicalNumber, the display-direction inverse, has the mirror-image problem: it emits a literal'-'whatever the locale.The same is true of the QML mirror in
src/qt/forms/qml/DynamicForm.qml, which comparesch === "-".Why it matters, and why it is smaller than #574 was
This one rejects, it does not silently mis-convert. A user who types
−5is told the entry is malformed, which is wrong but visible and recoverable — the opposite of"1.5"→15, which was the whole reason #574 was a defect. So the cost is a usability failure in a locale that uses the typographic minus, not a wrong number on the wire.Qt's
QLocale::negativeSign()returns U+2212 for several locales, andDynamicForm.qmlreads the rest of its separators straight offQt.locale(), so a renderer that passedqtLocale.negativeSignthrough would be handing this function something it cannot accept today.Suggested shape
A fourth parameter,
std::string_view negativeSign = "-", matched as a whole string the way the separators already are, and the same onformatCanonicalNumberso the pair stays inverse. Both edges must change together —docs/spec/forms/forms.md, "Locale data formatting", records that a divergence between the C++ function and its QML mirror is a divergence in what the product accepts.Not verified
QLocale's documented behaviour, not a measurement.positiveSignparameter is wanted for symmetry. Neither edge accepts a leading+today at all, in any locale, which is a separate question.What would change the verdict
Close this if the control edge is deliberately restricted to ASCII
-on entry, with the renderer expected to normalise the sign before calling — but nothing says that today, and the separators set the opposite precedent in the same function.