verdier opened a new issue, #45240:
URL: https://github.com/apache/superset/issues/45240
## Summary
Superset exposes `D3_FORMAT`, `D3_TIME_FORMAT` and `CURRENCIES` in
`superset_config.py`, but a deployment cannot cleanly render numbers, dates and
currencies in a non-US locale:
1. `D3_FORMAT` does not reach the default number format, so most charts keep
`1,234.5` whatever the config says.
2. The locale is one global value per deployment, not tied to the UI
language.
3. The `currency` key of `D3_FORMAT` rewrites the `$` of every saved format,
so it cannot be used to localise currencies.
4. Server-side outputs (CSV/Excel exports, reports) ignore `D3_FORMAT`.
Checked on `master` (`f18c034a68`, 2026-10-13) and on `6.1.0`.
## Details
### 1. SMART_NUMBER is built with the hard-coded en-US locale
`NumberFormatterRegistry` registers `SMART_NUMBER` and `SMART_NUMBER_SIGNED`
in its constructor and makes `SMART_NUMBER` the default key
(`number-format/NumberFormatterRegistry.ts:39-47`).
`createSmartNumberFormatter` builds its d3 formatters once, at module load,
from `DEFAULT_D3_FORMAT`
(`number-format/factories/createSmartNumberFormatter.ts:25`).
`createSiAtMostNDigitFormatter` does the same
(`createSiAtMostNDigitFormatter.ts:33`).
`setD3Format()`, called from `setupFormatters` with
`bootstrapData.common.d3_format`, only updates `this.d3Format`, which is used
for formatters created lazily from a format string
(`NumberFormatterRegistry.ts:51-75`). The two pre-registered formatters never
see it.
Result: with
```python
D3_FORMAT = {"decimal": ",", "thousands": " ", "grouping": [3]}
```
an explicit `,.2f` renders `1 234,50`, but every chart left on the default
("Adaptive formatting") still renders `1.23k` / `1,234.50`. This is most likely
the root cause behind #35088 and #29140 (both closed as configuration
questions).
### 2. One locale per deployment, unrelated to the UI language
`D3_FORMAT` and `D3_TIME_FORMAT` are global. Switching the UI language
through `LANGUAGES` changes the translations but not the number or date locale.
A deployment serving several languages has to pick one number locale for
everyone. Since #40931 (not in 6.1), the currency symbol *position* follows the
UI locale through `setCurrencyLocale(locale)`, so number separators and
currency position can now disagree.
### 3. `currency` in D3_FORMAT is not a currency setting
d3-format replaces `$` in a format string with `currency[0]`/`currency[1]`.
Saved charts use `$,.2f` as "a number with a currency sign", so setting
`currency: ["", " €"]` turns every one of them into euros, whatever the data.
Meanwhile, the dedicated currency feature (`CurrencyFormatter`) strips `$` and
formats the value with `SMART_NUMBER` by default (point 1), so currency columns
stay en-US.
### 4. Other hard-coded locales
- `plugin-chart-handlebars` `formatNumber` helper: default `locale =
'en-US'` (`HandlebarsViewer.tsx:123`).
- `preset-chart-deckgl` Handlebars renderer: same
(`HandlebarsRenderer.tsx:111`).
- `DatasourceEditor.tsx:1114`: `Intl.NumberFormat('en-US', …)`.
- Several `toLocaleString()` calls without a locale use the *browser* locale
instead (SQL Lab row count, dashboard header), so one page can mix two
conventions.
- Server side: CSV/Excel exports and report bodies format numbers in Python
and never read `D3_FORMAT`.
## Proposal
Smallest useful step, which I am happy to send as a PR:
- **Make the pre-registered formatters follow `setD3Format`**: have
`setD3Format()` rebuild `SMART_NUMBER` / `SMART_NUMBER_SIGNED` with the new
locale (`createSmartNumberFormatter({ locale })`). This is backward compatible:
with the default config, the output is identical.
Follow-ups to discuss:
- A `locale` option for `createSiAtMostNDigitFormatter` (it strips trailing
zeros with `parseFloat`, which needs care once the decimal separator is not
`.`).
- An optional per-language map (e.g. `D3_FORMAT_BY_LOCALE = {"fr": {...}}`)
resolved against the active UI locale, with `D3_FORMAT` as the fallback; same
for `D3_TIME_FORMAT`.
- Documenting that `currency` in `D3_FORMAT` rewrites `$` in saved formats,
and should normally be left unset.
- Passing the active locale to the Handlebars helpers and the remaining
`Intl`/`toLocaleString` calls.
## Environment
- Superset `6.1.0`, also reproduced by reading `master` `f18c034a68`.
- `superset_config.py`: `D3_FORMAT` as above, `BABEL_DEFAULT_LOCALE = "fr"`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]