Skip to content

[core][fields] A percent renders as 1.234,5 % in a list cell and 1.234,5% as a dashboard measure — two percent conventions for one number #4576

Description

@yinlianghui

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:

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.

Why #4566 did not fix it

Two measured reasons, both worth keeping on the record:

  1. It would move English. Intl's style: '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% becomes 99,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.
  2. It is a change of RENDERING CONVENTION, not of locale channel — a different claim from the one [core] formatMeasure renders every dashboard measure in the MACHINE locale — the last parallel implementation outside the display-locale channel #4566 was making, and it deserves to be judged on its own.

The decision this needs

Which convention is the correct one for a dashboard measure, given both surfaces show the same underlying number:

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.


Generated by Claude Code

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions