sadpandajoe opened a new pull request, #44467:
URL: https://github.com/apache/superset/pull/44467

   ### SUMMARY
   
   `superset/translations/messages.pot` is the extraction template every 
language
   catalog is generated from, but nothing in CI ever compared the committed
   template against a fresh extraction. The `babel-extract` job regenerates
   `messages.pot` from scratch in throwaway worktrees before comparing
   translated/fuzzy counts — a check scoped to catching a reworded source string
   invalidating an existing translation, not template/source parity. The 
template
   had drifted 432 strings behind source and carried 109 stale entries, so those
   432 strings could not reach any of the 30 `.po` catalogs and were 
untranslatable
   in every language.
   
   This PR does three things.
   
   **1. Adds a drift guard.** `scripts/translations/check_pot_drift.py` 
re-extracts
   from source with the same `pybabel extract` invocation as `babel_update.sh` 
and
   fails when the committed template's msgid set differs from a fresh 
extraction.
   It is wired into the `babel-extract` job as a hard gate, placed before
   `babel_update.sh` overwrites the workspace template. Comparison is on msgid 
sets
   only, so it is insensitive to `POT-Creation-Date` churn and to the
   do-not-translate / `python-format` post-processing steps. Line wrapping is
   deliberately *not* normalized away: gettext continuation lines concatenate 
back
   to the exact original, so any whitespace difference that survives parsing is 
a
   real source reword that gettext's exact-match lookup would miss.
   
   **2. Unbreaks extraction of the explore additional-actions menu.**
   `useExploreAdditionalActionsMenu/index.tsx` was almost entirely invisible to
   `pybabel extract`: `return /[",\r\n]/.test(s) ? ... : s;` puts a regex 
literal
   directly after `return`, and babel's JavaScript lexer reads that `/` as
   division, so the `"` inside the character class opens a phantom string 
literal
   that swallows the next ~290 lines. Only 3 of the module's 34 translatable
   strings survived extraction. The stale template still carried the other 31 
only
   because it predated the file's current shape — so regenerating it would have
   deleted 10 still-live, already-translated strings ("Export All Data", "Export
   Current View", "New chart", "Superset Chart", …) from all 30 catalogs. 
Hoisting
   the regex into a module constant fixes extraction with no behavior change.
   
   **3. Regenerates the template and all 30 catalogs** via `babel_update.sh`'s 
own
   sequence, so the new guard starts green. Adding the guard without 
regenerating
   would fail CI immediately against the already-stale template.
   
   Regeneration changes **zero existing translation values** (verified by 
parsing
   both revisions with `babel.messages.pofile.read_po` for all 30 catalogs, and
   independently re-verified in review): the diff is additions plus the removal 
of
   100 msgids that no longer exist in source, none of which still appear inside 
a
   `t()`/`_()`/`__()`/`tct()` call. The `it/messages.po` catalog's diff looks 
large
   because `babel_update.sh` also normalizes it from CRLF to LF line endings
   (master's copy was the only CRLF-encoded catalog) — that's a whitespace-only
   normalization, not a retranslation; the zero-changed-values check above 
covers
   it.
   
   Note: `babel_update.sh`'s `msgcat --sort-by-msgid --no-wrap` step is a no-op 
in
   CI today — `--sort-by-msgid` is not an msgcat option, the script has no
   `set -e`, so msgcat exits without writing. This PR reproduces current CI 
output
   rather than introducing a new convention; the flag itself is addressed
   separately in #44395. Its other two effects are redundant, since 
`--sort-output`
   and `--no-location` are already on the `pybabel extract` call.
   
   Out of scope, left untouched (separate, pre-existing issues): 
`flask_babel.lazy_gettext` call sites (e.g. `superset/views/filters.py:330`) 
are not reachable by `pybabel extract` at all, since neither babel's default 
keywords nor this project's `-k` list include `lazy_gettext` — worth its own 
follow-up issue.
   
   Fixes #44403
   
   ### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
   
   ### TESTING INSTRUCTIONS
   
   Guard passes on this branch:
   
       python scripts/translations/check_pot_drift.py
       # superset/translations/messages.pot matches a fresh extraction.
   
   Guard catches the bug it exists for — restore the pre-fix template and 
re-run:
   
       git show master:superset/translations/messages.pot > 
superset/translations/messages.pot
       python scripts/translations/check_pot_drift.py
       # exits 1: strings missing/stale
       git checkout -- superset/translations/messages.pot
   
   Unit tests (mocked cases plus a real end-to-end extraction against this
   checkout):
   
       pytest tests/unit_tests/scripts/translations/
   
   Frontend behavior of the hoisted regex is unchanged:
   
       cd superset-frontend
       npm run test -- src/explore/components/useExploreAdditionalActionsMenu
   
   Regeneration is idempotent — re-running 
`./scripts/translations/babel_update.sh`
   produces no diff beyond `POT-Creation-Date`.
   
   ### ADDITIONAL INFORMATION
   - [x] Has associated issue: #44403
   - [ ] Required feature flags:
   - [ ] Changes UI
   - [ ] Includes DB Migration (follow approval process in 
[SIP-59](https://github.com/apache/superset/issues/13351))
     - [ ] Migration is atomic, supports rollback & is backwards-compatible
     - [ ] Confirm DB migration upgrade and downgrade tested
     - [ ] Runtime estimates and downtime expectations provided
   - [ ] Introduces new feature or API
   - [ ] Removes existing feature or API
   


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