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 474d062d7f5 i18n: Add translations for Assets, Browse, and Admin pages 
 (#51558)
474d062d7f5 is described below

commit 474d062d7f58a61df272f996cc732c18ca2173bc
Author: LI,JHE-CHEN <[email protected]>
AuthorDate: Thu Jun 12 04:43:26 2025 +0800

    i18n: Add translations for Assets, Browse, and Admin pages  (#51558)
    
    * i18n: translate variables page
    
    * i18n: translate pools page
    
    * i18n: translate Providers & Plugins page
    
    * i18n: translate Connections and Config page
    
    * i18n: translate Assets & Browse page
    
    * i18n: Address feedback on PR#51558
    
    * fix: Modify translations
    
    * fix: Modify translations based on PR feedback
---
 .../ui/src/components/FlexibleForm/index.tsx       |   1 -
 airflow-core/src/airflow/ui/src/i18n/config.ts     |  26 ++--
 .../src/airflow/ui/src/i18n/locales/de/admin.json  |   6 +
 .../ui/src/i18n/locales/de/connections.json        |   4 -
 .../src/airflow/ui/src/i18n/locales/en/admin.json  | 141 +++++++++++++++++++++
 .../src/airflow/ui/src/i18n/locales/en/assets.json |  10 ++
 .../src/airflow/ui/src/i18n/locales/en/browse.json |  22 ++++
 .../src/airflow/ui/src/i18n/locales/en/common.json |   4 +
 .../ui/src/i18n/locales/en/connections.json        |   4 -
 .../src/airflow/ui/src/i18n/locales/pl/admin.json  |   6 +
 .../ui/src/i18n/locales/pl/connections.json        |   4 -
 .../airflow/ui/src/i18n/locales/zh-TW/admin.json   | 141 +++++++++++++++++++++
 .../airflow/ui/src/i18n/locales/zh-TW/assets.json  |  10 ++
 .../airflow/ui/src/i18n/locales/zh-TW/browse.json  |  22 ++++
 .../airflow/ui/src/i18n/locales/zh-TW/common.json  |  49 ++++++-
 .../ui/src/i18n/locales/zh-TW/connections.json     |   4 -
 .../airflow/ui/src/pages/AssetsList/AssetsList.tsx |  23 ++--
 .../ui/src/pages/AssetsList/DependencyPopover.tsx  |  69 +++++-----
 .../src/airflow/ui/src/pages/Configs/Configs.tsx   |  18 ++-
 .../src/pages/Connections/AddConnectionButton.tsx  |   8 +-
 .../ui/src/pages/Connections/ConnectionForm.tsx    |  32 ++---
 .../ui/src/pages/Connections/Connections.tsx       |  27 ++--
 .../pages/Connections/DeleteConnectionButton.tsx   |  22 ++--
 .../pages/Connections/DeleteConnectionsButton.tsx  |  19 +--
 .../src/pages/Connections/EditConnectionButton.tsx |   8 +-
 .../src/pages/Connections/TestConnectionButton.tsx |   8 +-
 .../pages/Dashboard/Stats/PluginImportErrors.tsx   |   8 +-
 .../Dashboard/Stats/PluginImportErrorsModal.tsx    |   6 +-
 .../src/airflow/ui/src/pages/Events/Events.tsx     |  39 +++---
 airflow-core/src/airflow/ui/src/pages/Plugins.tsx  |  16 ++-
 .../airflow/ui/src/pages/Pools/AddPoolButton.tsx   |   6 +-
 .../ui/src/pages/Pools/DeletePoolButton.tsx        |  10 +-
 .../airflow/ui/src/pages/Pools/EditPoolButton.tsx  |   8 +-
 .../src/airflow/ui/src/pages/Pools/PoolBarCard.tsx |  69 +++++-----
 .../src/airflow/ui/src/pages/Pools/PoolForm.tsx    |  20 +--
 .../src/airflow/ui/src/pages/Pools/Pools.tsx       |  23 ++--
 .../src/airflow/ui/src/pages/Providers.tsx         |  18 ++-
 .../src/pages/Variables/DeleteVariablesButton.tsx  |  22 ++--
 .../src/pages/Variables/ImportVariablesButton.tsx  |   6 +-
 .../ui/src/pages/Variables/ImportVariablesForm.tsx |  30 +++--
 .../Variables/ManageVariable/AddVariableButton.tsx |   6 +-
 .../ManageVariable/DeleteVariableButton.tsx        |  22 ++--
 .../ManageVariable/EditVariableButton.tsx          |   8 +-
 .../Variables/ManageVariable/VariableForm.tsx      |  20 +--
 .../airflow/ui/src/pages/Variables/Variables.tsx   |  28 ++--
 .../src/airflow/ui/src/pages/XCom/XCom.tsx         |  19 +--
 46 files changed, 780 insertions(+), 292 deletions(-)

diff --git a/airflow-core/src/airflow/ui/src/components/FlexibleForm/index.tsx 
b/airflow-core/src/airflow/ui/src/components/FlexibleForm/index.tsx
index 704b5d956ae..93460cadb18 100644
--- a/airflow-core/src/airflow/ui/src/components/FlexibleForm/index.tsx
+++ b/airflow-core/src/airflow/ui/src/components/FlexibleForm/index.tsx
@@ -23,6 +23,5 @@ export type FlexibleFormElementProps = {
 };
 
 export const flexibleFormDefaultSection = "Run Parameters";
-export const flexibleFormExtraFieldSection = "Extra Fields";
 
 export { FlexibleForm } from "./FlexibleForm";
diff --git a/airflow-core/src/airflow/ui/src/i18n/config.ts 
b/airflow-core/src/airflow/ui/src/i18n/config.ts
index 11100bb7998..a8c93554d8a 100644
--- a/airflow-core/src/airflow/ui/src/i18n/config.ts
+++ b/airflow-core/src/airflow/ui/src/i18n/config.ts
@@ -20,15 +20,17 @@ import i18n from "i18next";
 import LanguageDetector from "i18next-browser-languagedetector";
 import { initReactI18next } from "react-i18next";
 
+import deAdmin from "./locales/de/admin.json";
 import deCommon from "./locales/de/common.json";
 import deComponents from "./locales/de/components.json";
-import deConnections from "./locales/de/connections.json";
 import deDag from "./locales/de/dag.json";
 import deDags from "./locales/de/dags.json";
 import deDashboard from "./locales/de/dashboard.json";
+import enAdmin from "./locales/en/admin.json";
+import enAssets from "./locales/en/assets.json";
+import enBrowse from "./locales/en/browse.json";
 import enCommon from "./locales/en/common.json";
 import enComponents from "./locales/en/components.json";
-import enConnections from "./locales/en/connections.json";
 import enDag from "./locales/en/dag.json";
 import enDags from "./locales/en/dags.json";
 import enDashboard from "./locales/en/dashboard.json";
@@ -38,14 +40,16 @@ import koCommon from "./locales/ko/common.json";
 import koDashboard from "./locales/ko/dashboard.json";
 import nlCommon from "./locales/nl/common.json";
 import nlDashboard from "./locales/nl/dashboard.json";
+import plAdmin from "./locales/pl/admin.json";
 import plCommon from "./locales/pl/common.json";
 import plComponents from "./locales/pl/components.json";
-import plConnections from "./locales/pl/connections.json";
 import plDag from "./locales/pl/dag.json";
 import plDags from "./locales/pl/dags.json";
 import plDashboard from "./locales/pl/dashboard.json";
+import zhTWAdmin from "./locales/zh-TW/admin.json";
+import zhTWAssets from "./locales/zh-TW/assets.json";
+import zhTWBrowse from "./locales/zh-TW/browse.json";
 import zhTWCommon from "./locales/zh-TW/common.json";
-import zhTWConnections from "./locales/zh-TW/connections.json";
 import zhTWDags from "./locales/zh-TW/dags.json";
 import zhTWDashboard from "./locales/zh-TW/dashboard.json";
 
@@ -63,21 +67,23 @@ export const supportedLanguages = [
 ] as const;
 
 export const defaultLanguage = "en";
-export const namespaces = ["common", "dashboard", "dags", "connections"] as 
const;
+export const namespaces = ["common", "dashboard", "dags", "admin", "browse", 
"assets"] as const;
 
 const resources = {
   de: {
+    admin: deAdmin,
     common: deCommon,
     components: deComponents,
-    connections: deConnections,
     dag: deDag,
     dags: deDags,
     dashboard: deDashboard,
   },
   en: {
+    admin: enAdmin,
+    assets: enAssets,
+    browse: enBrowse,
     common: enCommon,
     components: enComponents,
-    connections: enConnections,
     dag: enDag,
     dags: enDags,
     dashboard: enDashboard,
@@ -95,16 +101,18 @@ const resources = {
     dashboard: nlDashboard,
   },
   pl: {
+    admin: plAdmin,
     common: plCommon,
     components: plComponents,
-    connections: plConnections,
     dag: plDag,
     dags: plDags,
     dashboard: plDashboard,
   },
   "zh-TW": {
+    admin: zhTWAdmin,
+    assets: zhTWAssets,
+    browse: zhTWBrowse,
     common: zhTWCommon,
-    connections: zhTWConnections,
     dags: zhTWDags,
     dashboard: zhTWDashboard,
   },
diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/de/admin.json 
b/airflow-core/src/airflow/ui/src/i18n/locales/de/admin.json
new file mode 100644
index 00000000000..ad8d52ac527
--- /dev/null
+++ b/airflow-core/src/airflow/ui/src/i18n/locales/de/admin.json
@@ -0,0 +1,6 @@
+{
+  "connections":{
+    "test": "Verbindung testen",
+    "testDisabled": "Das Testen von Verbindungen ist deaktiviert. Der 
Administrator kann via Konfiguration das Testen freischalten."
+  }
+}
diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/de/connections.json 
b/airflow-core/src/airflow/ui/src/i18n/locales/de/connections.json
deleted file mode 100644
index e9896e4f47d..00000000000
--- a/airflow-core/src/airflow/ui/src/i18n/locales/de/connections.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "test": "Verbindung testen",
-  "testDisabled": "Das Testen von Verbindungen ist deaktiviert. Der 
Administrator kann via Konfiguration das Testen freischalten."
-}
diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/en/admin.json 
b/airflow-core/src/airflow/ui/src/i18n/locales/en/admin.json
new file mode 100644
index 00000000000..a0de0cc1490
--- /dev/null
+++ b/airflow-core/src/airflow/ui/src/i18n/locales/en/admin.json
@@ -0,0 +1,141 @@
+{
+  "columns":{
+    "description": "Description",
+    "key": "Key",
+    "name": "Name",
+    "value": "Value"
+  },
+  "config":{
+    "columns":{
+      "section": "Section"
+    },
+    "title": "Airflow Configuration"
+  },
+  "connections":{
+    "add":"Add Connection",
+    "columns":{
+      "connectionId": "Connection ID",
+      "connectionType": "Connection Type",
+      "host": "Host",
+      "port": "Port"
+    },
+    "delete":{
+      "deleteConnection_one": "Delete 1 connection",
+      "deleteConnection_other": "Delete {{count}} connections",
+      "firstConfirmMessage_one": "You are about to delete the following 
connection:",
+      "firstConfirmMessage_other": "You are about to delete the following 
connections:",
+      "title": "Delete Connection"
+    },
+    "edit": "Edit Connection",
+    "form":{
+      "connectionIdRequired": "Connection ID is required",
+      "connectionIdRequirement": "Connection ID cannot contain only spaces",
+      "connectionTypeRequired": "Connection Type is required",
+      "extraFields": "Extra Fields",
+      "extraFieldsJson": "Extra Fields JSON",
+      "helperText": "Connection type missing? Make sure you have installed the 
corresponding Airflow Providers Package.",
+      "selectConnectionType": "Select Connection Type",
+      "standardFields": "Standard Fields"
+    },
+    "noRowMessage": "No connections found",
+    "searchPlaceholder": "Search Connections",
+    "test": "Test Connection",
+    "testDisabled": "Test connection feature is disabled. Please contact an 
administrator to enable it."
+  },
+  "deleteActions":{
+    "button": "Delete",
+    "modal":{
+      "confirmButton": "Yes, Delete",
+      "secondConfirmMessage": "This action is permanent and cannot be undone.",
+      "thirdConfirmMessage": " Are you sure you want to proceed?"
+    },
+    "selected": "Selected"
+  },
+  "formActions":{
+    "reset": "Reset",
+    "save": "Save"
+  },
+  "plugins": {
+    "columns": {
+      "source": "Source"
+    },
+    "importError_one": "Plugin Import Error",
+    "importError_other": "Plugin Import Errors",
+    "searchPlaceholder": "Search by file"
+  },
+  "pools": {
+    "add": "Add Pool",
+    "deferredSlotsIncluded": "Deferred Slots Included",
+    "delete":{
+      "title": "Delete Pool",
+      "warning": "This will remove all metadata related to the pool and may 
affect tasks using this pool."
+    },
+    "edit": "Edit Pool",
+    "form": {
+      "checkbox": "Check to include deferred tasks when calculating open pool 
slots",
+      "description": "Description",
+      "includeDeferred": "Include Deferred",
+      "nameMaxLength": "Name can contain a maximum of 256 characters",
+      "nameRequired": "Name is required",
+      "slots": "Slots"
+    },
+    "noPoolsFound": "No pools found",
+    "searchPlaceholder": "Search Pools",
+    "sort": {
+      "asc": "Name (A-Z)",
+      "desc": "Name (Z-A)",
+      "placeholder": "Sort by"
+    }
+  },
+  "providers": {
+    "columns": {
+      "packageName": "Package Name",
+      "version": "Version"
+    }
+  },
+  "variables": {
+    "add": "Add Variable",
+    "columns": {
+      "isEncrypted": "Is Encrypted"
+    },
+    "delete": {
+      "deleteVariable_one": "Delete 1 Variable",
+      "deleteVariable_other": "Delete {{count}} Variables",
+      "firstConfirmMessage_one": "You are about to delete the following 
variable:",
+      "firstConfirmMessage_other": "You are about to delete the following 
variables:",
+      "title": "Delete Variable"
+    },
+    "edit":  "Edit Variable",
+    "export": "Export",
+    "form": {
+      "invalidJson": "Invalid JSON",
+      "keyMaxLength": "Key can contain a maximum of 250 characters",
+      "keyRequired": "Key is required",
+      "valueRequired": "Value is required"
+    },
+    "import": {
+      "button": "Import",
+      "conflictResolution": "Select Variable Conflict Resolution",
+      "errorParsingJsonFile": "Error Parsing JSON File: Upload a JSON file 
containing variables (e.g., {\"key\": \"value\", ...}).",
+      "options": {
+        "fail": {
+          "description": "Fails the import if any existing variables are 
detected.",
+          "title": "Fail"
+        },
+        "overwrite": {
+          "description": "Overwrites the variable in case of a conflict.",
+          "title": "Overwrite"
+        },
+        "skip": {
+          "description": "Skips importing variables that already exist.",
+          "title": "Skip"
+        }
+      },
+      "title": "Import Variables",
+      "upload": "Upload a JSON File",
+      "uploadPlaceholder": "Upload a JSON file containing variables (e.g., 
{\"key\": \"value\", ...})"
+    },
+    "noRowsMessage": "No variables found",
+    "searchPlaceholder": "Search Keys"
+  }
+}
diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/en/assets.json 
b/airflow-core/src/airflow/ui/src/i18n/locales/en/assets.json
new file mode 100644
index 00000000000..b927d6891ea
--- /dev/null
+++ b/airflow-core/src/airflow/ui/src/i18n/locales/en/assets.json
@@ -0,0 +1,10 @@
+{
+  "columns": {
+    "consumingDags": "Consuming Dags",
+    "group": "Group",
+    "lastAssetEvent": "Last Asset Event",
+    "name": "Name",
+    "producingTasks": "Producing Tasks"
+  },
+  "searchPlaceholder": "Search Assets"
+}
diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/en/browse.json 
b/airflow-core/src/airflow/ui/src/i18n/locales/en/browse.json
new file mode 100644
index 00000000000..56d89a8dc5c
--- /dev/null
+++ b/airflow-core/src/airflow/ui/src/i18n/locales/en/browse.json
@@ -0,0 +1,22 @@
+{
+  "auditLog":{
+    "actions": {
+      "collapseAllExtra": "Collapse all extra json",
+      "expandAllExtra": "Expand all extra json"
+    },
+    "columns":{
+      "event": "Event",
+      "extra": "Extra",
+      "user": "User",
+      "when": "When"
+    },
+    "title": "Audit Log Events"
+  },
+  "xcom":{
+    "columns":{
+      "dag": "Dag",
+      "key": "Key",
+      "value": "Value"
+    }
+  }
+}
diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/en/common.json 
b/airflow-core/src/airflow/ui/src/i18n/locales/en/common.json
index de6d102b326..31ca56d587e 100644
--- a/airflow-core/src/airflow/ui/src/i18n/locales/en/common.json
+++ b/airflow-core/src/airflow/ui/src/i18n/locales/en/common.json
@@ -7,6 +7,8 @@
     "Providers": "Providers",
     "Variables": "Variables"
   },
+  "asset_one": "Asset",
+  "asset_other": "Assets",
   "assetEvent_one": "Asset Event",
   "assetEvent_other": "Asset Events",
   "backfill_one": "Backfill",
@@ -17,6 +19,7 @@
   },
   "dag_one": "Dag",
   "dag_other": "Dags",
+  "dagId": "Dag ID",
   "dagRun_one": "Dag Run",
   "dagRun_other": "Dag Runs",
   "dagWarnings": "Dag warnings/errors",
@@ -128,6 +131,7 @@
   },
   "task_one": "Task",
   "task_other": "Tasks",
+  "taskId": "Task ID",
   "taskInstance_one": "Task Instance",
   "taskInstance_other": "Task Instances",
   "timeRange": {
diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/en/connections.json 
b/airflow-core/src/airflow/ui/src/i18n/locales/en/connections.json
deleted file mode 100644
index c50cd75a2c7..00000000000
--- a/airflow-core/src/airflow/ui/src/i18n/locales/en/connections.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-    "test": "Test Connection",
-    "testDisabled": "Testing connections disabled. Contact your admin to 
enable it."
-}
diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/pl/admin.json 
b/airflow-core/src/airflow/ui/src/i18n/locales/pl/admin.json
new file mode 100644
index 00000000000..bbc6a9d53e5
--- /dev/null
+++ b/airflow-core/src/airflow/ui/src/i18n/locales/pl/admin.json
@@ -0,0 +1,6 @@
+{
+  "connections":{
+    "test": "Test połączenia",
+    "testDisabled": "Testowanie połączeń wyłączone. Skontaktuj się z 
administratorem, aby je włączyć."
+  }
+}
diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/pl/connections.json 
b/airflow-core/src/airflow/ui/src/i18n/locales/pl/connections.json
deleted file mode 100644
index a2f993ddb45..00000000000
--- a/airflow-core/src/airflow/ui/src/i18n/locales/pl/connections.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "test": "Test połączenia",
-  "testDisabled": "Testowanie połączeń wyłączone. Skontaktuj się z 
administratorem, aby je włączyć."
-}
diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/admin.json 
b/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/admin.json
new file mode 100644
index 00000000000..53010df9c88
--- /dev/null
+++ b/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/admin.json
@@ -0,0 +1,141 @@
+{
+  "columns":{
+    "description": "描述",
+    "key": "鍵",
+    "name": "名稱",
+    "value": "值"
+  },
+  "config":{
+    "columns":{
+      "section": "區段"
+    },
+    "title": "Airflow 設定"
+  },
+  "connections":{
+    "add":"新增連線",
+    "columns":{
+      "connectionId": "連線 ID",
+      "connectionType": "連線類型",
+      "host": "主機",
+      "port": "埠"
+    },
+    "delete":{
+      "deleteConnection_one": "刪除 1 個連線",
+      "deleteConnection_other": "刪除 {{count}} 個連線",
+      "firstConfirmMessage_one": "您即將刪除以下連線:",
+      "firstConfirmMessage_other": "您即將刪除以下連線:",
+      "title": "刪除連線"
+    },
+    "edit": "編輯連線",
+    "form":{
+      "connectionIdRequired": "連線 ID 是必填的",
+      "connectionIdRequirement": "連線 ID 不能只包含空格",
+      "connectionTypeRequired": "連線類型是必填的",
+      "extraFields": "額外欄位",
+      "extraFieldsJson": "額外欄位 JSON",
+      "helperText": "找不到連線類型?請確保您已安裝對應的 Airflow Providers 套件。",
+      "selectConnectionType": "選擇連線類型",
+      "standardFields": "標準欄位"
+    },
+    "noRowMessage": "找不到連線",
+    "searchPlaceholder": "搜尋連線",
+    "test": "測試連線",
+    "testDisabled": "測試連線功能已停用。請聯繫管理員以啟用。"
+  },
+  "deleteActions":{
+    "button": "刪除",
+    "modal":{
+      "confirmButton": "確定刪除",
+      "secondConfirmMessage": "此動作無法復原。",
+      "thirdConfirmMessage": "您確定要繼續嗎?"
+    },
+    "selected": "已選取"
+  },
+  "formActions":{
+    "reset": "重置",
+    "save": "儲存"
+  },
+  "plugins": {
+    "columns": {
+      "source": "來源"
+    },
+    "importError_one": "外掛匯入錯誤",
+    "importError_other": "外掛匯入錯誤",
+    "searchPlaceholder": "搜尋檔案"
+  },
+  "pools": {
+    "add": "新增資源池",
+    "deferredSlotsIncluded": "包含延後任務",
+    "delete":{
+      "title": "刪除資源池",
+      "warning": "這將刪除所有與此資源池相關的系統資料,可能會影響使用此資源池的任務。"
+    },
+    "edit": "編輯資源池",
+    "form": {
+      "checkbox": "計算可用資源池配額時,將包含延後的任務",
+      "description": "描述",
+      "includeDeferred": "包含延後任務",
+      "nameMaxLength": "名稱最多只能包含 256 個字元",
+      "nameRequired": "名稱是必填的",
+      "slots": "配額"
+    },
+    "noPoolsFound": "找不到資源池",
+    "searchPlaceholder": "搜尋資源池",
+    "sort": {
+      "asc": "名稱 (A-Z)",
+      "desc": "名稱 (Z-A)",
+      "placeholder": "排序方式"
+    }
+  },
+  "providers": {
+    "columns": {
+      "packageName": "套件名稱",
+      "version": "版本"
+    }
+  },
+  "variables": {
+    "add": "新增變數",
+    "columns": {
+      "isEncrypted": "是否加密"
+    },
+    "delete": {
+      "deleteVariable_one": "刪除 1 個變數",
+      "deleteVariable_other": "刪除 {{count}} 個變數",
+      "firstConfirmMessage_one": "您即將刪除以下變數:",
+      "firstConfirmMessage_other": "您即將刪除以下變數:",
+      "title": "刪除變數"
+    },
+    "edit": "編輯變數",
+    "export": "匯出",
+    "form": {
+      "invalidJson": "無效的 JSON",
+      "keyMaxLength": "鍵最多只能包含 250 個字元",
+      "keyRequired": "鍵是必填的",
+      "valueRequired": "值是必填的"
+    },
+    "import": {
+      "button": "匯入",
+      "conflictResolution": "選擇變數衝突解決方式",
+      "errorParsingJsonFile": "解析 JSON 檔案時發生錯誤:請上傳包含變數的 JSON 檔案 (例如:{\"key\": 
\"value\", ...})。",
+      "options": {
+        "fail": {
+          "description": "如果偵測到任何已存在的變數,則匯入失敗。",
+          "title": "失敗"
+        },
+        "overwrite": {
+          "description": "發生衝突時覆蓋變數。",
+          "title": "覆蓋"
+        },
+        "skip": {
+          "description": "略過匯入已存在的變數。",
+          "title": "跳過"
+        }
+      },
+      "title": "匯入變數",
+      "upload": "上傳 JSON 檔案",
+      "uploadPlaceholder": "上傳包含變數的 JSON 檔案 (例如:{\"key\": \"value\", ...})"
+    },
+    "noRowsMessage": "找不到變數",
+    "searchPlaceholder": "搜尋鍵"
+  }
+}
diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/assets.json 
b/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/assets.json
new file mode 100644
index 00000000000..04e46d86abf
--- /dev/null
+++ b/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/assets.json
@@ -0,0 +1,10 @@
+{
+  "columns": {
+    "consumingDags": "消費者 Dags",
+    "group": "群組",
+    "lastAssetEvent": "最後資源事件",
+    "name": "名稱",
+    "producingTasks": "生產任務"
+  },
+  "searchPlaceholder": "搜尋資源"
+}
diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/browse.json 
b/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/browse.json
new file mode 100644
index 00000000000..8787b39e735
--- /dev/null
+++ b/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/browse.json
@@ -0,0 +1,22 @@
+{
+  "auditLog":{
+    "actions": {
+      "collapseAllExtra": "收合所有額外 JSON",
+      "expandAllExtra": "展開所有額外 JSON"
+    },
+    "columns":{
+      "event": "事件",
+      "extra": "額外資訊",
+      "user": "使用者",
+      "when": "時間"
+    },
+    "title": "審計日誌事件"
+  },
+  "xcom":{
+    "columns":{
+      "dag": "Dag",
+      "key": "鍵",
+      "value": "值"
+    }
+  }
+}
diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/common.json 
b/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/common.json
index af2be17a809..18c11dfbc02 100644
--- a/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/common.json
+++ b/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/common.json
@@ -1,22 +1,28 @@
 {
   "admin": {
     "Config": "設定",
-    "Connections": "連結",
+    "Connections": "連線",
     "Plugins": "外掛",
     "Pools": "資源池",
     "Providers": "Providers",
     "Variables": "變數"
   },
+  "asset_one": "資源",
+  "asset_other": "資源",
   "assetEvent_one": "資源事件",
   "assetEvent_other": "資源事件",
+  "backfill_one": "回填",
+  "backfill_other": "回填",
   "browse": {
     "auditLog": "審計日誌",
     "xcoms": "XComs"
   },
   "dag_one": "Dag",
   "dag_other": "Dags",
+  "dagId": "Dag ID",
   "dagRun_one": "Dag 執行",
   "dagRun_other": "Dag 執行",
+  "dagWarnings": "Dag 警告 / 錯誤",
   "defaultToGraphView": "預設使用圖形視圖",
   "defaultToGridView": "預設使用網格視圖",
   "direction": "書寫方向",
@@ -25,6 +31,18 @@
     "githubRepo": "GitHub 倉庫",
     "restApiReference": "REST API 參考"
   },
+  "duration": {
+    "label": "持續時間",
+    "seconds": "{{count}} 秒"
+  },
+  "endDate": "結束日期",
+  "expression": {
+    "all": "全部",
+    "and": "且",
+    "any": "任何",
+    "or": "或"
+  },
+  "logicalDate": "邏輯日期",
   "logout": "登出",
   "logoutConfirmation": "確定要登出嗎?",
   "mapIndex": "映射索引",
@@ -46,16 +64,18 @@
     "plugins": "插件",
     "security": "安全"
   },
-  "noItemsFound": "找不到{{modelName}}",
+  "noItemsFound": "找不到 {{modelName}}",
+  "operator": "運算子",
   "pools": {
     "deferred": "已延後",
-    "open": "開啟",
+    "open": "開放",
     "pools_one": "資源池",
     "pools_other": "資源池",
     "queued": "排隊中",
     "running": "執行中",
     "scheduled": "已排程"
   },
+  "runId": "執行 ID",
   "runTypes": {
     "asset_triggered": "資源觸發",
     "backfill": "回填",
@@ -70,6 +90,8 @@
     "users": "使用者"
   },
   "selectLanguage": "選擇語言",
+  "startDate": "開始日期",
+  "state": "狀態",
   "states": {
     "deferred": "已延後",
     "failed": "失敗",
@@ -89,17 +111,27 @@
   "switchToDarkMode": "切換到深色模式",
   "switchToLightMode": "切換到淺色模式",
   "table": {
+    "completedAt": "完成時間",
+    "createdAt": "建立時間",
+    "duration": "持續時間",
     "filterByTag": "依標籤篩選 Dags",
     "filterColumns": "篩選表格欄位",
     "filterReset_one": "重置篩選",
     "filterReset_other": "重置篩選",
+    "from": "從",
+    "maxActiveRuns": "最大活躍執行數",
     "noTagsFound": "找不到標籤",
+    "reprocessBehavior": "重新處理行為",
     "tagMode": {
       "all": "全部",
       "any": "任何"
     },
-    "tagPlaceholder": "依標籤篩選"
+    "tagPlaceholder": "依標籤篩選",
+    "to": "到"
   },
+  "task_one": "任務",
+  "task_other": "任務",
+  "taskId": "任務 ID",
   "taskInstance_one": "任務實例",
   "taskInstance_other": "任務實例",
   "timeRange": {
@@ -117,5 +149,12 @@
     "utc": "UTC"
   },
   "triggered": "已觸發",
-  "user": "使用者"
+  "triggerRule": "觸發規則",
+  "tryNumber": "嘗試次數",
+  "user": "使用者",
+  "wrap": {
+    "tooltip": "按 w 切換換行",
+    "unwrap": "不換行",
+    "wrap": "換行"
+  }
 }
diff --git 
a/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/connections.json 
b/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/connections.json
deleted file mode 100644
index a8a6257cb43..00000000000
--- a/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/connections.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "test": "測試連線",
-  "testDisabled": "測試連線功能已停用。請聯繫管理員以啟用。"
-}
diff --git a/airflow-core/src/airflow/ui/src/pages/AssetsList/AssetsList.tsx 
b/airflow-core/src/airflow/ui/src/pages/AssetsList/AssetsList.tsx
index 8014b61d623..d05404f7ff5 100644
--- a/airflow-core/src/airflow/ui/src/pages/AssetsList/AssetsList.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/AssetsList/AssetsList.tsx
@@ -19,6 +19,7 @@
 import { Box, Heading, Link, VStack } from "@chakra-ui/react";
 import type { ColumnDef } from "@tanstack/react-table";
 import { useState } from "react";
