This is an automated email from the ASF dual-hosted git repository.
bbovenzi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 1f7ed74c8e2 i18n translation files served stale after Airflow upgrade
due to browser cache (#65720)
1f7ed74c8e2 is described below
commit 1f7ed74c8e279390c8254c5ff2561a78b130f325
Author: Shashwati Bhattacharyaa <[email protected]>
AuthorDate: Tue May 5 19:31:24 2026 +0530
i18n translation files served stale after Airflow upgrade due to browser
cache (#65720)
* Bust browser cache for i18n files by appending Airflow version to load
path
* Rename newsfragment to match PR number
* Fix import order, regex style, and newsfragment encoding
* Address review: use runtime version API for i18n cache-busting instead of
build-time pyproject.toml
* Fix trailing newline in vite-env.d.ts
* Fix ESLint: use generic type param instead of cast, extract queryString
variable
* Refactor: use VersionService generated client for type-safe version fetch
---------
Co-authored-by: Shashwati <[email protected]>
---
airflow-core/src/airflow/ui/src/i18n/config.ts | 58 ++++++++++++++++----------
1 file changed, 36 insertions(+), 22 deletions(-)
diff --git a/airflow-core/src/airflow/ui/src/i18n/config.ts
b/airflow-core/src/airflow/ui/src/i18n/config.ts
index 3d5e5d03fbe..0cca099fcb5 100644
--- a/airflow-core/src/airflow/ui/src/i18n/config.ts
+++ b/airflow-core/src/airflow/ui/src/i18n/config.ts
@@ -21,6 +21,8 @@ import LanguageDetector from
"i18next-browser-languagedetector";
import Backend from "i18next-http-backend";
import { initReactI18next } from "react-i18next";
+import { VersionService } from "openapi/requests/services.gen";
+
export const supportedLanguages = [
{ code: "en", name: "English" },
{ code: "ar", name: "العربية" },
@@ -61,28 +63,40 @@ const baseHref = document.querySelector("head >
base")?.getAttribute("href") ??
const baseUrl = new URL(baseHref, globalThis.location.origin);
const basePath = new URL(baseUrl).pathname.replace(/\/$/u, "");
-void i18n
- .use(Backend)
- .use(LanguageDetector)
- .use(initReactI18next)
- .init({
- backend: {
- loadPath: `${basePath}/static/i18n/locales/{{lng}}/{{ns}}.json`,
- },
- defaultNS: "common",
- detection: {
- caches: ["localStorage"],
- order: ["localStorage", "navigator", "htmlTag"],
- },
- fallbackLng: defaultLanguage,
- interpolation: {
- escapeValue: false,
- },
- ns: namespaces,
- react: {
- useSuspense: false,
- },
- supportedLngs: supportedLanguages.map((lang) => lang.code),
+const initI18n = (version: string) => {
+ const queryString = version ? `?v=${version}` : "";
+
+ void i18n
+ .use(Backend)
+ .use(LanguageDetector)
+ .use(initReactI18next)
+ .init({
+ backend: {
+ loadPath:
`${basePath}/static/i18n/locales/{{lng}}/{{ns}}.json${queryString}`,
+ },
+ defaultNS: "common",
+ detection: {
+ caches: ["localStorage"],
+ order: ["localStorage", "navigator", "htmlTag"],
+ },
+ fallbackLng: defaultLanguage,
+ interpolation: {
+ escapeValue: false,
+ },
+ ns: namespaces,
+ react: {
+ useSuspense: false,
+ },
+ supportedLngs: supportedLanguages.map((lang) => lang.code),
+ });
+};
+
+void VersionService.getVersion()
+ .then((data) => {
+ initI18n(data.version);
+ })
+ .catch(() => {
+ initI18n("");
});
export { default } from "i18next";