Skip to content

UI: Fix labels that render as raw translation keys - #75326

Merged
bbovenzi merged 2 commits into
apache:mainfrom
Pushkal-Gupta:fix-ui-missing-translation-keys
Oct 27, 2026
Merged

bbovenzi merged 2 commits into
apache:mainfrom
Pushkal-Gupta:fix-ui-missing-translation-keys

Conversation

@Pushkal-Gupta

Copy link
Copy Markdown
Contributor

Seven labels in the UI show a translation key instead of a sentence.

Set a pool name longer than 256 characters and the validation error reads:

pools.form.rules.nameMaxLength

It should read "Name can contain a maximum of 256 characters". That string already exists, and is already translated into all 21 languages. The form just asks for it by the wrong name.

What a user sees today

Each of these keys is missing from the en bundles, so i18next renders the key itself:

Where Key asked for What is shown
Pool form validation admin:pools.form.rules.nameMaxLength pools.form.rules.nameMaxLength
Config form error common:error.unknown error.unknown
Connection form error common:error.unknown error.unknown
Dag code page dag:dagDetails.bundleVersion dagDetails.bundleVersion
XCom column header dashboard:timestamp timestamp
Table sort button components:sort sort
Dag schedule dags:schedule.asset schedule.asset

Those are real outputs, read off an i18next instance built from the en bundles.

Three different causes

Two ask for a string that exists under another name. pools.form.nameMaxLength and common:error.defaultMessage are both present and translated in all 21 locales, so correcting the call restores the text in every language at once.

In PoolForm.tsx the line above already gets it right:

required: translate("pools.form.nameRequired"),
validate: (_value) => _value.length <= 256 || translate("pools.form.rules.nameMaxLength"),

The extra rules. reads like it came from the rules: {} object the call sits in. No locale has ever defined pools.form.rules, and common:error has defaultMessage but never had unknown.

Three were never written. dagDetails.bundleVersion, xcom.columns.timestamp and components:sort do not exist in any locale, so this adds them to en and leaves the other languages to translators, as usual. The XCom header was also reaching into the dashboard namespace for a column title; it now sits with the dag, key and value headers it belongs to.

One is a comparison that can never be true. Schedule.tsx chose between two views with:

timetableSummary === translate("schedule.asset")

timetableSummary comes from the server as AssetTriggeredTimetable.summary, which is the fixed literal "Asset". Comparing it to a translated string is wrong even with the key in place, because a translator localising that word would break the check in their language. With the key missing it compares against "schedule.asset" and never matches. It now compares against the literal, with a comment recording where the value comes from.

This one has stayed hidden because the || before it means the asset view still appeared whenever asset_expression was set.

The test

locales.test.ts gains one check: walk every .ts and .tsx file under src/, collect the namespaces each file loads and every literal key it passes to translate(...), and assert i18next can resolve them. It fails without this change and names all seven. Keys built by interpolation are skipped, as they only exist at run time.

It asks i18next rather than reimplementing the lookup, which turned out to matter. My first attempt reported 52 failures, nearly all wrong, because a hand-rolled check misses three things the real resolver handles:

  • plural-only keys, stored as foo_one and foo_other with no plain foo
  • flat keys that contain dots, like "limitedList.allItems" in components.json
  • a file listing several namespaces, all of which i18next searches, not just the first

exists(key, { count: 1 }) gets all three right. The counter-placeholder tests already in this file build an instance the same way.

Nothing checked this before. locales.test.ts only verified counter formatting, which is why seven keys could drift.

Checks

  • 1961 UI tests pass, 239 files
  • eslint and tsc clean
  • the new check reports 0 missing of 1256 keys after the change, 7 before

Was generative AI tooling used to co-author this PR?
  • Yes - Claude Code (Opus 5)

@boring-cyborg boring-cyborg Bot added area:translations area:UI Related to UI/UX. For Frontend Developers. translation:default labels Oct 21, 2026
@Pushkal-Gupta
Pushkal-Gupta force-pushed the fix-ui-missing-translation-keys branch from 0b59292 to 5601170 Compare October 21, 2026 16:13
@bbovenzi bbovenzi added the backport-to-v3-4-test Backport to v3-4-test label Oct 27, 2026
@bbovenzi bbovenzi added this to the Airflow 3.4.0 milestone Oct 27, 2026
@bbovenzi
bbovenzi merged commit d92a480 into apache:main Oct 27, 2026
78 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

Backport successfully created: v3-4-test

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

Status Branch Result
✅ v3-4-test PR Link

bbovenzi added a commit that referenced this pull request Oct 27, 2026
… (#75798)

(cherry picked from commit d92a480)

Co-authored-by: Pushkal Gupta <161060351+Pushkal-Gupta@users.noreply.github.com>
Co-authored-by: Brent Bovenzi <brent@astronomer.io>
aaiss0927 added a commit to aaiss0927/airflow-1 that referenced this pull request Oct 28, 2026
Covers the three keys added to en after this branch was cut:
xcom.columns.timestamp (browse), dagDetails.bundleVersion (common,
matching the existing versionDetails.bundleVersion wording), and the
sort aria-label (components).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A18rBgPJ6X4oXAzsecJjnz
aaiss0927 added a commit to aaiss0927/airflow-1 that referenced this pull request Oct 28, 2026
Covers the three keys added to en after this branch was cut:
xcom.columns.timestamp (browse), dagDetails.bundleVersion (common,
matching the existing versionDetails.bundleVersion wording), and the
sort aria-label (components).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A18rBgPJ6X4oXAzsecJjnz
aaiss0927 added a commit to aaiss0927/airflow-1 that referenced this pull request Oct 28, 2026
Covers the three keys added to en after this branch was cut:
xcom.columns.timestamp (browse), dagDetails.bundleVersion (common,
matching the existing versionDetails.bundleVersion wording), and the
sort aria-label (components).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A18rBgPJ6X4oXAzsecJjnz
choo121600 pushed a commit that referenced this pull request Oct 29, 2026
* i18n(ko): add missing translations(Oct 27)

Add the five missing Korean translations to restore key parity with
the English locale. These keys were added to the English locale after
the open batch PR #75415 branched, so they are not covered there:

- dag.json: versions.pathOccurrences_one/_other,
  versions.pathOccurrencesAtLeast_one/_other (added by #75433)
- hitl.json: response.selectAtLeastOne (added by #75643)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* i18n(ko): add translations for keys introduced in #75326

Covers the three keys added to en after this branch was cut:
xcom.columns.timestamp (browse), dagDetails.bundleVersion (common,
matching the existing versionDetails.bundleVersion wording), and the
sort aria-label (components).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A18rBgPJ6X4oXAzsecJjnz

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:translations area:UI Related to UI/UX. For Frontend Developers. backport-to-v3-4-test Backport to v3-4-test translation:default

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants