This is an automated email from the ASF dual-hosted git repository.
bbovenzi pushed a commit to branch v3-3-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/v3-3-test by this push:
new addfc8511f8 [v3-3-test] UI: Fix preventRunningTasks showing as raw
i18n key in Clear Task dialogs (#71045) (#71240)
addfc8511f8 is described below
commit addfc8511f81273215f8c4e0c85636a581abe851
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Thu Aug 6 12:53:01 2026 -0400
[v3-3-test] UI: Fix preventRunningTasks showing as raw i18n key in Clear
Task dialogs (#71045) (#71240)
* UI: Add missing preventRunningTasks translation for Italian and Thai
The Italian and Thai locale files were missing the
runAndTaskActions.options.preventRunningTasks key that was added to
the English locale, so users on those locales saw the raw
translation key instead of localized text in the clear task dialogs.
* UI: Bust the translation cache when the version lookup fails
The i18n loadPath is cache-busted with the running Airflow version, but
on a failed VersionService.getVersion() call it silently fell back to
an un-versioned request. Behind a caching CDN or browser cache (e.g. a
managed deployment like Astronomer), that can serve a translation
bundle cached from before a key was added, so newer keys render as raw
i18n keys (see #71007) while older, already-cached keys translate
fine. Fall back to a timestamp instead so the cache is always busted.
* Apply suggestion from @bbovenzi
---------
(cherry picked from commit 3dd137020958d69fc1d6f386ab5e0765ddd15dab)
Co-authored-by: krystianpl26
<[email protected]>
Co-authored-by: krystianpl26 <[email protected]>
Co-authored-by: Brent Bovenzi <[email protected]>
Co-authored-by: Brent Bovenzi <[email protected]>
---
.../src/airflow/ui/public/i18n/locales/it/dags.json | 1 +
.../src/airflow/ui/public/i18n/locales/th/dags.json | 1 +
airflow-core/src/airflow/ui/src/i18n/config.test.ts | 20 ++++++++++++++++++--
airflow-core/src/airflow/ui/src/i18n/config.ts | 18 +++++++++++-------
4 files changed, 31 insertions(+), 9 deletions(-)
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/it/dags.json
b/airflow-core/src/airflow/ui/public/i18n/locales/it/dags.json
index 6c6ab552ddc..29258d25869 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/it/dags.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/it/dags.json
@@ -61,6 +61,7 @@
"future": "Futuro",
"onlyFailed": "Pulisci solo le task fallite",
"past": "Passato",
+ "preventRunningTasks": "Impedisci la riesecuzione se la task è in
esecuzione",
"queueNew": "Inserisci nuove task",
"runOnLatestVersion": "Esegui con l'ultima versione del bundle",
"upstream": "Upstream"
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/th/dags.json
b/airflow-core/src/airflow/ui/public/i18n/locales/th/dags.json
index 9b1ce043e8f..106ded489ec 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/th/dags.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/th/dags.json
@@ -61,6 +61,7 @@
"future": "งานในอนาคต",
"onlyFailed": "ล้างเฉพาะงานที่ล้มเหลว",
"past": "งานในอดีต",
+ "preventRunningTasks": "ป้องกันการรันซ้ำหากงานกำลังทำงาน",
"queueNew": "จัดคิวงานใหม่",
"runOnLatestVersion": "ทำงานด้วยเวอร์ชันล่าสุดของชุดรวม (Bundle)",
"upstream": "งานก่อนหน้า"
diff --git a/airflow-core/src/airflow/ui/src/i18n/config.test.ts
b/airflow-core/src/airflow/ui/src/i18n/config.test.ts
index 9a49276fd33..fabde912791 100644
--- a/airflow-core/src/airflow/ui/src/i18n/config.test.ts
+++ b/airflow-core/src/airflow/ui/src/i18n/config.test.ts
@@ -17,9 +17,11 @@
* under the License.
*/
import { createInstance } from "i18next";
-import { describe, expect, it } from "vitest";
+import { describe, expect, it, vi } from "vitest";
-import { convertDetectedLanguage, i18nBaseOptions } from "./config";
+import { VersionService } from "openapi/requests/services.gen";
+
+import { convertDetectedLanguage, i18nBaseOptions, resolveI18nVersion } from
"./config";
// getBestMatchFromCodes is the resolver i18next runs on the array the
// LanguageDetector returns. It is not part of i18next's public types
@@ -89,3 +91,17 @@ describe("i18n language resolution", () => {
expect(await resolveLanguage(["hi-IN", "en"])).toBe("hi");
});
});
+
+describe("resolveI18nVersion", () => {
+ it("resolves to the running version", async () => {
+ vi.spyOn(VersionService, "getVersion").mockResolvedValueOnce({
git_version: null, version: "3.2.2" });
+
+ await expect(resolveI18nVersion()).resolves.toBe("3.2.2");
+ });
+
+ it("falls back to a cache-busting value, not an empty string, when the
version lookup fails", async () => {
+ vi.spyOn(VersionService, "getVersion").mockRejectedValueOnce(new
Error("network error"));
+
+ await expect(resolveI18nVersion()).resolves.not.toBe("");
+ });
+});
diff --git a/airflow-core/src/airflow/ui/src/i18n/config.ts
b/airflow-core/src/airflow/ui/src/i18n/config.ts
index 20b2970d9af..8b4ce747c6e 100644
--- a/airflow-core/src/airflow/ui/src/i18n/config.ts
+++ b/airflow-core/src/airflow/ui/src/i18n/config.ts
@@ -144,12 +144,16 @@ const initI18n = (version: string) => {
});
};
-void VersionService.getVersion()
- .then((data) => {
- initI18n(data.version);
- })
- .catch(() => {
- initI18n("");
- });
+// Falling back to an empty version on failure would drop the `?v=` cache
+// buster from the translation loadPath, letting a CDN/browser keep serving a
+// translation bundle cached from before the running version, indefinitely
+// missing any keys added since. A timestamp isn't the true version, but it
+// still busts the cache on every retry.
+export const resolveI18nVersion = (): Promise<string> =>
+ VersionService.getVersion()
+ .then((data) => data.version)
+ .catch(() => Date.now().toString());
+
+void resolveI18nVersion().then(initI18n);
export { default } from "i18next";