Skip to content

feat(i18n): translate asset metadata via configurable hook (SIP-161)#40679

Draft
alex-poor wants to merge 7 commits into
apache:masterfrom
alex-poor:feat/i18n-asset-metadata
Draft

feat(i18n): translate asset metadata via configurable hook (SIP-161)#40679
alex-poor wants to merge 7 commits into
apache:masterfrom
alex-poor:feat/i18n-asset-metadata

Conversation

@alex-poor
Copy link
Copy Markdown
Contributor

SUMMARY

Revives SIP-161 (Translating Superset asset metadata) with a focused, minimal-core implementation of the read path.

Superset's built-in i18n (Flask-Babel/gettext) translates UI chrome but not user-authored content — chart names, dashboard titles, axis/metric labels. This PR lets a deployment localize that metadata so a chart named "Sales" can display as "Ventes" / "Hokohoko" per the viewer's locale, while the canonical stored name is never changed.

Design — aligned with the maintainer direction on the SIP (mistercrunch/rusackas, Apr 2025): keep core minimal and push storage/authoring to deployments.

  • A configurable TRANSLATION_HOOK (default_text, locale, **context) -> str | None is the only integration point. Superset core does not store translations — the hook decides where they live (static map, external MT service, a table, .po catalogs, …).
  • A {{ i18n('...') }} Jinja macro lets templated fields opt in.
  • Gated by the ENABLE_I18N_ASSET_TRANSLATIONS feature flag and a multi-language LANGUAGES config, so single-language deployments pay zero cost.
  • The canonical text is always a safe fallback (missing/erroring hook → original text), and edit flows always operate on the canonical name — a translation can never be persisted over the real name.

This is the read path only. Storage and an authoring UI are intentionally left out of core; a self-contained database-backed reference (table + hook + seeding) is provided under examples/ to show end-to-end authoring without shipping it as a supported component.

Surfaces localized: chart/dashboard lists & cards, dashboard view header, chart panel titles, home "Recents" cards, and {{ i18n() }}-wrapped templated fields.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

Verified locally end-to-end with a demo hook (en + Māori): list pages, cards, dashboard header, and chart panels display the localized name; edit modals/inline title editing show the canonical English name. (Screenshots to be added.)

TESTING INSTRUCTIONS

  1. In superset_config.py:
    FEATURE_FLAGS = {"ENABLE_I18N_ASSET_TRANSLATIONS": True}
    LANGUAGES = {"en": {"flag": "us", "name": "English"},
                 "fr": {"flag": "fr", "name": "French"}}
    def TRANSLATION_HOOK(default_text, locale, **kwargs):
        return {("fr", "Sales"): "Ventes"}.get((locale, default_text))
  2. Name a chart "Sales", switch language to French, and view the chart/dashboard lists, cards, and dashboard — the name displays as "Ventes".
  3. Open the chart's Properties modal — the Name field still shows "Sales" (canonical).
  4. Switch back to English — the name reverts.

Automated: pytest tests/unit_tests/utils/i18n_test.py and the new recent_activity localization integration test in tests/integration_tests/log_api_tests.py; SliceHeader render tests cover the view-vs-edit behavior.

ADDITIONAL INFORMATION

Opened as a draft to restart the SIP-161 discussion with a concrete, reviewable read-path implementation. Storage/authoring deliberately deferred — feedback welcome on whether the hook contract is the right minimal-core surface.

alex-poor and others added 4 commits June 2, 2026 19:59
Add a read path for localizing user-authored asset metadata (chart names,
dashboard titles, axis/metric labels) into the viewer's locale, gated by the
ENABLE_I18N_ASSET_TRANSLATIONS feature flag and a multi-language LANGUAGES
config.

Superset core does not store translations; resolution is delegated to a
deployment-provided TRANSLATION_HOOK, keeping core minimal and the storage
strategy pluggable (per the SIP-161 maintainer direction). The canonical text
is always a safe fallback, so a missing or failing translation never blanks a
name.

- superset/utils/i18n.py: translate() resolver + enable gate
- config: ENABLE_I18N_ASSET_TRANSLATIONS flag + TRANSLATION_HOOK
- models: read-only localized_name / localized_title properties
- charts/dashboards schemas + list_columns: expose localized_* (dump-only)
- jinja_context: {{ i18n('...') }} macro for templated fields
- daos/log: localize recent-activity item titles

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Display the localized_name / localized_title fields across all surfaces that
show user-authored names, falling back to the canonical value:

- chart & dashboard list pages and cards
- dashboard view header and chart panel titles

Editing flows (Properties modals, inline title editing) keep operating on the
canonical slice_name / dashboard_title, so a save can never overwrite the
stored name with a translation. The localized title for the dashboard view is
carried as display-only state, never into persisted layout meta.

Also threads localized_title through the column allowlists the dashboard view
(DASHBOARD_GET_COLUMNS) and list (DASHBOARD_COLUMNS_TO_FETCH) request, which
otherwise silently drop unlisted fields.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- unit tests for translate(): enable gate, default-locale/hook/raise fallbacks,
  context forwarding, empty-text passthrough
- SliceHeader tests: localized name shown when viewing, canonical name shown in
  edit mode (so edits target the real value)
- integration test for recent-activity title localization

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- admin docs for the hook contract, the i18n Jinja macro, the enable gate, and
  three reference hook implementations (static dict, MT service, .po catalogs)
- a self-contained database-backed example (table + hook + seeding) under
  examples/, kept out of core to demonstrate end-to-end authoring

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added api Related to the REST API doc Namespace | Anything related to documentation labels Jun 2, 2026
@netlify
Copy link
Copy Markdown

netlify Bot commented Jun 2, 2026

Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit 840efd6
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/6a1e8db9e1d3e70008c0223e
😎 Deploy Preview https://deploy-preview-40679--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 2, 2026

Codecov Report

❌ Patch coverage is 55.93220% with 26 lines in your changes missing coverage. Please review.
✅ Project coverage is 55.92%. Comparing base (c29591b) to head (b99a392).
⚠️ Report is 61 commits behind head on master.

Files with missing lines Patch % Lines
superset/utils/i18n.py 31.03% 20 Missing ⚠️
superset/daos/log.py 33.33% 2 Missing ⚠️
superset/jinja_context.py 33.33% 2 Missing ⚠️
superset/models/dashboard.py 75.00% 1 Missing ⚠️
superset/models/slice.py 75.00% 1 Missing ⚠️

❗ There is a different number of reports uploaded between BASE (c29591b) and HEAD (b99a392). Click for more details.

HEAD has 39 uploads less than BASE
Flag BASE (c29591b) HEAD (b99a392)
javascript 3 1
python 31 5
presto 3 1
hive 3 1
unit 10 3
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #40679      +/-   ##
==========================================
- Coverage   63.94%   55.92%   -8.03%     
==========================================
  Files        2658     2659       +1     
  Lines      143011   143075      +64     
  Branches    32866    32880      +14     
==========================================
- Hits        91454    80015   -11439     
- Misses      49994    62372   +12378     
+ Partials     1563      688     -875     
Flag Coverage Δ
hive 39.76% <46.93%> (+<0.01%) ⬆️
javascript 67.37% <100.00%> (+<0.01%) ⬆️
mysql ?
postgres ?
presto 41.36% <46.93%> (+<0.01%) ⬆️
python 42.68% <46.93%> (-17.28%) ⬇️
sqlite ?
unit 100.00% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

The dashboard list now requests localized_title in select_columns; update the
inline snapshot of the fetch URL to match.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
alex-poor and others added 2 commits June 2, 2026 20:35
The shared integration-test database may contain unrelated recent activity, so
locate the seeded dashboard's entry by item_url rather than assuming it is
first in the result.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- add unit tests for the i18n_macro (translates via hook; no-op when disabled)
- ignore examples/ in codecov: the reference implementation is documentation,
  not shipped application code

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api Related to the REST API doc Namespace | Anything related to documentation review:draft size/XXL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants