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]

Reply via email to