sadpandajoe commented on code in PR #40679:
URL: https://github.com/apache/superset/pull/40679#discussion_r3819304816


##########
superset/charts/schemas.py:
##########
@@ -223,6 +227,9 @@ class ChartEntityResponseSchema(Schema):
 
     id = fields.Integer(metadata={"description": id_description})
     slice_name = fields.String(metadata={"description": 
slice_name_description})
+    localized_name = fields.String(

Review Comment:
   This adds a public response field, but the checked-in 
`docs/static/resources/openapi.json` still contains neither `localized_name` 
nor `localized_title`. Could the generated OpenAPI artifact be refreshed so 
generated clients and API documentation can discover the new contract?



##########
examples/asset_metadata_translation/README.md:
##########
@@ -0,0 +1,65 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+# Reference: database-backed asset metadata translation
+
+This is a **self-contained reference**, not part of Superset core. It shows one
+concrete way to implement end-to-end authoring on top of the
+`TRANSLATION_HOOK` read path documented at
+[Asset Metadata 
Translation](https://superset.apache.org/docs/configuration/asset-metadata-translation).
+
+Superset core intentionally ships only the read path (the hook + the Jinja
+`i18n` macro). It does **not** provide storage or an authoring UI — those are
+left to deployments so core stays minimal (per SIP-161 / the maintainer
+direction). This example fills that gap for the common case: "I want editors to
+enter translations and have them stored in the metadata database."
+
+## What it provides
+
+- `model.py` — a single `AssetTranslation` table keyed by
+  `(model_name, field_name, default_text, language_code)`.
+- `hook.py` — a `translation_hook(default_text, locale, **kwargs)` that reads
+  that table, suitable for assigning to `TRANSLATION_HOOK`.
+- `seed.py` — a small helper to populate translations programmatically (stand
+  in for, or grow into, a real authoring UI / CSV import / Transifex sync).
+
+## Why it lives outside core
+
+A production-grade version of this would be a proper
+[Superset extension](https://superset.apache.org/docs/contributing/development)
+(its own migration, CRUD API, and React authoring surface). That is a separate
+project. This example deliberately stays minimal so it reads as documentation:
+enough to wire up and demonstrate, not a supported component.
+
+## Usage sketch
+
+```python
+# superset_config.py
+from asset_metadata_translation.hook import translation_hook

Review Comment:
   Following this example verbatim imports a top-level 
`asset_metadata_translation` package that is not installed by Superset: 
packaging includes `superset` but not the new top-level `examples/` directory. 
Could the example either document the required copy/PYTHONPATH step or be 
packaged so this configuration does not fail at startup with 
`ModuleNotFoundError`?



##########
superset/models/dashboard.py:
##########
@@ -328,13 +348,27 @@ def data(self) -> dict[str, Any]:
         positions = self.position_json
         if positions:
             positions = json.loads(positions)
+        # Resolve every chart name in one shot; the per-slice 
``localized_name``
+        # lookups below then read from the request memo instead of hitting the
+        # translation hook once per chart. Gated so a disabled deployment does
+        # not pay for the extra pass over the slices.
+        if is_asset_translation_enabled():

Review Comment:
   The new prefetch is in `Dashboard.data`, but the dashboard UI gets its chart 
payload from the `/dashboard/<id>/charts` endpoint rather than this property. 
That path serializes each slice independently, so a configured batch hook is 
invoked once per chart instead of once per dashboard. Could the chart endpoint 
prefetch the slice names before serialization so a dashboard with a 
remote-backed hook does not make N translation calls?



##########
docs/admin_docs/configuration/asset-metadata-translation.mdx:
##########
@@ -0,0 +1,228 @@
+---
+title: Asset Metadata Translation
+hide_title: true
+sidebar_position: 16
+version: 1
+---
+
+# Asset Metadata Translation
+
+Superset's built-in internationalization (Flask-Babel / gettext) translates the
+application's **UI chrome** — buttons, menus, labels, error messages. It does
+**not** translate user-authored content such as chart names, dashboard titles,
+or axis/metric labels, because those are stored as data rather than as
+translatable source strings.
+
+This feature lets a deployment localize that user-authored metadata, so a chart
+named "Sales" can display as "Ventes" to a French viewer and "Hokohoko" to a
+Māori viewer — while the canonical stored name stays unchanged.
+
+:::info Background
+This implements the read path discussed in
+[SIP-161](https://github.com/apache/superset/issues/32854). Superset core does
+**not** store these translations. It calls a deployment-provided
+`TRANSLATION_HOOK` at render time; where the translations live and how they are
+authored is entirely up to the deployment (a static map, an external machine
+translation service, a database table, gettext `.po` catalogs, …). This keeps
+core minimal and the storage/authoring strategy pluggable.
+:::
+
+## Enabling
+
+Two conditions must both be true, otherwise translation is skipped entirely
+(single-language deployments pay zero cost):
+
+1. The `ENABLE_I18N_ASSET_TRANSLATIONS` [feature 
flag](/admin-docs/configuration/configuring-superset#feature-flags)
+   is enabled.
+2. More than one language is configured in `LANGUAGES`.
+
+```python
+# superset_config.py
+FEATURE_FLAGS = {
+    "ENABLE_I18N_ASSET_TRANSLATIONS": True,
+}
+
+BABEL_DEFAULT_LOCALE = "en"
+LANGUAGES = {
+    "en": {"flag": "us", "name": "English"},
+    "fr": {"flag": "fr", "name": "French"},
+}
+```
+
+When enabled, the canonical text is always returned unchanged if:
+
+- the active locale is the default locale (`BABEL_DEFAULT_LOCALE`), or
+- no `TRANSLATION_HOOK` is configured, or

Review Comment:
   This says the canonical value is returned when no `TRANSLATION_HOOK` is 
configured, but the supported `TRANSLATION_BATCH_HOOK`-only setup below still 
translates values. Could this say that neither translation hook is configured 
(and update the later Jinja wording too), so the documented fallback matches 
the runtime contract?



-- 
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