+1, non-binding
On 2026/08/28 23:01:23 "Evan Rusackas (ASF)" wrote:
> Hey all,
>
> Kicking off a new vote on an old SIP, that’s been largely implemented. Happy
> to see it moving again, and would be stoked to see it merged as Superset is
> *almost* fully translated nowadays! Let’s dive in...
>
> SIP-161 ("Translating Superset asset metadata"):
> https://github.com/apache/superset/issues/32854
>
> Quick background:
> This SIP got extensive [DISCUSS] treatment on this list and in the issue back
> in April 2025, and Max and I converged with the community on a minimal-core
> direction. Namely, a deployment-configurable `TRANSLATION_HOOK` as the only
> integration point, with Superset core never storing translations itself.
>
> The original proposer had to step away for funding reasons before we closed
> the loop with a vote, and the issue sat until @alex-poor (GH handle) picked
> it back up with a PR that implements this converged direction:
>
> https://github.com/apache/superset/pull/40679
>
> *************** DETAILS ***************
>
>
> What new things can be translated?
>
> • Chart names and dashboard titles, automatically — no author action needed.
> • Home-page "Recents" item titles.
> • Anything an author explicitly wraps in a new `{{ i18n('...') }}` Jinja
> macro inside a templated field (axis labels, native filter names, etc.)
> • This is opt-in per field, not automatic.
> • Explicitly not covered: the actual chart data/values and localized
> number/date formatting, which are the same exclusions the original SIP had.
>
>
> How are translations maintained and loaded?
>
> • Superset core stores none of it, that's the design shift from the original
> proposal.
> • There's one hook:
> • TRANSLATION_HOOK(text, locale, **context) -> str | None
> • You implement it in config, and back it with whatever you want — a
> static dict, an external MT API, gettext `.po` catalogs, or a database table,
> whatever
> • A `TRANSLATION_BATCH_HOOK` variant exists for anything where each
> lookup is a query or network call. Superset prefetches through it wherever it
> already holds a full collection (a dashboard's charts, the Recents list).
> That means a 30-chart dashboard costs 1 hook call, not 30, and results are
> memoized. The one place that still resolves per-row is the list views, since
> FAB serializes each row independently. The docs tell you to cache your hook
> if that matters.
> • There's no export/import built into core; that's on whatever you build
> behind the hook.
>
>
> Effect on our `.pot`/`.po` effort?
>
> • None on the existing pipeline — UI chrome strings are unaffected, nothing
> new gets added to Superset's own translatable-string extraction.
> • One of the four reference hooks in the docs *does* show how a deployment
> could reuse the gettext toolchain (Poedit/Transifex/Weblate) for asset
> content. But that’s in a separate catalog domain (e.g. `assets`) so it can't
> collide with or pollute our existing UI catalogs. Opt-in per deployment, zero
> impact on Superset’s core.
>
>
> Breaking? Nope… fully additive.
>
> • Feature flag + a multi-language `LANGUAGES` config are both required to
> activate anything, so virtually every existing single-language install is
> untouched.
> • New optional config hooks (no-op if undefined), new dump-only REST fields
> (`localized_name`/`localized_title`, nothing removed or renamed)
> • One new Jinja macro
> • No DB migration.
> • Editing a name always shows/saves the canonical value, the edit workflow
> doesn't change.
>
>
> Summary of what you'd be voting on:
>
>
> • A `TRANSLATION_HOOK(text, locale, **context) -> str | None` config hook
> (plus an optional batch variant for query/API-backed stores), fully pluggable
> — static map, external MT service, `.po` catalogs, a DB table, whatever a
> deployment wants.
> • A `{{ i18n('...') }}` Jinja macro for opt-in translation of templated
> fields.
> • - Gated behind `ENABLE_I18N_ASSET_TRANSLATIONS` + a multi-language
> `LANGUAGES` config, so single-language deployments (the default) pay zero
> cost.
> • No new core dependencies, no DB migration, no translations stored in
> Superset itself. Fully additive REST fields, editing always operates on the
> canonical name.
> • Automatically covers chart names and dashboard titles; anything else (axis
> labels, native filter names, etc.) is opt-in via the macro. Search/filtering
> on translated text is not addressed. Both are known, named gaps relative to
> the original SIP's ambitions, not oversights.
>
>
> Worth flagging from prior discussion / alternatives:
>
> • The original motivation explicitly called out *axis and metric labels* as
> things to translate. This PR only auto-covers `slice_name`/`dashboard_title`.
> Everything else needs manual `{{ i18n() }}` wrapping per field, per org, so
> it’s a narrower scope
> • "Search/filter by translated text" was an open question in the original SIP
> and remains unaddressed — list search still matches canonical text only.
> • The SIP's "markup vs. auto-wrap" contention is resolved as a hybrid option
> (auto for the two title fields, manual macro for everything else)
> • It was doubted that batch retrieval was feasible *through Jinja* but this
> PR sidesteps that by prefetching outside the macro (dashboard-charts
> endpoint, Recents), while the macro itself still resolves one string per call
> site, consistent with rather than disproving the doubt.
>
>
> The PR itself has already had thorough review already — worth an additional
> pass if you want the engineering details
>
> *************** /END WALL OF DETAILS ***************
>
>
> Please vote:
>
> [ ] +1 approve
> [ ] +0 no opinion
> [ ] -1 disapprove (please say why)
>
> Vote will stay open for at least 72 hours.
>
> Evan Rusackas
> Preset, Inc
> PMC, Apache Superset
> Member, ASF
>