+import { useTranslation } from "react-i18next";
 import { useSearchParams, Link as RouterLink } from "react-router-dom";
 
 import { useAssetServiceGetAssets } from "openapi/queries";
@@ -30,13 +31,12 @@ import { SearchBar } from "src/components/SearchBar";
 import Time from "src/components/Time";
 import { SearchParamsKeys } from "src/constants/searchParams";
 import { CreateAssetEvent } from "src/pages/Asset/CreateAssetEvent";
-import { pluralize } from "src/utils";
 
 import { DependencyPopover } from "./DependencyPopover";
 
 type AssetRow = { row: { original: AssetResponse } };
 
-const columns: Array<ColumnDef<AssetResponse>> = [
+const createColumns = (translate: (key: string) => string): 
Array<ColumnDef<AssetResponse>> => [
   {
     accessorKey: "name",
     cell: ({ row: { original } }: AssetRow) => (
@@ -44,7 +44,7 @@ const columns: Array<ColumnDef<AssetResponse>> = [
         <RouterLink to={`/assets/${original.id}`}>{original.name}</RouterLink>
       </Link>
     ),
-    header: () => "Name",
+    header: () => translate("columns.name"),
   },
   {
     accessorKey: "last_asset_event",
@@ -59,12 +59,12 @@ const columns: Array<ColumnDef<AssetResponse>> = [
       return <Time datetime={timestamp} />;
     },
     enableSorting: false,
-    header: () => "Last Asset Event",
+    header: () => translate("columns.lastAssetEvent"),
   },
   {
     accessorKey: "group",
     enableSorting: false,
-    header: () => "Group",
+    header: () => translate("columns.group"),
   },
   {
     accessorKey: "consuming_dags",
@@ -73,7 +73,7 @@ const columns: Array<ColumnDef<AssetResponse>> = [
         <DependencyPopover dependencies={original.consuming_dags} type="Dag" />
       ) : undefined,
     enableSorting: false,
-    header: () => "Consuming Dags",
+    header: () => translate("columns.consumingDags"),
   },
   {
     accessorKey: "producing_tasks",
@@ -82,7 +82,7 @@ const columns: Array<ColumnDef<AssetResponse>> = [
         <DependencyPopover dependencies={original.producing_tasks} type="Task" 
/>
       ) : undefined,
     enableSorting: false,
-    header: () => "Producing Tasks",
+    header: () => translate("columns.producingTasks"),
   },
   {
     accessorKey: "trigger",
@@ -95,6 +95,7 @@ const columns: Array<ColumnDef<AssetResponse>> = [
 const NAME_PATTERN_PARAM = SearchParamsKeys.NAME_PATTERN;
 
 export const AssetsList = () => {
+  const { t: translate } = useTranslation(["assets", "common"]);
   const [searchParams, setSearchParams] = useSearchParams();
 
   const [namePattern, setNamePattern] = 
useState(searchParams.get(NAME_PATTERN_PARAM) ?? undefined);
@@ -132,21 +133,21 @@ export const AssetsList = () => {
           buttonProps={{ disabled: true }}
           defaultValue={namePattern ?? ""}
           onChange={handleSearchChange}
-          placeHolder="Search Assets"
+          placeHolder={translate("searchPlaceholder")}
         />
 
         <Heading py={3} size="md">
-          {pluralize("Asset", data?.total_entries)}
+          {data?.total_entries} {translate("common:asset", { count: 
data?.total_entries })}
         </Heading>
       </VStack>
       <Box overflow="auto">
         <DataTable
-          columns={columns}
+          columns={createColumns(translate)}
           data={data?.assets ?? []}
           errorMessage={<ErrorAlert error={error} />}
           initialState={tableURLState}
           isLoading={isLoading}
-          modelName="Asset"
+          modelName={translate("common:asset_one")}
           onStateChange={setTableURLState}
           total={data?.total_entries}
         />
diff --git 
a/airflow-core/src/airflow/ui/src/pages/AssetsList/DependencyPopover.tsx 
b/airflow-core/src/airflow/ui/src/pages/AssetsList/DependencyPopover.tsx
index 0e3d17707ab..99575c8f32a 100644
--- a/airflow-core/src/airflow/ui/src/pages/AssetsList/DependencyPopover.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/AssetsList/DependencyPopover.tsx
@@ -17,48 +17,53 @@
  * under the License.
  */
 import { Link } from "@chakra-ui/react";
+import { useTranslation } from "react-i18next";
 import { Link as RouterLink } from "react-router-dom";
 
 import type { DagScheduleAssetReference, TaskOutletAssetReference } from 
"openapi/requests/types.gen";
 import { Button, Popover } from "src/components/ui";
-import { pluralize } from "src/utils";
 
 type Props = {
   readonly dependencies: Array<DagScheduleAssetReference | 
TaskOutletAssetReference>;
   readonly type: "Dag" | "Task";
 };
 
-export const DependencyPopover = ({ dependencies, type }: Props) => (
-  // eslint-disable-next-line jsx-a11y/no-autofocus
-  <Popover.Root autoFocus={false} lazyMount unmountOnExit>
-    <Popover.Trigger asChild>
-      <Button size="sm" variant="outline">
-        {pluralize(type, dependencies.length)}
-      </Button>
-    </Popover.Trigger>
-    <Popover.Content css={{ "--popover-bg": "colors.bg.emphasized" }} 
width="fit-content">
-      <Popover.Arrow />
-      <Popover.Body>
-        {dependencies.map((dependency) => {
-          let key = dependency.dag_id;
-          let link = `/dags/${dependency.dag_id}`;
-          let label = dependency.dag_id;
+export const DependencyPopover = ({ dependencies, type }: Props) => {
+  const { t: translate } = useTranslation("common");
+  const dependencyKey = type.toLowerCase() as "dag" | "task";
 
-          if (type === "Task") {
-            const dep = dependency as TaskOutletAssetReference;
+  return (
+    // eslint-disable-next-line jsx-a11y/no-autofocus
+    <Popover.Root autoFocus={false} lazyMount unmountOnExit>
+      <Popover.Trigger asChild>
+        <Button size="sm" variant="outline">
+          {dependencies.length} {translate(dependencyKey, { count: 
dependencies.length })}
+        </Button>
+      </Popover.Trigger>
+      <Popover.Content css={{ "--popover-bg": "colors.bg.emphasized" }} 
width="fit-content">
+        <Popover.Arrow />
+        <Popover.Body>
+          {dependencies.map((dependency) => {
+            let key = dependency.dag_id;
+            let link = `/dags/${dependency.dag_id}`;
+            let label = dependency.dag_id;
 
-            key = `${dep.dag_id}-${dep.task_id}`;
-            link = `/dags/${dep.dag_id}/tasks/${dep.task_id}`;
-            label = `${dep.dag_id}.${dep.task_id}`;
-          }
+            if (type === "Task") {
+              const dep = dependency as TaskOutletAssetReference;
 
-          return (
-            <Link asChild color="fg.info" display="block" key={key} py={2}>
-              <RouterLink to={link}>{label}</RouterLink>
-            </Link>
-          );
-        })}
-      </Popover.Body>
-    </Popover.Content>
-  </Popover.Root>
-);
+              key = `${dep.dag_id}-${dep.task_id}`;
+              link = `/dags/${dep.dag_id}/tasks/${dep.task_id}`;
+              label = `${dep.dag_id}.${dep.task_id}`;
+            }
+
+            return (
+              <Link asChild color="fg.info" display="block" key={key} py={2}>
+                <RouterLink to={link}>{label}</RouterLink>
+              </Link>
+            );
+          })}
+        </Popover.Body>
+      </Popover.Content>
+    </Popover.Root>
+  );
+};
diff --git a/airflow-core/src/airflow/ui/src/pages/Configs/Configs.tsx 
b/airflow-core/src/airflow/ui/src/pages/Configs/Configs.tsx
index 8d542e71c14..f194da70113 100644
--- a/airflow-core/src/airflow/ui/src/pages/Configs/Configs.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Configs/Configs.tsx
@@ -18,6 +18,9 @@
  */
 import { Heading, Separator } from "@chakra-ui/react";
 import type { ColumnDef } from "@tanstack/react-table";
+import type { TFunction } from "i18next";
+import { useMemo } from "react";
+import { useTranslation } from "react-i18next";
 
 import { useConfigServiceGetConfig } from "openapi/queries";
 import type { ConfigOption } from "openapi/requests/types.gen";
@@ -28,27 +31,30 @@ type ConfigColums = {
   section: string;
 } & ConfigOption;
 
-const columns: Array<ColumnDef<ConfigColums>> = [
+const createColumns = (translate: TFunction): Array<ColumnDef<ConfigColums>> 
=> [
   {
     accessorKey: "section",
     enableSorting: false,
-    header: "Section",
+    header: translate("config.columns.section"),
   },
   {
     accessorKey: "key",
     enableSorting: false,
-    header: "Key",
+    header: translate("columns.key"),
   },
   {
     accessorKey: "value",
     enableSorting: false,
-    header: "Value",
+    header: translate("columns.value"),
   },
 ];
 
 export const Configs = () => {
+  const { t: translate } = useTranslation(["admin", "common"]);
   const { data, error } = useConfigServiceGetConfig();
 
+  const columns = useMemo(() => createColumns(translate), [translate]);
+
   const render =
     data?.sections.flatMap((section) =>
       section.options.map((option) => ({
@@ -59,10 +65,10 @@ export const Configs = () => {
 
   return (
     <>
-      <Heading mb={4}>Airflow Configuration</Heading>
+      <Heading mb={4}>{translate("config.title")}</Heading>
       <Separator />
       {error === null ? (
-        <DataTable columns={columns} data={render} modelName="Config" />
+        <DataTable columns={columns} data={render} 
modelName={translate("common:admin.Config")} />
       ) : (
         <ErrorAlert error={error} />
       )}
diff --git 
a/airflow-core/src/airflow/ui/src/pages/Connections/AddConnectionButton.tsx 
b/airflow-core/src/airflow/ui/src/pages/Connections/AddConnectionButton.tsx
index be9de6ce449..2b437260e72 100644
--- a/airflow-core/src/airflow/ui/src/pages/Connections/AddConnectionButton.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Connections/AddConnectionButton.tsx
@@ -18,6 +18,7 @@
  */
 import { Box, Heading, VStack } from "@chakra-ui/react";
 import { useDisclosure } from "@chakra-ui/react";
+import { useTranslation } from "react-i18next";
 import { FiPlusCircle } from "react-icons/fi";
 
 import { Dialog } from "src/components/ui";
@@ -28,6 +29,7 @@ import ConnectionForm from "./ConnectionForm";
 import type { ConnectionBody } from "./Connections";
 
 const AddConnectionButton = () => {
+  const { t: translate } = useTranslation("admin");
   const { onClose, onOpen, open } = useDisclosure();
   const { addConnection, error, isPending } = useAddConnection({ 
onSuccessConfirm: onClose });
   const initialConnection: ConnectionBody = {
@@ -45,11 +47,11 @@ const AddConnectionButton = () => {
   return (
     <Box>
       <ActionButton
-        actionName="Add Connection"
+        actionName={translate("connections.add")}
         colorPalette="blue"
         icon={<FiPlusCircle />}
         onClick={onOpen}
-        text="Add Connection"
+        text={translate("connections.add")}
         variant="solid"
       />
 
@@ -57,7 +59,7 @@ const AddConnectionButton = () => {
         <Dialog.Content backdrop>
           <Dialog.Header paddingBottom={0}>
             <VStack align="start" gap={4}>
-              <Heading size="xl">Add Connection</Heading>
+              <Heading size="xl">{translate("connections.add")}</Heading>
             </VStack>
           </Dialog.Header>
 
diff --git 
a/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.tsx 
b/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.tsx
index 866d555c068..2badcd37966 100644
--- a/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.tsx
@@ -20,10 +20,11 @@ import { Input, Button, Box, Spacer, HStack, Field, Stack, 
VStack, Spinner } fro
 import { Select } from "chakra-react-select";
 import { useEffect, useState } from "react";
 import { useForm, Controller } from "react-hook-form";
+import { useTranslation } from "react-i18next";
 import { FiSave } from "react-icons/fi";
 
 import { ErrorAlert } from "src/components/ErrorAlert";
-import { FlexibleForm, flexibleFormExtraFieldSection } from 
"src/components/FlexibleForm";
+import { FlexibleForm } from "src/components/FlexibleForm";
 import { JsonEditor } from "src/components/JsonEditor";
 import { Accordion } from "src/components/ui";
 import { useConnectionTypeMeta } from "src/queries/useConnectionTypeMeta";
@@ -65,6 +66,7 @@ const ConnectionForm = ({
     mode: "onBlur",
   });
 
+  const { t: translate } = useTranslation("admin");
   const selectedConnType = watch("conn_type"); // Get the selected connection 
type
   const standardFields = connectionTypeMeta[selectedConnType]?.standard_fields 
?? {};
   const paramsDic = { paramsDict: 
connectionTypeMeta[selectedConnType]?.extra_fields ?? ({} as ParamsSpec) };
@@ -131,7 +133,7 @@ const ConnectionForm = ({
             <Field.Root invalid={Boolean(fieldState.error)} 
orientation="horizontal" required>
               <Stack>
                 <Field.Label fontSize="md" style={{ flexBasis: "30%" }}>
-                  Connection ID <Field.RequiredIndicator />
+                  {translate("connections.columns.connectionId")} 
<Field.RequiredIndicator />
                 </Field.Label>
               </Stack>
               <Stack css={{ flexBasis: "70%" }}>
@@ -141,8 +143,9 @@ const ConnectionForm = ({
             </Field.Root>
           )}
           rules={{
-            required: "Connection ID is required",
-            validate: (value) => (value.trim() === "" ? "Connection ID cannot 
contain only spaces" : true),
+            required: translate("connections.form.connectionIdRequired"),
+            validate: (value) =>
+              value.trim() === "" ? 
translate("connections.form.connectionIdRequirement") : true,
           }}
         />
 
@@ -153,7 +156,7 @@ const ConnectionForm = ({
             <Field.Root invalid={Boolean(fieldState.error)} 
orientation="horizontal" required>
               <Stack>
                 <Field.Label fontSize="md" style={{ flexBasis: "30%" }}>
-                  Connection Type <Field.RequiredIndicator />
+                  {translate("connections.columns.connectionType")} 
<Field.RequiredIndicator />
                 </Field.Label>
               </Stack>
               <Stack css={{ flexBasis: "70%" }}>
@@ -166,19 +169,16 @@ const ConnectionForm = ({
                     isDisabled={isMetaPending}
                     onChange={(val) => onChange(val?.value)}
                     options={connTypesOptions}
-                    placeholder="Select Connection Type"
+                    
placeholder={translate("connections.form.selectConnectionType")}
                     value={connTypesOptions.find((type) => type.value === 
value)}
                   />
                 </Stack>
-                <Field.HelperText>
-                  Connection type missing? Make sure you have installed the 
corresponding Airflow Providers
-                  Package.
-                </Field.HelperText>
+                
<Field.HelperText>{translate("connections.form.helperText")}</Field.HelperText>
               </Stack>
             </Field.Root>
           )}
           rules={{
-            required: "Connection Type is required",
+            required: translate("connections.form.connectionTypeRequired"),
           }}
         />
 
@@ -192,19 +192,21 @@ const ConnectionForm = ({
             variant="enclosed"
           >
             <Accordion.Item key="standardFields" value="standardFields">
-              <Accordion.ItemTrigger>Standard Fields</Accordion.ItemTrigger>
+              
<Accordion.ItemTrigger>{translate("connections.form.standardFields")}</Accordion.ItemTrigger>
               <Accordion.ItemContent>
                 <StandardFields control={control} 
standardFields={standardFields} />
               </Accordion.ItemContent>
             </Accordion.Item>
             <FlexibleForm
-              flexibleFormDefaultSection={flexibleFormExtraFieldSection}
+              
flexibleFormDefaultSection={translate("connections.form.extraFields")}
               initialParamsDict={paramsDic}
               key={selectedConnType}
               setError={setFormErrors}
             />
             <Accordion.Item key="extraJson" value="extraJson">
-              <Accordion.ItemTrigger cursor="button">Extra Fields 
JSON</Accordion.ItemTrigger>
+              <Accordion.ItemTrigger cursor="button">
+                {translate("connections.form.extraFieldsJson")}
+              </Accordion.ItemTrigger>
               <Accordion.ItemContent>
                 <Controller
                   control={control}
@@ -235,7 +237,7 @@ const ConnectionForm = ({
             disabled={Boolean(errors.conf) || formErrors || isPending || 
!isValid}
             onClick={() => void handleSubmit(onSubmit)()}
           >
-            <FiSave /> Save
+            <FiSave /> {translate("formActions.save")}
           </Button>
         </HStack>
       </Box>
diff --git a/airflow-core/src/airflow/ui/src/pages/Connections/Connections.tsx 
b/airflow-core/src/airflow/ui/src/pages/Connections/Connections.tsx
index fe1553aca7b..3ce3a020cb2 100644
--- a/airflow-core/src/airflow/ui/src/pages/Connections/Connections.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Connections/Connections.tsx
@@ -18,7 +18,9 @@
  */
 import { Box, Flex, HStack, Spacer, VStack } from "@chakra-ui/react";
 import type { ColumnDef } from "@tanstack/react-table";
+import type { TFunction } from "i18next";
 import { useMemo, useState } from "react";
+import { useTranslation } from "react-i18next";
 import { useSearchParams } from "react-router-dom";
 
 import { useConnectionServiceGetConnections } from "openapi/queries";
@@ -57,7 +59,8 @@ const getColumns = ({
   onRowSelect,
   onSelectAll,
   selectedRows,
-}: GetColumnsParams): Array<ColumnDef<ConnectionResponse>> => [
+  translate,
+}: { translate: TFunction } & GetColumnsParams): 
Array<ColumnDef<ConnectionResponse>> => [
   {
     accessorKey: "select",
     cell: ({ row }) => (
@@ -84,23 +87,23 @@ const getColumns = ({
   },
   {
     accessorKey: "connection_id",
-    header: "Connection Id",
+    header: translate("connections.columns.connectionId"),
   },
   {
     accessorKey: "conn_type",
-    header: "Connection Type",
+    header: translate("connections.columns.connectionType"),
   },
   {
     accessorKey: "description",
-    header: "Description",
+    header: translate("columns.description"),
   },
   {
     accessorKey: "host",
-    header: "Host",
+    header: translate("connections.columns.host"),
   },
   {
     accessorKey: "port",
-    header: "Port",
+    header: translate("connections.columns.port"),
   },
   {
     accessorKey: "actions",
@@ -120,6 +123,7 @@ const getColumns = ({
 ];
 
 export const Connections = () => {
+  const { t: translate } = useTranslation("admin");
   const { setTableURLState, tableURLState } = useTableURLState();
   const [searchParams, setSearchParams] = useSearchParams();
   const { NAME_PATTERN: NAME_PATTERN_PARAM }: SearchParamsKeysType = 
SearchParamsKeys;
@@ -151,8 +155,9 @@ export const Connections = () => {
         onRowSelect: handleRowSelect,
         onSelectAll: handleSelectAll,
         selectedRows,
+        translate,
       }),
-    [allRowsSelected, handleRowSelect, handleSelectAll, selectedRows],
+    [allRowsSelected, handleRowSelect, handleSelectAll, selectedRows, 
translate],
   );
 
   const handleSearchChange = (value: string) => {
@@ -176,7 +181,7 @@ export const Connections = () => {
           buttonProps={{ disabled: true }}
           defaultValue={connectionIdPattern ?? ""}
           onChange={handleSearchChange}
-          placeHolder="Search Connections"
+          placeHolder={translate("connections.searchPlaceholder")}
         />
         <HStack gap={4} mt={2}>
           <Spacer />
@@ -192,14 +197,16 @@ export const Connections = () => {
           initialState={tableURLState}
           isFetching={isFetching}
           isLoading={isLoading}
-          modelName="Connection"
+          modelName={translate("common:admin.Connections")}
           onStateChange={setTableURLState}
           total={data?.total_entries ?? 0}
         />
       </Box>
       <ActionBar.Root closeOnInteractOutside={false} 
open={Boolean(selectedRows.size)}>
         <ActionBar.Content>
-          <ActionBar.SelectionTrigger>{selectedRows.size} 
selected</ActionBar.SelectionTrigger>
+          <ActionBar.SelectionTrigger>
+            {selectedRows.size} {translate("deleteActions.selected")}
+          </ActionBar.SelectionTrigger>
           <ActionBar.Separator />
           <Tooltip content="Delete selected connections">
             <DeleteConnectionsButton
diff --git 
a/airflow-core/src/airflow/ui/src/pages/Connections/DeleteConnectionButton.tsx 
b/airflow-core/src/airflow/ui/src/pages/Connections/DeleteConnectionButton.tsx
index 8cb239dc3f8..a1af0745f12 100644
--- 
a/airflow-core/src/airflow/ui/src/pages/Connections/DeleteConnectionButton.tsx
+++ 
b/airflow-core/src/airflow/ui/src/pages/Connections/DeleteConnectionButton.tsx
@@ -16,7 +16,8 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Flex, useDisclosure, Text, VStack, Heading } from "@chakra-ui/react";
+import { Flex, useDisclosure, Text, VStack, Heading, Code } from 
"@chakra-ui/react";
+import { useTranslation } from "react-i18next";
 import { FiTrash } from "react-icons/fi";
 
 import { Button, Dialog } from "src/components/ui";
@@ -29,6 +30,7 @@ type Props = {
 };
 
 const DeleteConnectionButton = ({ connectionId, disabled }: Props) => {
+  const { t: translate } = useTranslation("admin");
   const { onClose, onOpen, open } = useDisclosure();
   const { isPending, mutate } = useDeleteConnection({
     onSuccessConfirm: onClose,
@@ -37,13 +39,13 @@ const DeleteConnectionButton = ({ connectionId, disabled }: 
Props) => {
   return (
     <>
       <ActionButton
-        actionName="Delete Connection"
+        actionName={translate("connections.delete.title")}
         disabled={disabled}
         icon={<FiTrash />}
         onClick={() => {
           onOpen();
         }}
-        text="Delete Connection"
+        text={translate("connections.delete.title")}
         withText={false}
       />
 
@@ -51,7 +53,7 @@ const DeleteConnectionButton = ({ connectionId, disabled }: 
Props) => {
         <Dialog.Content backdrop>
           <Dialog.Header>
             <VStack align="start" gap={4}>
-              <Heading size="xl">Delete Connection</Heading>
+              <Heading 
size="xl">{translate("connections.delete.deleteConnection", { count: 1 
})}</Heading>
             </VStack>
           </Dialog.Header>
 
@@ -59,10 +61,14 @@ const DeleteConnectionButton = ({ connectionId, disabled }: 
Props) => {
 
           <Dialog.Body width="full">
             <Text color="gray.solid" fontSize="md" fontWeight="semibold" 
mb={4}>
-              You are about to delete connection having ID 
<strong>{connectionId}</strong>.
+              {translate("connections.delete.firstConfirmMessage_one")}
               <br />
-              This action is permanent and cannot be undone.{" "}
-              <strong>Are you sure you want to proceed?</strong>
+              <Code mb={2} mt={2} p={4}>
+                {connectionId}
+              </Code>
+              <br />
+              {translate("deleteActions.modal.secondConfirmMessage")}
+              
<strong>{translate("deleteActions.modal.thirdConfirmMessage")}</strong>
             </Text>
             <Flex justifyContent="end" mt={3}>
               <Button
@@ -74,7 +80,7 @@ const DeleteConnectionButton = ({ connectionId, disabled }: 
Props) => {
                   });
                 }}
               >
-                <FiTrash /> <Text fontWeight="bold">Yes, Delete</Text>
+                <FiTrash /> <Text 
fontWeight="bold">{translate("deleteActions.modal.confirmButton")}</Text>
               </Button>
             </Flex>
           </Dialog.Body>
diff --git 
a/airflow-core/src/airflow/ui/src/pages/Connections/DeleteConnectionsButton.tsx 
b/airflow-core/src/airflow/ui/src/pages/Connections/DeleteConnectionsButton.tsx
index 66e248cdfe3..fcaf2178351 100644
--- 
a/airflow-core/src/airflow/ui/src/pages/Connections/DeleteConnectionsButton.tsx
+++ 
b/airflow-core/src/airflow/ui/src/pages/Connections/DeleteConnectionsButton.tsx
@@ -17,6 +17,7 @@
  * under the License.
  */
 import { Code, Flex, Heading, Text, VStack, useDisclosure } from 
"@chakra-ui/react";
+import { useTranslation } from "react-i18next";
 import { FiTrash, FiTrash2 } from "react-icons/fi";
 
 import { ErrorAlert } from "src/components/ErrorAlert";
@@ -29,6 +30,7 @@ type Props = {
 };
 
 const DeleteConnectionsButton = ({ clearSelections, deleteKeys: connectionIds 
}: Props) => {
+  const { t: translate } = useTranslation("admin");
   const { onClose, onOpen, open } = useDisclosure();
   const { error, isPending, mutate } = useBulkDeleteConnections({
     clearSelections,
@@ -42,14 +44,16 @@ const DeleteConnectionsButton = ({ clearSelections, 
deleteKeys: connectionIds }:
   return (
     <>
       <Button aria-label="Delete selected connections" onClick={onOpen} 
size="sm" variant="outline">
-        <FiTrash2 /> Delete
+        <FiTrash2 /> {translate("deleteActions.button")}
       </Button>
 
       <Dialog.Root onOpenChange={onClose} open={open} size="xl">
         <Dialog.Content backdrop>
           <Dialog.Header>
             <VStack align="start" gap={4}>
-              <Heading size="xl">Delete Connection{connectionIds.length > 1 ? 
"s" : ""}</Heading>
+              <Heading size="xl">
+                {translate("connections.delete.deleteConnection", { count: 
connectionIds.length })}
+              </Heading>
             </VStack>
           </Dialog.Header>
 
@@ -57,17 +61,14 @@ const DeleteConnectionsButton = ({ clearSelections, 
deleteKeys: connectionIds }:
 
           <Dialog.Body width="full">
             <Text color="gray.solid" fontSize="md" fontWeight="semibold" 
mb={4}>
-              You are about to delete{" "}
-              <strong>
-                {connectionIds.length} connection{connectionIds.length > 1 ? 
"s" : ""}.
-              </strong>
+              {translate("connections.delete.firstConfirmMessage", { count: 
connectionIds.length })}
               <br />
               <Code mb={2} mt={2} p={4}>
                 {connectionIds.join(", ")}
               </Code>
               <br />
-              This action is permanent and cannot be undone.{" "}
-              <strong>Are you sure you want to proceed?</strong>
+              {translate("deleteActions.modal.secondConfirmMessage")}
+              
<strong>{translate("deleteActions.modal.thirdConfirmMessage")}</strong>
             </Text>
             <ErrorAlert error={error} />
             <Flex justifyContent="end" mt={3}>
@@ -78,7 +79,7 @@ const DeleteConnectionsButton = ({ clearSelections, 
deleteKeys: connectionIds }:
                   mutate({ requestBody: { actions: [{ action: "delete", 
entities: connectionIds }] } });
                 }}
               >
-                <FiTrash /> <Text as="span">Yes, Delete</Text>
+                <FiTrash /> <Text 
as="span">{translate("deleteActions.modal.confirmButton")}</Text>
               </Button>
             </Flex>
           </Dialog.Body>
diff --git 
a/airflow-core/src/airflow/ui/src/pages/Connections/EditConnectionButton.tsx 
b/airflow-core/src/airflow/ui/src/pages/Connections/EditConnectionButton.tsx
index 33ce9832b9a..1e3b7eccfab 100644
--- a/airflow-core/src/airflow/ui/src/pages/Connections/EditConnectionButton.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Connections/EditConnectionButton.tsx
@@ -17,6 +17,7 @@
  * under the License.
  */
 import { Heading, useDisclosure } from "@chakra-ui/react";
+import { useTranslation } from "react-i18next";
 import { FiEdit } from "react-icons/fi";
 
 import type { ConnectionResponse } from "openapi/requests/types.gen";
@@ -33,6 +34,7 @@ type Props = {
 };
 
 const EditConnectionButton = ({ connection, disabled }: Props) => {
+  const { t: translate } = useTranslation("admin");
   const { onClose, onOpen, open } = useDisclosure();
   const initialConnectionValue: ConnectionBody = {
     conn_type: connection.conn_type,
@@ -57,20 +59,20 @@ const EditConnectionButton = ({ connection, disabled }: 
Props) => {
   return (
     <>
       <ActionButton
-        actionName="Edit Connection"
+        actionName={translate("connections.edit")}
         disabled={disabled}
         icon={<FiEdit />}
         onClick={() => {
           onOpen();
         }}
-        text="Edit Connection"
+        text={translate("connections.edit")}
         withText={false}
       />
 
       <Dialog.Root onOpenChange={handleClose} open={open} size="xl">
         <Dialog.Content backdrop>
           <Dialog.Header>
-            <Heading size="xl">Edit Connection</Heading>
+            <Heading size="xl">{translate("connections.edit")}</Heading>
           </Dialog.Header>
 
           <Dialog.CloseTrigger />
diff --git 
a/airflow-core/src/airflow/ui/src/pages/Connections/TestConnectionButton.tsx 
b/airflow-core/src/airflow/ui/src/pages/Connections/TestConnectionButton.tsx
index 3fddfb62e8b..7b27877d870 100644
--- a/airflow-core/src/airflow/ui/src/pages/Connections/TestConnectionButton.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Connections/TestConnectionButton.tsx
@@ -35,7 +35,7 @@ const connectedIcon = <FiWifi color="green" />;
 const disconnectedIcon = <FiWifiOff color="red" />;
 
 const TestConnectionButton = ({ connection }: Props) => {
-  const { t: translate } = useTranslation("connections");
+  const { t: translate } = useTranslation("admin");
   const [icon, setIcon] = useState(defaultIcon);
   const testConnection = useConfig("test_connection");
   let option: TestConnectionOption;
@@ -72,7 +72,9 @@ const TestConnectionButton = ({ connection }: Props) => {
 
   return (
     <ActionButton
-      actionName={option === "Enabled" ? translate("test") : 
translate("testDisabled")}
+      actionName={
+        option === "Enabled" ? translate("connections.test") : 
translate("connections.testDisabled")
+      }
       disabled={option === "Disabled"}
       display={option === "Hidden" ? "none" : "flex"}
       icon={icon}
@@ -80,7 +82,7 @@ const TestConnectionButton = ({ connection }: Props) => {
       onClick={() => {
         mutate({ requestBody: connectionBody });
       }}
-      text={translate("test")}
+      text={translate("connections.test")}
       withText={false}
     />
   );
diff --git 
a/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/PluginImportErrors.tsx 
b/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/PluginImportErrors.tsx
index 5c0a89680c1..cea92bed6d7 100644
--- 
a/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/PluginImportErrors.tsx
+++ 
b/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/PluginImportErrors.tsx
@@ -17,19 +17,19 @@
  * under the License.
  */
 import { Box, Text, Button, useDisclosure, Skeleton } from "@chakra-ui/react";
+import { useTranslation } from "react-i18next";
 import { FiChevronRight } from "react-icons/fi";
 import { LuPlug } from "react-icons/lu";
 
 import { usePluginServiceImportErrors } from "openapi/queries";
 import { ErrorAlert, type ExpandedApiError } from "src/components/ErrorAlert";
 import { StateBadge } from "src/components/StateBadge";
-import { pluralize } from "src/utils";
 
 import { PluginImportErrorsModal } from "./PluginImportErrorsModal";
 
 export const PluginImportErrors = ({ iconOnly = false }: { readonly iconOnly?: 
boolean }) => {
   const { onClose, onOpen, open } = useDisclosure();
-
+  const { t: translate } = useTranslation("admin");
   const { data, error, isLoading } = usePluginServiceImportErrors();
 
   const importErrorsCount = data?.total_entries ?? 0;
@@ -56,7 +56,7 @@ export const PluginImportErrors = ({ iconOnly = false }: { 
readonly iconOnly?: b
           colorPalette="failed"
           height={7}
           onClick={onOpen}
-          title={pluralize("Plugin Import Error", importErrorsCount)}
+          title={translate("plugins.importError", { count: importErrorsCount 
})}
         >
           <LuPlug size="0.5rem" />
           {importErrorsCount}
@@ -75,7 +75,7 @@ export const PluginImportErrors = ({ iconOnly = false }: { 
readonly iconOnly?: b
             {importErrorsCount}
           </StateBadge>
           <Box alignItems="center" display="flex" gap={1}>
-            <Text fontWeight="bold">Plugin Import Errors</Text>
+            <Text fontWeight="bold">{translate("plugins.importError", { count: 
importErrorsCount })}</Text>
             <FiChevronRight />
           </Box>
         </Button>
diff --git 
a/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/PluginImportErrorsModal.tsx
 
b/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/PluginImportErrorsModal.tsx
index e4a76482f06..905a023a22c 100644
--- 
a/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/PluginImportErrorsModal.tsx
+++ 
b/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/PluginImportErrorsModal.tsx
@@ -18,6 +18,7 @@
  */
 import { Heading, Text, HStack } from "@chakra-ui/react";
 import { useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
 import { LuFileWarning } from "react-icons/lu";
 import { PiFilePy } from "react-icons/pi";
 
@@ -39,6 +40,7 @@ export const PluginImportErrorsModal: 
React.FC<PluginImportErrorsModalProps> = (
   onClose,
   open,
 }) => {
+  const { t: translate } = useTranslation("admin");
   const [page, setPage] = useState(1);
   const [searchQuery, setSearchQuery] = useState("");
   const [filteredErrors, setFilteredErrors] = useState(importErrors);
@@ -67,14 +69,14 @@ export const PluginImportErrorsModal: 
React.FC<PluginImportErrorsModalProps> = (
         <Dialog.Header display="flex" justifyContent="space-between">
           <HStack fontSize="xl">
             <LuFileWarning />
-            <Heading>Plugin Import Errors</Heading>
+            <Heading>{translate("plugins.importError_one")}</Heading>
           </HStack>
           <SearchBar
             buttonProps={{ disabled: true }}
             defaultValue={searchQuery}
             hideAdvanced
             onChange={setSearchQuery}
-            placeHolder="Search by file"
+            placeHolder={translate("plugins.searchPlaceholder")}
           />
         </Dialog.Header>
 
diff --git a/airflow-core/src/airflow/ui/src/pages/Events/Events.tsx 
b/airflow-core/src/airflow/ui/src/pages/Events/Events.tsx
index 5a732fcba44..a3b306a4af3 100644
--- a/airflow-core/src/airflow/ui/src/pages/Events/Events.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Events/Events.tsx
@@ -18,6 +18,7 @@
  */
 import { Box, ButtonGroup, Code, Flex, Heading, IconButton, useDisclosure } 
from "@chakra-ui/react";
 import type { ColumnDef } from "@tanstack/react-table";
+import { useTranslation } from "react-i18next";
 import { MdCompress, MdExpand } from "react-icons/md";
 import { useParams } from "react-router-dom";
 
@@ -36,12 +37,15 @@ type EventsColumn = {
   taskId?: string;
 };
 
-const eventsColumn = ({ dagId, open, runId, taskId }: EventsColumn): 
Array<ColumnDef<EventLogResponse>> => [
+const eventsColumn = (
+  { dagId, open, runId, taskId }: EventsColumn,
+  translate: (key: string) => string,
+): Array<ColumnDef<EventLogResponse>> => [
   {
     accessorKey: "when",
     cell: ({ row: { original } }) => <Time datetime={original.when} />,
     enableSorting: true,
-    header: "When",
+    header: translate("auditLog.columns.when"),
     meta: {
       skeletonWidth: 10,
     },
@@ -49,7 +53,7 @@ const eventsColumn = ({ dagId, open, runId, taskId }: 
EventsColumn): Array<Colum
   {
     accessorKey: "event",
     enableSorting: true,
-    header: "Event",
+    header: translate("auditLog.columns.event"),
     meta: {
       skeletonWidth: 10,
     },
@@ -57,7 +61,7 @@ const eventsColumn = ({ dagId, open, runId, taskId }: 
EventsColumn): Array<Colum
   {
     accessorKey: "owner",
     enableSorting: true,
-    header: "User",
+    header: translate("auditLog.columns.user"),
     meta: {
       skeletonWidth: 10,
     },
@@ -78,7 +82,7 @@ const eventsColumn = ({ dagId, open, runId, taskId }: 
EventsColumn): Array<Colum
       return undefined;
     },
     enableSorting: false,
-    header: "Extra",
+    header: translate("auditLog.columns.extra"),
     meta: {
       skeletonWidth: 200,
     },
@@ -89,7 +93,7 @@ const eventsColumn = ({ dagId, open, runId, taskId }: 
EventsColumn): Array<Colum
         {
           accessorKey: "dag_id",
           enableSorting: true,
-          header: "Dag ID",
+          header: translate("common:dagId"),
           meta: {
             skeletonWidth: 10,
           },
@@ -101,7 +105,7 @@ const eventsColumn = ({ dagId, open, runId, taskId }: 
EventsColumn): Array<Colum
         {
           accessorKey: "run_id",
           enableSorting: true,
-          header: "Run ID",
+          header: translate("common:runId"),
           meta: {
             skeletonWidth: 10,
           },
@@ -113,7 +117,7 @@ const eventsColumn = ({ dagId, open, runId, taskId }: 
EventsColumn): Array<Colum
         {
           accessorKey: "task_id",
           enableSorting: true,
-          header: "Task ID",
+          header: translate("common:taskId"),
           meta: {
             skeletonWidth: 10,
           },
@@ -122,7 +126,7 @@ const eventsColumn = ({ dagId, open, runId, taskId }: 
EventsColumn): Array<Colum
   {
     accessorKey: "map_index",
     enableSorting: false,
-    header: "Map Index",
+    header: translate("common:mapIndex"),
     meta: {
       skeletonWidth: 10,
     },
@@ -130,7 +134,7 @@ const eventsColumn = ({ dagId, open, runId, taskId }: 
EventsColumn): Array<Colum
   {
     accessorKey: "try_number",
     enableSorting: false,
-    header: "Try Number",
+    header: translate("common:tryNumber"),
     meta: {
       skeletonWidth: 10,
     },
@@ -138,6 +142,7 @@ const eventsColumn = ({ dagId, open, runId, taskId }: 
EventsColumn): Array<Colum
 ];
 
 export const Events = () => {
+  const { t: translate } = useTranslation("browse");
   const { dagId, runId, taskId } = useParams();
   const { setTableURLState, tableURLState } = useTableURLState();
   const { pagination, sorting } = tableURLState;
@@ -162,22 +167,22 @@ export const Events = () => {
   return (
     <Box>
       <Flex alignItems="center" justifyContent="space-between">
-        <Heading>Audit Log Events</Heading>
+        <Heading>{translate("auditLog.title")}</Heading>
         <ButtonGroup attached mt="1" size="sm" variant="surface">
           <IconButton
-            aria-label="Expand all extra json"
+            aria-label={translate("auditLog.actions.expandAllExtra")}
             onClick={onOpen}
             size="sm"
-            title="Expand all extra json"
+            title={translate("auditLog.actions.expandAllExtra")}
             variant="surface"
           >
             <MdExpand />
           </IconButton>
           <IconButton
-            aria-label="Collapse all extra json"
+            aria-label={translate("auditLog.actions.collapseAllExtra")}
             onClick={onClose}
             size="sm"
-            title="Collapse all extra json"
+            title={translate("auditLog.actions.collapseAllExtra")}
             variant="surface"
           >
             <MdCompress />
@@ -186,13 +191,13 @@ export const Events = () => {
       </Flex>
       <ErrorAlert error={error} />
       <DataTable
-        columns={eventsColumn({ dagId, open, runId, taskId })}
+        columns={eventsColumn({ dagId, open, runId, taskId }, translate)}
         data={data ? data.event_logs : []}
         displayMode="table"
         initialState={tableURLState}
         isFetching={isFetching}
         isLoading={isLoading}
-        modelName="Event"
+        modelName={translate("auditLog.columns.event")}
         onStateChange={setTableURLState}
         skeletonCount={undefined}
         total={data ? data.total_entries : 0}
diff --git a/airflow-core/src/airflow/ui/src/pages/Plugins.tsx 
b/airflow-core/src/airflow/ui/src/pages/Plugins.tsx
index a97c1e9fb82..2829c05c311 100644
--- a/airflow-core/src/airflow/ui/src/pages/Plugins.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Plugins.tsx
@@ -18,6 +18,9 @@
  */
 import { Box, Heading, HStack } from "@chakra-ui/react";
 import type { ColumnDef } from "@tanstack/react-table";
+import type { TFunction } from "i18next";
+import { useMemo } from "react";
+import { useTranslation } from "react-i18next";
 
 import { usePluginServiceGetPlugins } from "openapi/queries";
 import type { PluginResponse } from "openapi/requests/types.gen";
@@ -26,33 +29,36 @@ import { ErrorAlert } from "src/components/ErrorAlert";
 
 import { PluginImportErrors } from "./Dashboard/Stats/PluginImportErrors";
 
-const columns: Array<ColumnDef<PluginResponse>> = [
+const createColumns = (translate: TFunction): Array<ColumnDef<PluginResponse>> 
=> [
   {
     accessorKey: "name",
     enableSorting: false,
-    header: "Name",
+    header: translate("columns.name"),
   },
   {
     accessorKey: "source",
     enableSorting: false,
-    header: "Source",
+    header: translate("plugins.columns.source"),
   },
 ];
 
 export const Plugins = () => {
+  const { t: translate } = useTranslation(["admin", "common"]);
   const { data, error } = usePluginServiceGetPlugins();
 
+  const columns = useMemo(() => createColumns(translate), [translate]);
+
   return (
     <Box p={2}>
       <HStack>
-        <Heading>Plugins</Heading>
+        <Heading>{translate("common:admin.Plugins")}</Heading>
         <PluginImportErrors iconOnly />
       </HStack>
       <DataTable
         columns={columns}
         data={data?.plugins ?? []}
         errorMessage={<ErrorAlert error={error} />}
-        modelName="Plugin"
+        modelName={translate("common:admin.Plugins")}
         total={data?.total_entries}
       />
     </Box>
diff --git a/airflow-core/src/airflow/ui/src/pages/Pools/AddPoolButton.tsx 
b/airflow-core/src/airflow/ui/src/pages/Pools/AddPoolButton.tsx
index e3de3529829..48167580872 100644
--- a/airflow-core/src/airflow/ui/src/pages/Pools/AddPoolButton.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Pools/AddPoolButton.tsx
@@ -17,6 +17,7 @@
  * under the License.
  */
 import { Heading, useDisclosure } from "@chakra-ui/react";
+import { useTranslation } from "react-i18next";
 import { FiPlusCircle } from "react-icons/fi";
 
 import { Button, Dialog, Toaster } from "src/components/ui";
@@ -25,6 +26,7 @@ import { useAddPool } from "src/queries/useAddPool";
 import PoolForm, { type PoolBody } from "./PoolForm";
 
 const AddPoolButton = () => {
+  const { t: translate } = useTranslation("admin");
   const { onClose, onOpen, open } = useDisclosure();
   const { addPool, error, isPending, setError } = useAddPool({
     onSuccessConfirm: onClose,
@@ -46,13 +48,13 @@ const AddPoolButton = () => {
     <>
       <Toaster />
       <Button colorPalette="blue" onClick={onOpen}>
-        <FiPlusCircle /> Add Pool
+        <FiPlusCircle /> {translate("pools.add")}
       </Button>
 
       <Dialog.Root onOpenChange={handleClose} open={open} size="xl">
         <Dialog.Content backdrop>
           <Dialog.Header>
-            <Heading size="xl">Add Pool</Heading>
+            <Heading size="xl">{translate("pools.add")}</Heading>
           </Dialog.Header>
 
           <Dialog.CloseTrigger />
diff --git a/airflow-core/src/airflow/ui/src/pages/Pools/DeletePoolButton.tsx 
b/airflow-core/src/airflow/ui/src/pages/Pools/DeletePoolButton.tsx
index 1e76102ba83..bc2c47e8e38 100644
--- a/airflow-core/src/airflow/ui/src/pages/Pools/DeletePoolButton.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Pools/DeletePoolButton.tsx
@@ -17,6 +17,7 @@
  * under the License.
  */
 import { useDisclosure } from "@chakra-ui/react";
+import { useTranslation } from "react-i18next";
 import { FiTrash2 } from "react-icons/fi";
 
 import DeleteDialog from "src/components/DeleteDialog";
@@ -29,6 +30,7 @@ type Props = {
 };
 
 const DeletePoolButton = ({ poolName, withText = false }: Props) => {
+  const { t: translate } = useTranslation("admin");
   const { onClose, onOpen, open } = useDisclosure();
   const { isPending, mutate } = useDeletePool({
     onSuccessConfirm: onClose,
@@ -37,11 +39,11 @@ const DeletePoolButton = ({ poolName, withText = false }: 
Props) => {
   return (
     <>
       <ActionButton
-        actionName="Delete Pool"
+        actionName={translate("pools.delete.title")}
         colorPalette="red"
         icon={<FiTrash2 />}
         onClick={onOpen}
-        text="Delete Pool"
+        text={translate("pools.delete.warning")}
         variant="solid"
         withText={withText}
       />
@@ -52,8 +54,8 @@ const DeletePoolButton = ({ poolName, withText = false }: 
Props) => {
         onDelete={() => mutate({ poolName })}
         open={open}
         resourceName={poolName}
-        title="Delete Pool"
-        warningText="This will remove all metadata related to the pool and may 
affect tasks using this pool."
+        title={translate("pools.delete.title")}
+        warningText={translate("pools.delete.warning")}
       />
     </>
   );
diff --git a/airflow-core/src/airflow/ui/src/pages/Pools/EditPoolButton.tsx 
b/airflow-core/src/airflow/ui/src/pages/Pools/EditPoolButton.tsx
index 3f1a9898cf8..914b36f7462 100644
--- a/airflow-core/src/airflow/ui/src/pages/Pools/EditPoolButton.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Pools/EditPoolButton.tsx
@@ -17,6 +17,7 @@
  * under the License.
  */
 import { Heading, useDisclosure } from "@chakra-ui/react";
+import { useTranslation } from "react-i18next";
 import { FiEdit } from "react-icons/fi";
 
 import type { PoolResponse } from "openapi/requests/types.gen";
@@ -31,6 +32,7 @@ type Props = {
 };
 
 const EditPoolButton = ({ pool }: Props) => {
+  const { t: translate } = useTranslation("admin");
   const { onClose, onOpen, open } = useDisclosure();
   const initialPoolValue: PoolBody = {
     description: pool.description ?? "",
@@ -50,19 +52,19 @@ const EditPoolButton = ({ pool }: Props) => {
   return (
     <>
       <ActionButton
-        actionName="Edit Pool"
+        actionName={translate("pools.edit")}
         icon={<FiEdit />}
         onClick={() => {
           onOpen();
         }}
-        text="Edit Pool"
+        text={translate("pools.edit")}
         withText={false}
       />
 
       <Dialog.Root onOpenChange={handleClose} open={open} size="xl">
         <Dialog.Content backdrop>
           <Dialog.Header>
-            <Heading size="xl">Edit Pool</Heading>
+            <Heading size="xl">{translate("pools.edit")}</Heading>
           </Dialog.Header>
 
           <Dialog.CloseTrigger />
diff --git a/airflow-core/src/airflow/ui/src/pages/Pools/PoolBarCard.tsx 
b/airflow-core/src/airflow/ui/src/pages/Pools/PoolBarCard.tsx
index b4b31c4fcde..2e0403592c3 100644
--- a/airflow-core/src/airflow/ui/src/pages/Pools/PoolBarCard.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Pools/PoolBarCard.tsx
@@ -17,6 +17,7 @@
  * under the License.
  */
 import { Box, Flex, HStack, Text, VStack } from "@chakra-ui/react";
+import { useTranslation } from "react-i18next";
 
 import type { PoolResponse } from "openapi/requests/types.gen";
 import { PoolBar } from "src/components/PoolBar";
@@ -30,40 +31,44 @@ type PoolBarCardProps = {
   readonly pool: PoolResponse;
 };
 
-const PoolBarCard = ({ pool }: PoolBarCardProps) => (
-  <Box borderColor="border.emphasized" borderRadius={8} borderWidth={1} mb={2} 
overflow="hidden">
-    <Flex alignItems="center" bg="bg.muted" justifyContent="space-between" 
p={4}>
-      <VStack align="start" flex="1">
-        <HStack justifyContent="space-between" width="100%">
-          <Text fontSize="lg" fontWeight="bold" whiteSpace="normal" 
wordBreak="break-word">
-            {pool.name} ({pool.slots} slots)
-            {pool.include_deferred ? (
-              <Tooltip content="Deferred Slots Included">
-                <StateIcon size={18} state="deferred" style={{ display: 
"inline", marginLeft: 6 }} />
-              </Tooltip>
-            ) : undefined}
-          </Text>
-          <HStack gap={0}>
-            <EditPoolButton pool={pool} />
-            {pool.name === "default_pool" ? undefined : (
-              <DeletePoolButton poolName={pool.name} withText={false} />
-            )}
-          </HStack>
-        </HStack>
-        {pool.description ?? (
-          <Text color="gray.fg" fontSize="sm">
-            {pool.description}
-          </Text>
-        )}
-      </VStack>
-    </Flex>
+const PoolBarCard = ({ pool }: PoolBarCardProps) => {
+  const { t: translate } = useTranslation("admin");
 
-    <Box margin={4}>
-      <Flex bg="gray.muted" borderRadius="md" h="20px" overflow="hidden" 
w="100%">
-        <PoolBar pool={pool} totalSlots={pool.slots} />
+  return (
+    <Box borderColor="border.emphasized" borderRadius={8} borderWidth={1} 
mb={2} overflow="hidden">
+      <Flex alignItems="center" bg="bg.muted" justifyContent="space-between" 
p={4}>
+        <VStack align="start" flex="1">
+          <HStack justifyContent="space-between" width="100%">
+            <Text fontSize="lg" fontWeight="bold" whiteSpace="normal" 
wordBreak="break-word">
+              {pool.name} ({pool.slots} {translate("pools.form.slots")})
+              {pool.include_deferred ? (
+                <Tooltip content={translate("pools.deferredSlotsIncluded")}>
+                  <StateIcon size={18} state="deferred" style={{ display: 
"inline", marginLeft: 6 }} />
+                </Tooltip>
+              ) : undefined}
+            </Text>
+            <HStack gap={0}>
+              <EditPoolButton pool={pool} />
+              {pool.name === "default_pool" ? undefined : (
+                <DeletePoolButton poolName={pool.name} withText={false} />
+              )}
+            </HStack>
+          </HStack>
+          {pool.description ?? (
+            <Text color="gray.fg" fontSize="sm">
+              {pool.description}
+            </Text>
+          )}
+        </VStack>
       </Flex>
+
+      <Box margin={4}>
+        <Flex bg="gray.muted" borderRadius="md" h="20px" overflow="hidden" 
w="100%">
+          <PoolBar pool={pool} totalSlots={pool.slots} />
+        </Flex>
+      </Box>
     </Box>
-  </Box>
-);
+  );
+};
 
 export default PoolBarCard;
diff --git a/airflow-core/src/airflow/ui/src/pages/Pools/PoolForm.tsx 
b/airflow-core/src/airflow/ui/src/pages/Pools/PoolForm.tsx
index f93ab81442f..a95252c97f7 100644
--- a/airflow-core/src/airflow/ui/src/pages/Pools/PoolForm.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Pools/PoolForm.tsx
@@ -18,6 +18,7 @@
  */
 import { Box, Field, HStack, Input, Spacer, Textarea } from "@chakra-ui/react";
 import { Controller, useForm } from "react-hook-form";
+import { useTranslation } from "react-i18next";
 import { FiSave } from "react-icons/fi";
 
 import { ErrorAlert } from "src/components/ErrorAlert";
@@ -40,6 +41,7 @@ type PoolFormProps = {
 };
 
 const PoolForm = ({ error, initialPool, isPending, manageMutate, setError }: 
PoolFormProps) => {
+  const { t: translate } = useTranslation("admin");
   const {
     control,
     formState: { isDirty, isValid },
@@ -67,15 +69,15 @@ const PoolForm = ({ error, initialPool, isPending, 
manageMutate, setError }: Poo
         render={({ field, fieldState }) => (
           <Field.Root invalid={Boolean(fieldState.error)} required>
             <Field.Label fontSize="md">
-              Name <Field.RequiredIndicator />
+              {translate("columns.name")} <Field.RequiredIndicator />
             </Field.Label>
             <Input {...field} disabled={Boolean(initialPool.name)} required 
size="sm" />
             {fieldState.error ? 
<Field.ErrorText>{fieldState.error.message}</Field.ErrorText> : undefined}
           </Field.Root>
         )}
         rules={{
-          required: "Name is required",
-          validate: (_value) => _value.length <= 256 || "Name can contain a 
maximum of 256 characters",
+          required: translate("pools.form.nameRequired"),
+          validate: (_value) => _value.length <= 256 || 
translate("pools.form.rules.nameMaxLength"),
         }}
       />
 
@@ -84,7 +86,7 @@ const PoolForm = ({ error, initialPool, isPending, 
manageMutate, setError }: Poo
         name="slots"
         render={({ field }) => (
           <Field.Root mt={4}>
-            <Field.Label fontSize="md">Slots</Field.Label>
+            <Field.Label 
fontSize="md">{translate("pools.form.slots")}</Field.Label>
             <Input {...field} min={initialPool.slots} size="sm" type="number" 
/>
           </Field.Root>
         )}
@@ -95,7 +97,7 @@ const PoolForm = ({ error, initialPool, isPending, 
manageMutate, setError }: Poo
         name="description"
         render={({ field }) => (
           <Field.Root mb={4} mt={4}>
-            <Field.Label fontSize="md">Description</Field.Label>
+            <Field.Label 
fontSize="md">{translate("columns.description")}</Field.Label>
             <Textarea {...field} disabled={initialPool.name === 
"default_pool"} size="sm" />
           </Field.Root>
         )}
@@ -106,9 +108,9 @@ const PoolForm = ({ error, initialPool, isPending, 
manageMutate, setError }: Poo
         name="include_deferred"
         render={({ field }) => (
           <Field.Root mb={4} mt={4}>
-            <Field.Label fontSize="md">Include Deferred</Field.Label>
+            <Field.Label 
fontSize="md">{translate("pools.form.includeDeferred")}</Field.Label>
             <Checkbox checked={field.value} colorPalette="blue" 
onChange={field.onChange} size="sm">
-              Check to include deferred tasks when calculating open pool slots
+              {translate("pools.form.checkbox")}
             </Checkbox>
           </Field.Root>
         )}
@@ -120,7 +122,7 @@ const PoolForm = ({ error, initialPool, isPending, 
manageMutate, setError }: Poo
         <HStack w="full">
           {isDirty ? (
             <Button onClick={handleReset} variant="outline">
-              Reset
+              {translate("formActions.reset")}
             </Button>
           ) : undefined}
           <Spacer />
@@ -129,7 +131,7 @@ const PoolForm = ({ error, initialPool, isPending, 
manageMutate, setError }: Poo
             disabled={!isValid || isPending}
             onClick={() => void handleSubmit(onSubmit)()}
           >
-            <FiSave /> Save
+            <FiSave /> {translate("formActions.save")}
           </Button>
         </HStack>
       </Box>
diff --git a/airflow-core/src/airflow/ui/src/pages/Pools/Pools.tsx 
b/airflow-core/src/airflow/ui/src/pages/Pools/Pools.tsx
index 48b0b54c4b0..ff1ca88c9f4 100644
--- a/airflow-core/src/airflow/ui/src/pages/Pools/Pools.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Pools/Pools.tsx
@@ -19,6 +19,7 @@
 import { Box, HStack, Skeleton } from "@chakra-ui/react";
 import { createListCollection } from "@chakra-ui/react/collection";
 import { useState } from "react";
+import { useTranslation } from "react-i18next";
 import { useSearchParams } from "react-router-dom";
 
 import { usePoolServiceGetPools } from "openapi/queries";
@@ -42,14 +43,15 @@ const cardDef = (): CardDef<PoolResponse> => ({
   },
 });
 
-const poolSortOptions = createListCollection({
-  items: [
-    { label: "Name (A-Z)", value: "name" },
-    { label: "Name (Z-A)", value: "-name" },
-  ],
-});
-
 export const Pools = () => {
+  const { t: translate } = useTranslation(["admin", "common"]);
+
+  const poolSortOptions = createListCollection({
+    items: [
+      { label: translate("pools.sort.asc"), value: "name" },
+      { label: translate("pools.sort.desc"), value: "-name" },
+    ],
+  });
   const [searchParams, setSearchParams] = useSearchParams();
   const { NAME_PATTERN: NAME_PATTERN_PARAM }: SearchParamsKeysType = 
SearchParamsKeys;
   const [poolNamePattern, setPoolNamePattern] = 
useState(searchParams.get(NAME_PATTERN_PARAM) ?? undefined);
@@ -94,7 +96,7 @@ export const Pools = () => {
         buttonProps={{ disabled: true }}
         defaultValue={poolNamePattern ?? ""}
         onChange={handleSearchChange}
-        placeHolder="Search Pools"
+        placeHolder={translate("pools.searchPlaceholder")}
       />
       <HStack gap={4} mt={4}>
         <Select.Root
@@ -105,7 +107,7 @@ export const Pools = () => {
           width={130}
         >
           <Select.Trigger>
-            <Select.ValueText placeholder="Sort by" />
+            <Select.ValueText 
placeholder={translate("pools.sort.placeholder")} />
           </Select.Trigger>
 
           <Select.Content>
@@ -126,7 +128,8 @@ export const Pools = () => {
           displayMode="card"
           initialState={tableURLState}
           isLoading={isLoading}
-          modelName="Pool"
+          modelName={translate("common:admin.Pools")}
+          noRowsMessage={translate("pools.noPoolsFound")}
           onStateChange={setTableURLState}
           total={data ? data.total_entries : 0}
         />
diff --git a/airflow-core/src/airflow/ui/src/pages/Providers.tsx 
b/airflow-core/src/airflow/ui/src/pages/Providers.tsx
index 85f11d3d12c..8602f3534e9 100644
--- a/airflow-core/src/airflow/ui/src/pages/Providers.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Providers.tsx
@@ -18,6 +18,9 @@
  */
 import { Box, Heading, Link } from "@chakra-ui/react";
 import type { ColumnDef } from "@tanstack/react-table";
+import type { TFunction } from "i18next";
+import { useMemo } from "react";
+import { useTranslation } from "react-i18next";
 
 import { useProviderServiceGetProviders } from "openapi/queries";
 import type { ProviderResponse } from "openapi/requests/types.gen";
@@ -26,7 +29,7 @@ import { useTableURLState } from 
"src/components/DataTable/useTableUrlState";
 import { ErrorAlert } from "src/components/ErrorAlert";
 import { urlRegex } from "src/constants/urlRegex";
 
-const columns: Array<ColumnDef<ProviderResponse>> = [
+const createColumns = (translate: TFunction): 
Array<ColumnDef<ProviderResponse>> => [
   {
     accessorKey: "package_name",
     cell: ({ row: { original } }) => (
@@ -41,13 +44,13 @@ const columns: Array<ColumnDef<ProviderResponse>> = [
       </Link>
     ),
     enableSorting: false,
-    header: "Package Name",
+    header: translate("providers.columns.packageName"),
   },
   {
     accessorKey: "version",
     cell: ({ row: { original } }) => original.version,
     enableSorting: false,
-    header: () => "Version",
+    header: translate("providers.columns.version"),
   },
   {
     accessorKey: "description",
@@ -66,13 +69,16 @@ const columns: Array<ColumnDef<ProviderResponse>> = [
       );
     },
     enableSorting: false,
-    header: "Description",
+    header: translate("columns.description"),
   },
 ];
 
 export const Providers = () => {
+  const { t: translate } = useTranslation(["admin", "common"]);
   const { setTableURLState, tableURLState } = useTableURLState();
 
+  const columns = useMemo(() => createColumns(translate), [translate]);
+
   const { pagination } = tableURLState;
 
   const { data, error } = useProviderServiceGetProviders({
@@ -82,13 +88,13 @@ export const Providers = () => {
 
   return (
     <Box p={2}>
-      <Heading>Providers</Heading>
+      <Heading>{translate("common:admin.Providers")}</Heading>
       <DataTable
         columns={columns}
         data={data?.providers ?? []}
         errorMessage={<ErrorAlert error={error} />}
         initialState={tableURLState}
-        modelName="Provider"
+        modelName={translate("common:admin.Providers")}
         onStateChange={setTableURLState}
         total={data?.total_entries}
       />
diff --git 
a/airflow-core/src/airflow/ui/src/pages/Variables/DeleteVariablesButton.tsx 
b/airflow-core/src/airflow/ui/src/pages/Variables/DeleteVariablesButton.tsx
index dfb1f7d20cb..628806a4745 100644
--- a/airflow-core/src/airflow/ui/src/pages/Variables/DeleteVariablesButton.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Variables/DeleteVariablesButton.tsx
@@ -17,6 +17,7 @@
  * under the License.
  */
 import { Flex, useDisclosure, Text, VStack, Heading, Code } from 
"@chakra-ui/react";
+import { useTranslation } from "react-i18next";
 import { FiTrash, FiTrash2 } from "react-icons/fi";
 
 import { ErrorAlert } from "src/components/ErrorAlert";
@@ -29,6 +30,7 @@ type Props = {
 };
 
 const DeleteVariablesButton = ({ clearSelections, deleteKeys: variableKeys }: 
Props) => {
+  const { t: translate } = useTranslation("admin");
   const { onClose, onOpen, open } = useDisclosure();
   const { error, isPending, mutate } = useBulkDeleteVariables({ 
clearSelections, onSuccessConfirm: onClose });
 
@@ -42,32 +44,32 @@ const DeleteVariablesButton = ({ clearSelections, 
deleteKeys: variableKeys }: Pr
         variant="outline"
       >
         <FiTrash2 />
-        Delete
+        {translate("deleteActions.button")}
       </Button>
 
       <Dialog.Root onOpenChange={onClose} open={open} size="xl">
         <Dialog.Content backdrop>
           <Dialog.Header>
             <VStack align="start" gap={4}>
-              <Heading size="xl">Delete Variable{variableKeys.length > 1 ? "s" 
: ""}</Heading>
+              <Heading size="xl">
+                {translate("variables.delete.deleteVariable", {
+                  count: variableKeys.length,
+                })}
+              </Heading>
             </VStack>
           </Dialog.Header>
 
           <Dialog.CloseTrigger />
-
           <Dialog.Body width="full">
             <Text color="gray.solid" fontSize="md" fontWeight="semibold" 
mb={4}>
-              You are about to delete{" "}
-              <strong>
-                {variableKeys.length} variable{variableKeys.length > 1 ? "s" : 
""}.
-              </strong>
+              {translate("variables.delete.firstConfirmMessage", { count: 
variableKeys.length })}
               <br />
               <Code mb={2} mt={2} p={4}>
                 {variableKeys.join(", ")}
               </Code>
               <br />
-              This action is permanent and cannot be undone.{" "}
-              <strong>Are you sure you want to proceed?</strong>
+              {translate("deleteActions.modal.secondConfirmMessage")}
+              
<strong>{translate("deleteActions.modal.thirdConfirmMessage")}</strong>
             </Text>
             <ErrorAlert error={error} />
             <Flex justifyContent="end" mt={3}>
@@ -88,7 +90,7 @@ const DeleteVariablesButton = ({ clearSelections, deleteKeys: 
variableKeys }: Pr
                   });
                 }}
               >
-                <FiTrash /> <Text fontWeight="bold">Yes, Delete</Text>
+                <FiTrash /> <Text 
fontWeight="bold">{translate("deleteActions.modal.confirmButton")}</Text>
               </Button>
             </Flex>
           </Dialog.Body>
diff --git 
a/airflow-core/src/airflow/ui/src/pages/Variables/ImportVariablesButton.tsx 
b/airflow-core/src/airflow/ui/src/pages/Variables/ImportVariablesButton.tsx
index 4f23d32d772..8c9275602a8 100644
--- a/airflow-core/src/airflow/ui/src/pages/Variables/ImportVariablesButton.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Variables/ImportVariablesButton.tsx
@@ -17,6 +17,7 @@
  * under the License.
  */
 import { Heading, useDisclosure, VStack } from "@chakra-ui/react";
+import { useTranslation } from "react-i18next";
 import { FiUploadCloud } from "react-icons/fi";
 
 import { Button, Dialog } from "src/components/ui";
@@ -28,19 +29,20 @@ type Props = {
 };
 
 const ImportVariablesButton = ({ disabled }: Props) => {
+  const { t: translate } = useTranslation("admin");
   const { onClose, onOpen, open } = useDisclosure();
 
   return (
     <>
       <Button colorPalette="blue" disabled={disabled} onClick={onOpen}>
-        <FiUploadCloud /> Import Variables
+        <FiUploadCloud /> {translate("variables.import.title")}
       </Button>
 
       <Dialog.Root onOpenChange={onClose} open={open} size="xl">
         <Dialog.Content backdrop>
           <Dialog.Header>
             <VStack align="start" gap={4}>
-              <Heading size="xl"> Import Variables </Heading>
+              <Heading size="xl"> {translate("variables.import.title")} 
</Heading>
             </VStack>
           </Dialog.Header>
 
diff --git 
a/airflow-core/src/airflow/ui/src/pages/Variables/ImportVariablesForm.tsx 
b/airflow-core/src/airflow/ui/src/pages/Variables/ImportVariablesForm.tsx
index 37111f88a6d..87713f4c5eb 100644
--- a/airflow-core/src/airflow/ui/src/pages/Variables/ImportVariablesForm.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Variables/ImportVariablesForm.tsx
@@ -17,7 +17,9 @@
  * under the License.
  */
 import { Box, Center, HStack, Spinner } from "@chakra-ui/react";
+import type { TFunction } from "i18next";
 import { useState } from "react";
+import { useTranslation } from "react-i18next";
 import { FiUploadCloud } from "react-icons/fi";
 import { LuFileUp } from "react-icons/lu";
 
@@ -33,25 +35,26 @@ type ImportVariablesFormProps = {
   readonly onClose: () => void;
 };
 
-const actionIfExistsOptions = [
+const actionIfExistsOptions = (translate: TFunction) => [
   {
-    description: "Fails the import if any existing variables are detected.",
-    title: "Fail",
+    description: translate("variables.import.options.fail.description"),
+    title: translate("variables.import.options.fail.title"),
     value: "fail",
   },
   {
-    description: "Overwrites the variable in case of a conflict.",
-    title: "Overwrite",
+    description: translate("variables.import.options.overwrite.description"),
+    title: translate("variables.import.options.overwrite.title"),
     value: "overwrite",
   },
   {
-    description: "Skips importing variables that already exist.",
-    title: "Skip",
+    description: translate("variables.import.options.skip.description"),
+    title: translate("variables.import.options.skip.title"),
     value: "skip",
   },
 ];
 
 const ImportVariablesForm = ({ onClose }: ImportVariablesFormProps) => {
+  const { t: translate } = useTranslation("admin");
   const { error, isPending, mutate, setError } = useImportVariables({
     onSuccessConfirm: onClose,
   });
@@ -73,8 +76,7 @@ const ImportVariablesForm = ({ onClose }: 
ImportVariablesFormProps) => {
       } catch {
         setError({
           body: {
-            detail:
-              'Error Parsing JSON File: Upload a JSON file containing 
variables (e.g., {"key": "value", ...}).',
+            detail: translate("variables.import.errorParsingJsonFile"),
           },
         });
         setFileContent(undefined);
@@ -125,7 +127,7 @@ const ImportVariablesForm = ({ onClose }: 
ImportVariablesFormProps) => {
         required
       >
         <FileUpload.Label fontSize="md" mb={3}>
-          Upload a JSON File{" "}
+          {translate("variables.import.upload")}
         </FileUpload.Label>
         <InputGroup
           endElement={
@@ -148,7 +150,7 @@ const ImportVariablesForm = ({ onClose }: 
ImportVariablesFormProps) => {
           startElement={<LuFileUp />}
           w="full"
         >
-          <FileInput placeholder='Upload a JSON file containing variables 
(e.g., {"key": "value", ...})' />
+          <FileInput 
placeholder={translate("variables.import.uploadPlaceholder")} />
         </InputGroup>
         {isParsing ? (
           <Center mt={2}>
@@ -166,10 +168,10 @@ const ImportVariablesForm = ({ onClose }: 
ImportVariablesFormProps) => {
         }}
       >
         <RadioCardLabel fontSize="md" mb={3}>
-          Select Variable Conflict Resolution
+          {translate("variables.import.conflictResolution")}
         </RadioCardLabel>
         <HStack align="stretch">
-          {actionIfExistsOptions.map((item) => (
+          {actionIfExistsOptions(translate).map((item) => (
             <RadioCardItem
               description={item.description}
               key={item.value}
@@ -189,7 +191,7 @@ const ImportVariablesForm = ({ onClose }: 
ImportVariablesFormProps) => {
           </Box>
         ) : undefined}
         <Button colorPalette="blue" disabled={!Boolean(fileContent) || 
isPending} onClick={onSubmit}>
-          <FiUploadCloud /> Import
+          <FiUploadCloud /> {translate("variables.import.button")}
         </Button>
       </Box>
     </>
diff --git 
a/airflow-core/src/airflow/ui/src/pages/Variables/ManageVariable/AddVariableButton.tsx
 
b/airflow-core/src/airflow/ui/src/pages/Variables/ManageVariable/AddVariableButton.tsx
index c3b3c3a5519..8ffb8a45f80 100644
--- 
a/airflow-core/src/airflow/ui/src/pages/Variables/ManageVariable/AddVariableButton.tsx
+++ 
b/airflow-core/src/airflow/ui/src/pages/Variables/ManageVariable/AddVariableButton.tsx
@@ -17,6 +17,7 @@
  * under the License.
  */
 import { Heading, useDisclosure } from "@chakra-ui/react";
+import { useTranslation } from "react-i18next";
 import { FiPlusCircle } from "react-icons/fi";
 
 import { Button, Dialog, Toaster } from "src/components/ui";
@@ -29,6 +30,7 @@ type Props = {
 };
 
 const AddVariableButton = ({ disabled }: Props) => {
+  const { t: translate } = useTranslation("admin");
   const { onClose, onOpen, open } = useDisclosure();
   const { addVariable, error, isPending, setError } = useAddVariable({
     onSuccessConfirm: onClose,
@@ -49,13 +51,13 @@ const AddVariableButton = ({ disabled }: Props) => {
     <>
       <Toaster />
       <Button colorPalette="blue" disabled={disabled} onClick={onOpen}>
-        <FiPlusCircle /> Add Variable
+        <FiPlusCircle /> {translate("variables.add")}
       </Button>
 
       <Dialog.Root onOpenChange={handleClose} open={open} size="xl">
         <Dialog.Content backdrop>
           <Dialog.Header>
-            <Heading size="xl">Add Variable</Heading>
+            <Heading size="xl">{translate("variables.add")}</Heading>
           </Dialog.Header>
 
           <Dialog.CloseTrigger />
diff --git 
a/airflow-core/src/airflow/ui/src/pages/Variables/ManageVariable/DeleteVariableButton.tsx
 
b/airflow-core/src/airflow/ui/src/pages/Variables/ManageVariable/DeleteVariableButton.tsx
index fab939d73cc..9445bca6a5a 100644
--- 
a/airflow-core/src/airflow/ui/src/pages/Variables/ManageVariable/DeleteVariableButton.tsx
+++ 
b/airflow-core/src/airflow/ui/src/pages/Variables/ManageVariable/DeleteVariableButton.tsx
@@ -16,7 +16,8 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Flex, useDisclosure, Text, VStack, Heading } from "@chakra-ui/react";
+import { Flex, useDisclosure, Text, VStack, Heading, Code } from 
"@chakra-ui/react";
+import { useTranslation } from "react-i18next";
 import { FiTrash } from "react-icons/fi";
 
 import { Button, Dialog } from "src/components/ui";
@@ -29,6 +30,7 @@ type Props = {
 };
 
 const DeleteVariableButton = ({ deleteKey: variableKey, disabled }: Props) => {
+  const { t: translate } = useTranslation("admin");
   const { onClose, onOpen, open } = useDisclosure();
   const { isPending, mutate } = useDeleteVariable({
     onSuccessConfirm: onClose,
@@ -37,13 +39,13 @@ const DeleteVariableButton = ({ deleteKey: variableKey, 
disabled }: Props) => {
   return (
     <>
       <ActionButton
-        actionName="Delete Variable"
+        actionName={translate("variables.delete.title")}
         disabled={disabled}
         icon={<FiTrash />}
         onClick={() => {
           onOpen();
         }}
-        text="Delete Variable"
+        text={translate("variables.delete.title")}
         withText={false}
       />
 
@@ -51,7 +53,7 @@ const DeleteVariableButton = ({ deleteKey: variableKey, 
disabled }: Props) => {
         <Dialog.Content backdrop>
           <Dialog.Header>
             <VStack align="start" gap={4}>
-              <Heading size="xl">Delete Variable</Heading>
+              <Heading size="xl">{translate("variables.delete.deleteVariable", 
{ count: 1 })}</Heading>
             </VStack>
           </Dialog.Header>
 
@@ -59,10 +61,14 @@ const DeleteVariableButton = ({ deleteKey: variableKey, 
disabled }: Props) => {
 
           <Dialog.Body width="full">
             <Text color="gray.solid" fontSize="md" fontWeight="semibold" 
mb={4}>
-              You are about to delete variable with key 
<strong>{variableKey}</strong>.
+              {translate("variables.delete.firstConfirmMessage_one")}
               <br />
-              This action is permanent and cannot be undone.{" "}
-              <strong>Are you sure you want to proceed?</strong>
+              <Code mb={2} mt={2} p={4}>
+                {variableKey}
+              </Code>
+              <br />
+              {translate("deleteActions.modal.secondConfirmMessage")}
+              
<strong>{translate("deleteActions.modal.thirdConfirmMessage")}</strong>
             </Text>
             <Flex justifyContent="end" mt={3}>
               <Button
@@ -74,7 +80,7 @@ const DeleteVariableButton = ({ deleteKey: variableKey, 
disabled }: Props) => {
                   });
                 }}
               >
-                <FiTrash /> <Text fontWeight="bold">Yes, Delete</Text>
+                <FiTrash /> <Text 
fontWeight="bold">{translate("deleteActions.modal.confirmButton")}</Text>
               </Button>
             </Flex>
           </Dialog.Body>
diff --git 
a/airflow-core/src/airflow/ui/src/pages/Variables/ManageVariable/EditVariableButton.tsx
 
b/airflow-core/src/airflow/ui/src/pages/Variables/ManageVariable/EditVariableButton.tsx
index 5138cefb6fe..4310a2f92ff 100644
--- 
a/airflow-core/src/airflow/ui/src/pages/Variables/ManageVariable/EditVariableButton.tsx
+++ 
b/airflow-core/src/airflow/ui/src/pages/Variables/ManageVariable/EditVariableButton.tsx
@@ -17,6 +17,7 @@
  * under the License.
  */
 import { Heading, useDisclosure } from "@chakra-ui/react";
+import { useTranslation } from "react-i18next";
 import { FiEdit } from "react-icons/fi";
 
 import type { VariableResponse } from "openapi/requests/types.gen";
@@ -33,6 +34,7 @@ type Props = {
 };
 
 const EditVariableButton = ({ disabled, variable }: Props) => {
+  const { t: translate } = useTranslation("admin");
   const { onClose, onOpen, open } = useDisclosure();
   const initialVariableValue: VariableBody = {
     description: variable.description ?? "",
@@ -51,20 +53,20 @@ const EditVariableButton = ({ disabled, variable }: Props) 
=> {
   return (
     <>
       <ActionButton
-        actionName="Edit Variable"
+        actionName={translate("variables.edit")}
         disabled={disabled}
         icon={<FiEdit />}
         onClick={() => {
           onOpen();
         }}
-        text="Edit Variable"
+        text={translate("variables.edit")}
         withText={false}
       />
 
       <Dialog.Root onOpenChange={handleClose} open={open} size="xl">
         <Dialog.Content backdrop>
           <Dialog.Header>
-            <Heading size="xl">Edit Variable</Heading>
+            <Heading size="xl">{translate("variables.edit")}</Heading>
           </Dialog.Header>
 
           <Dialog.CloseTrigger />
diff --git 
a/airflow-core/src/airflow/ui/src/pages/Variables/ManageVariable/VariableForm.tsx
 
b/airflow-core/src/airflow/ui/src/pages/Variables/ManageVariable/VariableForm.tsx
index 2b7c65e760e..63ab6bb4c24 100644
--- 
a/airflow-core/src/airflow/ui/src/pages/Variables/ManageVariable/VariableForm.tsx
+++ 
b/airflow-core/src/airflow/ui/src/pages/Variables/ManageVariable/VariableForm.tsx
@@ -18,6 +18,7 @@
  */
 import { Box, Field, HStack, Input, Spacer, Textarea, Text } from 
"@chakra-ui/react";
 import { Controller, useForm } from "react-hook-form";
+import { useTranslation } from "react-i18next";
 import { FiSave } from "react-icons/fi";
 
 import { ErrorAlert } from "src/components/ErrorAlert";
@@ -48,6 +49,7 @@ type VariableFormProps = {
 };
 
 const VariableForm = ({ error, initialVariable, isPending, manageMutate, 
setError }: VariableFormProps) => {
+  const { t: translate } = useTranslation("admin");
   const {
     control,
     formState: { isDirty, isValid },
@@ -75,15 +77,15 @@ const VariableForm = ({ error, initialVariable, isPending, 
manageMutate, setErro
         render={({ field, fieldState }) => (
           <Field.Root invalid={Boolean(fieldState.error)} required>
             <Field.Label fontSize="md">
-              Key <Field.RequiredIndicator />
+              {translate("columns.key")} <Field.RequiredIndicator />
             </Field.Label>
             <Input {...field} disabled={Boolean(initialVariable.key)} required 
size="sm" />
             {fieldState.error ? 
<Field.ErrorText>{fieldState.error.message}</Field.ErrorText> : undefined}
           </Field.Root>
         )}
         rules={{
-          required: "Key is required",
-          validate: (_value) => _value.length <= 250 || "Key can contain a 
maximum of 250 characters",
+          required: translate("variables.form.keyRequired"),
+          validate: (_value) => _value.length <= 250 || 
translate("variables.form.keyMaxLength"),
         }}
       />
 
@@ -97,12 +99,12 @@ const VariableForm = ({ error, initialVariable, isPending, 
manageMutate, setErro
           return (
             <Field.Root invalid={Boolean(fieldState.error)} mt={4} required>
               <Field.Label fontSize="md">
-                Value <Field.RequiredIndicator />
+                {translate("columns.value")} <Field.RequiredIndicator />
               </Field.Label>
               <Textarea {...field} size="sm" />
               {showJsonWarning ? (
                 <Text color="fg.warning" fontSize="xs">
-                  Invalid JSON
+                  {translate("variables.form.invalidJson")}
                 </Text>
               ) : undefined}
               {fieldState.error ? 
<Field.ErrorText>{fieldState.error.message}</Field.ErrorText> : undefined}
@@ -110,7 +112,7 @@ const VariableForm = ({ error, initialVariable, isPending, 
manageMutate, setErro
           );
         }}
         rules={{
-          required: "Value is required",
+          required: translate("variables.form.valueRequired"),
         }}
       />
 
@@ -119,7 +121,7 @@ const VariableForm = ({ error, initialVariable, isPending, 
manageMutate, setErro
         name="description"
         render={({ field }) => (
           <Field.Root mb={4} mt={4}>
-            <Field.Label fontSize="md">Description</Field.Label>
+            <Field.Label 
fontSize="md">{translate("columns.description")}</Field.Label>
             <Textarea {...field} size="sm" />
           </Field.Root>
         )}
@@ -131,7 +133,7 @@ const VariableForm = ({ error, initialVariable, isPending, 
manageMutate, setErro
         <HStack w="full">
           {isDirty ? (
             <Button onClick={handleReset} variant="outline">
-              Reset
+              {translate("formActions.reset")}
             </Button>
           ) : undefined}
           <Spacer />
@@ -140,7 +142,7 @@ const VariableForm = ({ error, initialVariable, isPending, 
manageMutate, setErro
             disabled={!isValid || isPending}
             onClick={() => void handleSubmit(onSubmit)()}
           >
-            <FiSave /> Save
+            <FiSave /> {translate("formActions.save")}
           </Button>
         </HStack>
       </Box>
diff --git a/airflow-core/src/airflow/ui/src/pages/Variables/Variables.tsx 
b/airflow-core/src/airflow/ui/src/pages/Variables/Variables.tsx
index d7c4256f2c1..10cd89138bf 100644
--- a/airflow-core/src/airflow/ui/src/pages/Variables/Variables.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Variables/Variables.tsx
@@ -18,7 +18,9 @@
  */
 import { Box, Flex, HStack, Spacer, VStack } from "@chakra-ui/react";
 import type { ColumnDef } from "@tanstack/react-table";
+import type { TFunction } from "i18next";
 import { useEffect, useMemo, useState } from "react";
+import { useTranslation } from "react-i18next";
 import { FiShare } from "react-icons/fi";
 import { useSearchParams } from "react-router-dom";
 
@@ -47,7 +49,8 @@ const getColumns = ({
   onRowSelect,
   onSelectAll,
   selectedRows,
-}: GetColumnsParams): Array<ColumnDef<VariableResponse>> => [
+  translate,
+}: { translate: TFunction } & GetColumnsParams): 
Array<ColumnDef<VariableResponse>> => [
   {
     accessorKey: "select",
     cell: ({ row }) => (
@@ -75,21 +78,21 @@ const getColumns = ({
   {
     accessorKey: "key",
     cell: ({ row }) => <TrimText isClickable onClickContent={row.original} 
text={row.original.key} />,
-    header: "Key",
+    header: translate("columns.key"),
   },
   {
     accessorKey: "value",
     cell: ({ row }) => <TrimText showTooltip text={row.original.value} />,
-    header: "Value",
+    header: translate("columns.value"),
   },
   {
     accessorKey: "description",
     cell: ({ row }) => <TrimText showTooltip text={row.original.description} 
/>,
-    header: "Description",
+    header: translate("columns.description"),
   },
   {
     accessorKey: "is_encrypted",
-    header: "Is Encrypted",
+    header: translate("variables.columns.isEncrypted"),
   },
   {
     accessorKey: "actions",
@@ -108,6 +111,7 @@ const getColumns = ({
 ];
 
 export const Variables = () => {
+  const { t: translate } = useTranslation("admin");
   const { setTableURLState, tableURLState } = useTableURLState({
     pagination: { pageIndex: 0, pageSize: 30 },
     sorting: [{ desc: false, id: "key" }],
@@ -142,8 +146,9 @@ export const Variables = () => {
         onRowSelect: handleRowSelect,
         onSelectAll: handleSelectAll,
         selectedRows,
+        translate,
       }),
-    [allRowsSelected, handleRowSelect, handleSelectAll, selectedRows],
+    [allRowsSelected, handleRowSelect, handleSelectAll, selectedRows, 
translate],
   );
 
   const handleSearchChange = (value: string) => {
@@ -190,7 +195,7 @@ export const Variables = () => {
           buttonProps={{ disabled: true }}
           defaultValue={variableKeyPattern ?? ""}
           onChange={handleSearchChange}
-          placeHolder="Search Keys"
+          placeHolder={translate("variables.searchPlaceholder")}
         />
         <HStack gap={4} mt={2}>
           <ImportVariablesButton disabled={selectedRows.size > 0} />
@@ -206,14 +211,17 @@ export const Variables = () => {
           initialState={tableURLState}
           isFetching={isFetching}
           isLoading={isLoading}
-          modelName="Variable"
+          modelName={translate("common:admin.Variables")}
+          noRowsMessage={translate("variables.noRowsMessage")}
           onStateChange={setTableURLState}
           total={data?.total_entries ?? 0}
         />
       </Box>
       <ActionBar.Root closeOnInteractOutside={false} 
open={Boolean(selectedRows.size)}>
         <ActionBar.Content>
-          <ActionBar.SelectionTrigger>{selectedRows.size} 
selected</ActionBar.SelectionTrigger>
+          <ActionBar.SelectionTrigger>
+            {selectedRows.size} {translate("deleteActions.selected")}
+          </ActionBar.SelectionTrigger>
           <ActionBar.Separator />
           <Tooltip content="Delete selected variables">
             <DeleteVariablesButton clearSelections={clearSelections} 
deleteKeys={[...selectedRows.keys()]} />
@@ -221,7 +229,7 @@ export const Variables = () => {
           <Tooltip content="Export selected variables">
             <Button onClick={() => downloadJson(selectedVariables, 
"variables")} size="sm" variant="outline">
               <FiShare />
-              Export
+              {translate("variables.export")}
             </Button>
           </Tooltip>
           <ActionBar.CloseTrigger onClick={clearSelections} />
diff --git a/airflow-core/src/airflow/ui/src/pages/XCom/XCom.tsx 
b/airflow-core/src/airflow/ui/src/pages/XCom/XCom.tsx
index 43f1e3d17c3..1fe894d3edf 100644
--- a/airflow-core/src/airflow/ui/src/pages/XCom/XCom.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/XCom/XCom.tsx
@@ -18,6 +18,7 @@
  */
 import { Box, Link } from "@chakra-ui/react";
 import type { ColumnDef } from "@tanstack/react-table";
+import { useTranslation } from "react-i18next";
 import { Link as RouterLink, useParams } from "react-router-dom";
 
 import { useXcomServiceGetXcomEntries } from "openapi/queries";
@@ -30,11 +31,11 @@ import { getTaskInstanceLinkFromObj } from 
"src/utils/links";
 
 import { XComEntry } from "./XComEntry";
 
-const columns: Array<ColumnDef<XComResponse>> = [
+const columns = (translate: (key: string) => string): 
Array<ColumnDef<XComResponse>> => [
   {
     accessorKey: "key",
     enableSorting: false,
-    header: "Key",
+    header: translate("xcom.columns.key"),
   },
   {
     accessorKey: "dag_id",
@@ -44,7 +45,7 @@ const columns: Array<ColumnDef<XComResponse>> = [
       </Link>
     ),
     enableSorting: false,
-    header: "Dag",
+    header: translate("xcom.columns.dag"),
   },
   {
     accessorKey: "run_id",
@@ -56,7 +57,7 @@ const columns: Array<ColumnDef<XComResponse>> = [
       </Link>
     ),
     enableSorting: false,
-    header: "Run Id",
+    header: translate("common:runId"),
   },
   {
     accessorKey: "task_id",
@@ -75,12 +76,12 @@ const columns: Array<ColumnDef<XComResponse>> = [
       </Link>
     ),
     enableSorting: false,
-    header: "Task ID",
+    header: translate("common:taskId"),
   },
   {
     accessorKey: "map_index",
     enableSorting: false,
-    header: "Map Index",
+    header: translate("common:mapIndex"),
   },
   {
     cell: ({ row: { original } }) => (
@@ -93,13 +94,13 @@ const columns: Array<ColumnDef<XComResponse>> = [
       />
     ),
     enableSorting: false,
-    header: "Value",
+    header: translate("xcom.columns.value"),
   },
 ];
 
 export const XCom = () => {
   const { dagId = "~", mapIndex = "-1", runId = "~", taskId = "~" } = 
useParams();
-
+  const { t: translate } = useTranslation(["browse", "common"]);
   const { setTableURLState, tableURLState } = useTableURLState();
   const { pagination } = tableURLState;
 
@@ -120,7 +121,7 @@ export const XCom = () => {
     <Box>
       <ErrorAlert error={error} />
       <DataTable
-        columns={columns}
+        columns={columns(translate)}
         data={data ? data.xcom_entries : []}
         displayMode="table"
         initialState={tableURLState}

Reply via email to