You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Found and measured while implementing objectui#4566. Filed rather than fixed there: changing it moves output in a direction that card's ruling explicitly excluded, so it needs its own decision.
The divergence
The two formatters build the percent sign differently:
formatMeasure (@object-ui/core, utils/dataset-format.ts) appends a LITERAL % to a decimal-formatted body, so it gets no space in any locale.
Measured, de-DE, the same stored value:
surface
output
list cell (formatPercent)
1.234,5 % (U+00A0 before the sign)
dashboard measure (formatMeasure)
1.234,5%
English is identical on both paths (1,234.5%), so this is invisible in an en session. Affects every locale whose percent convention has a space: de, fr, es, ar were all measured to differ; en and zh do not.
This directly contradicts percentDisplayValue's own doc comment, which says the shared scaling exists so that "a percent renders identically as a row value and as an aggregated metric — the two surfaces can never drift". The SCALING no longer drifts; the CONVENTION now does.
Which convention is the correct one for a dashboard measure, given both surfaces show the same underlying number:
A. Route formatMeasure's percent branch through Intlstyle: 'percent' so both surfaces agree on the locale's convention. Costs the precision artefact above at extreme magnitudes (arguably irrelevant for a percentage, which is not normally 1e21).
C. Accept the divergence and record it at both ends.
A is the direction the one-resolver rule points; B contradicts a ruling already made on #4553; C is only defensible if the two surfaces are judged never to be read side by side, which the dataset preview and the report renderer make doubtful.
Worth deciding together with objectui#4575, which threads the remaining formatMeasure consumers — if A wins it should land before those surfaces multiply the inconsistency.
Found and measured while implementing objectui#4566. Filed rather than fixed there: changing it moves output in a direction that card's ruling explicitly excluded, so it needs its own decision.
The divergence
The two formatters build the percent sign differently:
formatPercent/formatPercentBody(@object-ui/fields) goes throughIntlwithstyle: 'percent'since objectui#4553 / PR fix(fields): formatPercent groups and follows the display locale — the last tooltip channel (#4553) #4565, so it gets the locale's percent CONVENTION — German writes a no-break space before the sign.formatMeasure(@object-ui/core,utils/dataset-format.ts) appends a LITERAL%to a decimal-formatted body, so it gets no space in any locale.Measured, de-DE, the same stored value:
formatPercent)1.234,5 %(U+00A0 before the sign)formatMeasure)1.234,5%English is identical on both paths (
1,234.5%), so this is invisible in an en session. Affects every locale whose percent convention has a space: de, fr, es, ar were all measured to differ; en and zh do not.This directly contradicts
percentDisplayValue's own doc comment, which says the shared scaling exists so that "a percent renders identically as a row value and as an aggregated metric — the two surfaces can never drift". The SCALING no longer drifts; the CONVENTION now does.Why #4566 did not fix it
Two measured reasons, both worth keeping on the record:
Intl'sstyle: 'percent're-scales by 100, and the round trip loses precision at the top of the range:100,000,000,000,000,000,000,000%becomes99,999,999,999,999,990,000,000%in en-US (24 of 32,760 measured combinations move, all at 1e21 and MAX_SAFE_INTEGER). [core] formatMeasure renders every dashboard measure in the MACHINE locale — the last parallel implementation outside the display-locale channel #4566's ruling made en byte-identity the discriminator for a correct mapping, so this change could not ride along on it.The decision this needs
Which convention is the correct one for a dashboard measure, given both surfaces show the same underlying number:
formatMeasure's percent branch throughIntlstyle: 'percent'so both surfaces agree on the locale's convention. Costs the precision artefact above at extreme magnitudes (arguably irrelevant for a percentage, which is not normally 1e21).formatPercentinstead, i.e. keep the literal sign on both. Cheaper and en-stable, but it deliberately renders German against its own convention, which is what [plugin-gantt] tooltip number / currency / percent rows render in the MACHINE locale, next to date rows that follow the display locale #4553 set out to stop.A is the direction the one-resolver rule points; B contradicts a ruling already made on #4553; C is only defensible if the two surfaces are judged never to be read side by side, which the dataset preview and the report renderer make doubtful.
Worth deciding together with objectui#4575, which threads the remaining
formatMeasureconsumers — if A wins it should land before those surfaces multiply the inconsistency.Generated by Claude Code