This is an automated email from the ASF dual-hosted git repository.

potiuk 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 23140992902 Add possibility of removing extra translations missing in 
en (#57060)
23140992902 is described below

commit 2314099290225765f53375891082bf45fd72524f
Author: Jarek Potiuk <[email protected]>
AuthorDate: Wed Oct 22 15:22:35 2025 +0200

    Add possibility of removing extra translations missing in en (#57060)
    
    Sometimes we rename/move translation - we did not have a tool to
    remove such dangling translations. Now we have.
---
 airflow-core/src/airflow/ui/public/i18n/README.md  | 12 ++++
 .../ui/public/i18n/locales/ar/components.json      |  1 -
 .../airflow/ui/public/i18n/locales/ar/dags.json    |  3 +-
 .../airflow/ui/public/i18n/locales/el/common.json  |  1 -
 .../ui/public/i18n/locales/es/components.json      |  1 -
 .../airflow/ui/public/i18n/locales/es/dags.json    |  3 +-
 .../airflow/ui/public/i18n/locales/fr/dags.json    |  3 +-
 .../ui/public/i18n/locales/he/components.json      |  1 -
 .../airflow/ui/public/i18n/locales/he/dags.json    |  3 +-
 .../airflow/ui/public/i18n/locales/hi/common.json  |  3 -
 .../ui/public/i18n/locales/hi/components.json      |  1 -
 .../src/airflow/ui/public/i18n/locales/hi/dag.json |  5 +-
 .../airflow/ui/public/i18n/locales/hi/dags.json    |  3 +-
 .../airflow/ui/public/i18n/locales/hu/common.json  |  2 -
 .../ui/public/i18n/locales/hu/components.json      |  1 -
 .../airflow/ui/public/i18n/locales/hu/dags.json    |  3 +-
 .../ui/public/i18n/locales/it/components.json      |  1 -
 .../airflow/ui/public/i18n/locales/it/dags.json    |  3 +-
 .../ui/public/i18n/locales/nl/components.json      |  1 -
 .../airflow/ui/public/i18n/locales/nl/dags.json    |  3 +-
 .../ui/public/i18n/locales/pt/components.json      |  1 -
 .../airflow/ui/public/i18n/locales/pt/dags.json    |  3 +-
 .../ui/public/i18n/locales/tr/components.json      |  1 -
 .../airflow/ui/public/i18n/locales/tr/dags.json    |  3 +-
 .../ui/public/i18n/locales/zh-CN/components.json   |  1 -
 .../airflow/ui/public/i18n/locales/zh-CN/dags.json |  3 +-
 dev/i18n/check_translations_completeness.py        | 70 +++++++++++++++++++++-
 27 files changed, 93 insertions(+), 43 deletions(-)

diff --git a/airflow-core/src/airflow/ui/public/i18n/README.md 
b/airflow-core/src/airflow/ui/public/i18n/README.md
index 1d1c21f0a2a..e2fe51ff739 100644
--- a/airflow-core/src/airflow/ui/public/i18n/README.md
+++ b/airflow-core/src/airflow/ui/public/i18n/README.md
@@ -331,6 +331,18 @@ Adding missing translations (with `TODO: translate` 
prefix):
 uv run dev/i18n/check_translations_completeness.py --language <language_code> 
--add-missing
 ```
 
+You can also remove extra translations from the language of your choice:
+
+```bash
+uv run dev/i18n/check_translations_completeness.py --language <language_code> 
--remove-extra
+```
+
+Or from all languages:
+
+```bash
+uv run dev/i18n/check_translations_completeness.py --remove-extra
+```
+
 The script is also added as a prek hook (manual) so that it can be run from 
within `prek` and CI:
 
 ```bash
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/ar/components.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/ar/components.json
index 0b1c5d74aa9..df1b9d69d9b 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/ar/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/ar/components.json
@@ -120,7 +120,6 @@
   "limitedList.clickToInteract": "انقر على علامة لتصفية Dags",
   "limitedList.clickToOpenFull": "انقر \"+{{count}} المزيد\" لعرض القائمة 
الكاملة",
   "limitedList.copyPasteText": "يمكنك نسخ ولصق النص أعلاه",
-  "limitedList.showingItems": "عرض {{count}} عنصرًا",
   "logs": {
     "file": "ملف",
     "location": "سطر {{line}} في {{name}}"
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/ar/dags.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/ar/dags.json
index b7f8e60bbd8..12961f79af6 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/ar/dags.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/ar/dags.json
@@ -20,8 +20,7 @@
       "all": "الكل",
       "paused": "متوقف"
     },
-    "runIdPatternFilter": "بحث تشغيلات الDag",
-    "triggeringUserNameFilter": "البحث حسب المستخدم صاحب الاطلاق"
+    "runIdPatternFilter": "بحث تشغيلات الDag"
   },
   "ownerLink": "رابط المالك لـ{{owner}}",
   "runAndTaskActions": {
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/el/common.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/el/common.json
index f3b725d02fd..eddc6a8f5a2 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/el/common.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/el/common.json
@@ -163,7 +163,6 @@
     },
     "tooltip": "Πατήστε {{hotkey}} για κύλιση προς τα {{direction}}"
   },
-  "seconds": "{{count}}δ",
   "security": {
     "actions": "Ενέργειες",
     "permissions": "Δικαιώματα",
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/es/components.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/es/components.json
index 20f31033ee0..ad1edcd1b39 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/es/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/es/components.json
@@ -99,7 +99,6 @@
   "limitedList.clickToInteract": "Haz clic en una etiqueta para filtrar Dags",
   "limitedList.clickToOpenFull": "Haz clic en \"+{{count}} más\" para ver la 
lista completa",
   "limitedList.copyPasteText": "Puedes copiar y pegar el texto de arriba",
-  "limitedList.showingItems": "Mostrando {{count}} elementos",
   "logs": {
     "file": "Archivo",
     "location": "línea {{line}} en {{name}}"
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/es/dags.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/es/dags.json
index 7d93addccfc..353ae56534a 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/es/dags.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/es/dags.json
@@ -20,8 +20,7 @@
       "all": "Todos",
       "paused": "Pausado"
     },
-    "runIdPatternFilter": "Buscar Ejecuciones de Dag",
-    "triggeringUserNameFilter": "Buscar por usuario que activó"
+    "runIdPatternFilter": "Buscar Ejecuciones de Dag"
   },
   "ownerLink": "Enlace de Propietario para {{owner}}",
   "runAndTaskActions": {
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/fr/dags.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/fr/dags.json
index cd6b2c27356..b8a68745b81 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/fr/dags.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/fr/dags.json
@@ -20,8 +20,7 @@
       "all": "Tous",
       "paused": "En pause"
     },
-    "runIdPatternFilter": "Rechercher des exécutions de Dag",
-    "triggeringUserNameFilter": "Rechercher par utilisateur déclencheur"
+    "runIdPatternFilter": "Rechercher des exécutions de Dag"
   },
   "ownerLink": "Lien du propriétaire pour {{owner}}",
   "runAndTaskActions": {
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/he/components.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/he/components.json
index 424d5f675b1..453f3819801 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/he/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/he/components.json
@@ -99,7 +99,6 @@
   "limitedList.clickToInteract": "לחץ על תגית כדי לסנן Dags",
   "limitedList.clickToOpenFull": "לחץ על \"+{{count}} נוספים\" כדי לפתוח את 
התצוגה המלאה",
   "limitedList.copyPasteText": "ניתן להעתיק ולהדביק את הטקסט שמעל",
-  "limitedList.showingItems": "מציג {{count}} פריטים",
   "logs": {
     "file": "קובץ",
     "location": "שורה {{line}} ב{{name}}"
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/he/dags.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/he/dags.json
index 15729c5f1e8..1b3b06d4bf6 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/he/dags.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/he/dags.json
@@ -20,8 +20,7 @@
       "all": "הכל",
       "paused": "מושהה"
     },
-    "runIdPatternFilter": "חפש הרצת Dag",
-    "triggeringUserNameFilter": "חפש לפי שם המשתמש המפעיל"
+    "runIdPatternFilter": "חפש הרצת Dag"
   },
   "ownerLink": "קישור בעלים ל-{{owner}}",
   "runAndTaskActions": {
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/hi/common.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/hi/common.json
index a506b9198b8..1dcef4cb0cc 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/hi/common.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/hi/common.json
@@ -25,7 +25,6 @@
   "dag_other": "डैग्स",
   "dagDetails": {
     "catchup": "पकड़ना",
-    "concurrency": "समानांतरता",
     "dagRunTimeout": "डैग रन टाइमआउट",
     "defaultArgs": "डिफ़ॉल्ट तर्क",
     "description": "विवरण",
@@ -188,8 +187,6 @@
     "up_for_retry": "पुनः प्रयास के लिए",
     "upstream_failed": "अपस्ट्रीम विफल"
   },
-  "switchToDarkMode": "डार्क मोड में स्विच करें",
-  "switchToLightMode": "लाइट मोड में स्विच करें",
   "table": {
     "completedAt": "पर पूर्ण",
     "createdAt": "पर बनाया",
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/hi/components.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/hi/components.json
index 4efe768e9be..d3caf8c34c5 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/hi/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/hi/components.json
@@ -92,7 +92,6 @@
   "limitedList.clickToInteract": "टैग पर क्लिक करके Dags फ़िल्टर करें",
   "limitedList.clickToOpenFull": "\"+{{count}} और\" पर क्लिक करके पूरी सूची 
खोलें",
   "limitedList.copyPasteText": "आप ऊपर दिए गए पाठ को कॉपी और पेस्ट कर सकते 
हैं",
-  "limitedList.showingItems": "{{count}} आइटम दिखाए जा रहे हैं",
   "logs": {
     "file": "फ़ाइल",
     "location": "{{name}} में लाइन {{line}}"
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/hi/dag.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/hi/dag.json
index 253ed958540..36e5d3adfca 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/hi/dag.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/hi/dag.json
@@ -40,7 +40,6 @@
     "warning": "WARNING"
   },
   "navigation": {
-    "jump": "जंप: Shift+{{arrow}}",
     "navigation": "नेवीगेशन: {{arrow}}",
     "toggleGroup": "ग्रुप टॉगल करें: Space"
   },
@@ -64,9 +63,7 @@
   },
   "panel": {
     "buttons": {
-      "options": "विकल्प",
-      "showGraph": "ग्राफ़ दिखाएं",
-      "showGrid": "ग्रिड दिखाएं"
+      "options": "विकल्प"
     },
     "dagRuns": {
       "label": "डैग रन्स की संख्या"
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/hi/dags.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/hi/dags.json
index 54cac115336..74c112d0dfb 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/hi/dags.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/hi/dags.json
@@ -20,8 +20,7 @@
       "all": "सभी",
       "paused": "रोका गया"
     },
-    "runIdPatternFilter": "डैग रन्स खोजें",
-    "triggeringUserNameFilter": "ट्रिगर करने वाले उपयोगकर्ता द्वारा खोजें"
+    "runIdPatternFilter": "डैग रन्स खोजें"
   },
   "ownerLink": "{{owner}} के लिए स्वामी लिंक",
   "runAndTaskActions": {
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/hu/common.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/hu/common.json
index f26a1540f08..084a73f3c44 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/hu/common.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/hu/common.json
@@ -189,8 +189,6 @@
     "up_for_retry": "Újrapróbálkozásra vár",
     "upstream_failed": "Előfeltétel sikertelen"
   },
-  "switchToDarkMode": "Váltás sötét módra",
-  "switchToLightMode": "Váltás világos módra",
   "table": {
     "completedAt": "Befejezve ekkor",
     "createdAt": "Létrehozva ekkor",
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/hu/components.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/hu/components.json
index ded34869e9d..014e8242b43 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/hu/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/hu/components.json
@@ -92,7 +92,6 @@
   "limitedList.clickToInteract": "Kattintson egy címkére a Dag-ok szűréséhez",
   "limitedList.clickToOpenFull": "Kattintson a \"+{{count}} további\" gombra a 
teljes nézethez",
   "limitedList.copyPasteText": "A fenti szöveg másolható és beilleszthető",
-  "limitedList.showingItems": "{{count}} elem megjelenítése",
   "logs": {
     "file": "Fájl",
     "location": "{{name}} fájl {{line}}. sora"
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/hu/dags.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/hu/dags.json
index 93a925c7c4d..6394092f747 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/hu/dags.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/hu/dags.json
@@ -20,8 +20,7 @@
       "all": "Összes",
       "paused": "Szüneteltetett"
     },
-    "runIdPatternFilter": "Dag futások keresése",
-    "triggeringUserNameFilter": "Keresés indító felhasználó alapján"
+    "runIdPatternFilter": "Dag futások keresése"
   },
   "ownerLink": "Tulajdonosi hivatkozás: {{owner}}",
   "runAndTaskActions": {
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/it/components.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/it/components.json
index e8903d951a2..3978d69905b 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/it/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/it/components.json
@@ -106,7 +106,6 @@
   "limitedList.clickToInteract": "Fai clic su un'etichetta per filtrare i Dag",
   "limitedList.clickToOpenFull": "Fai clic su \"+{{count}} altro\" per 
visualizzare tutto",
   "limitedList.copyPasteText": "Puoi copiare e incollare il testo sopra",
-  "limitedList.showingItems": "Visualizzazione di {{count}} elementi",
   "logs": {
     "file": "File",
     "location": "linea {{line}} in {{name}}"
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/it/dags.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/it/dags.json
index 0cb4eac8ac7..6c6ab552ddc 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/it/dags.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/it/dags.json
@@ -20,8 +20,7 @@
       "all": "Tutti",
       "paused": "In Pausa"
     },
-    "runIdPatternFilter": "Cercare Dag Runs",
-    "triggeringUserNameFilter": "Cercare per Utente che ha Attivato"
+    "runIdPatternFilter": "Cercare Dag Runs"
   },
   "ownerLink": "Link dell'Owner per {{owner}}",
   "runAndTaskActions": {
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/nl/components.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/nl/components.json
index 83785a7112a..9997e067172 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/nl/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/nl/components.json
@@ -92,7 +92,6 @@
   "limitedList.clickToInteract": "Klik op een label om Dags te filteren",
   "limitedList.clickToOpenFull": "Klik op \"+{{count}} meer\" om de volledige 
lijst te openen",
   "limitedList.copyPasteText": "Je kunt de bovenstaande tekst kopiëren en 
plakken",
-  "limitedList.showingItems": "{{count}} items weergegeven",
   "logs": {
     "file": "Bestand",
     "location": "regel {{line}} in {{name}}"
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/nl/dags.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/nl/dags.json
index b57b2290a92..23fdb3bc2d4 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/nl/dags.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/nl/dags.json
@@ -20,8 +20,7 @@
       "all": "Alles",
       "paused": "Gepauzeerd"
     },
-    "runIdPatternFilter": "Zoek Dag Runs",
-    "triggeringUserNameFilter": "Zoek op Triggering User"
+    "runIdPatternFilter": "Zoek Dag Runs"
   },
   "ownerLink": "Eigenaarslink voor {{owner}}",
   "runAndTaskActions": {
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/pt/components.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/pt/components.json
index ae83855677a..5b30826d8b7 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/pt/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/pt/components.json
@@ -106,7 +106,6 @@
   "limitedList.clickToInteract": "Clique em uma etiqueta para filtrar os Dags",
   "limitedList.clickToOpenFull": "Clique em \"+{{count}} mais\" para ver a 
lista completa",
   "limitedList.copyPasteText": "Você pode copiar e colar o texto acima",
-  "limitedList.showingItems": "Exibindo {{count}} itens",
   "logs": {
     "file": "Arquivo",
     "location": "linha {{line}} em {{name}}"
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/pt/dags.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/pt/dags.json
index 683cf090a8b..6ac6422c19e 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/pt/dags.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/pt/dags.json
@@ -20,8 +20,7 @@
       "all": "Todos",
       "paused": "Pausado"
     },
-    "runIdPatternFilter": "Pesquisar Execuções de DAG",
-    "triggeringUserNameFilter": "Pesquisar por Usuário que Disparou"
+    "runIdPatternFilter": "Pesquisar Execuções de DAG"
   },
   "ownerLink": "Link do Proprietário para {{owner}}",
   "runAndTaskActions": {
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/tr/components.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/tr/components.json
index 69d80a7672b..0a32afc28b3 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/tr/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/tr/components.json
@@ -92,7 +92,6 @@
   "limitedList.clickToInteract": "Bir etikete tıklayarak Dag'leri filtreleyin",
   "limitedList.clickToOpenFull": "\"+{{count}} daha\" tıklayarak tam görünümü 
açın",
   "limitedList.copyPasteText": "Yukarıdaki metni kopyalayıp 
yapıştırabilirsiniz",
-  "limitedList.showingItems": "{{count}} öğe gösteriliyor",
   "logs": {
     "file": "Dosya",
     "location": "{{name}} içinde satır {{line}}"
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/tr/dags.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/tr/dags.json
index 2974a4d4f48..8c6d0213052 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/tr/dags.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/tr/dags.json
@@ -20,8 +20,7 @@
       "all": "Tümü",
       "paused": "Duraklatılmış"
     },
-    "runIdPatternFilter": "Dag Çalıştırmalarında Ara",
-    "triggeringUserNameFilter": "Tetikleyen Kullanıcıya Göre Ara"
+    "runIdPatternFilter": "Dag Çalıştırmalarında Ara"
   },
   "ownerLink": "{{owner}} için sahip bağlantısı",
   "runAndTaskActions": {
diff --git 
a/airflow-core/src/airflow/ui/public/i18n/locales/zh-CN/components.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/zh-CN/components.json
index e7255110e8f..652011da2be 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/zh-CN/components.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/zh-CN/components.json
@@ -90,7 +90,6 @@
   "limitedList.clickToInteract": "点击标签以筛选 DAGs",
   "limitedList.clickToOpenFull": "点击 \"+{{count}} 更多\" 打开完整视图",
   "limitedList.copyPasteText": "你可以复制并粘贴上方文本",
-  "limitedList.showingItems": "显示 {{count}} 项",
   "logs": {
     "file": "文件",
     "location": "第 {{line}} 行,位于 {{name}}"
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/zh-CN/dags.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/zh-CN/dags.json
index b8e4f0929d4..90ba4ff9588 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/zh-CN/dags.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/zh-CN/dags.json
@@ -20,8 +20,7 @@
       "all": "全部",
       "paused": "暂停"
     },
-    "runIdPatternFilter": "搜索 Dag 执行",
-    "triggeringUserNameFilter": "搜索触发用户名称"
+    "runIdPatternFilter": "搜索 Dag 执行"
   },
   "ownerLink": "拥有者 {{owner}} 的地址",
   "runAndTaskActions": {
diff --git a/dev/i18n/check_translations_completeness.py 
b/dev/i18n/check_translations_completeness.py
index e3c2e0d8418..5972087b9ff 100755
--- a/dev/i18n/check_translations_completeness.py
+++ b/dev/i18n/check_translations_completeness.py
@@ -458,7 +458,13 @@ def print_translation_progress(console, locale_files, 
missing_counts, summary):
     default=False,
     help="Add missing translations for all languages except English, prefixed 
with 'TODO: translate:'.",
 )
-def cli(language: str | None = None, add_missing: bool = False):
[email protected](
+    "--remove-extra",
+    is_flag=True,
+    default=False,
+    help="Remove extra translations that are present in the language but 
missing in English.",
+)
+def cli(language: str | None = None, add_missing: bool = False, remove_extra: 
bool = False):
     locale_files = get_locale_files()
     console = Console(force_terminal=True, color_system="auto")
     print_locale_file_table(locale_files, console, language)
@@ -481,6 +487,22 @@ def cli(language: str | None = None, add_missing: bool = 
False):
             add_missing_translations(lf.locale, filtered_summary, console)
         # After adding, re-run the summary for all languages
         summary, missing_counts = compare_keys(get_locale_files(), console)
+    if remove_extra and language != "en":
+        # Loop through all languages except 'en' and remove extra translations
+        if language:
+            language_files = [lf for lf in locale_files if lf.locale == 
language]
+        else:
+            language_files = [lf for lf in locale_files if lf.locale != "en"]
+        for lf in language_files:
+            filtered_summary = {}
+            for filename, diff in summary.items():
+                filtered_summary[filename] = LocaleSummary(
+                    missing_keys={lf.locale: diff.missing_keys.get(lf.locale, 
[])},
+                    extra_keys={lf.locale: diff.extra_keys.get(lf.locale, [])},
+                )
+            remove_extra_translations(lf.locale, filtered_summary, console)
+        # After removing, re-run the summary for all languages
+        summary, missing_counts = compare_keys(get_locale_files(), console)
     if language:
         locales = [lf.locale for lf in locale_files]
         if language not in locales:
@@ -594,5 +616,51 @@ def add_missing_translations(language: str, summary: 
dict[str, LocaleSummary], c
         console.print(f"[green]Added missing translations to 
{lang_path}[/green]")
 
 
+def remove_extra_translations(language: str, summary: dict[str, 
LocaleSummary], console: Console):
+    """
+    Remove extra translations for the selected language.
+
+    Removes keys that are present in the language file but missing in the 
English file.
+    """
+    for filename, diff in summary.items():
+        extra_keys = set(diff.extra_keys.get(language, []))
+        if not extra_keys:
+            continue
+        lang_path = LOCALES_DIR / language / filename
+        try:
+            lang_data = load_json(lang_path)
+        except Exception as e:
+            console.print(f"[yellow]Failed to load {language} file 
{lang_path}: {e}[/yellow]")
+            continue
+
+        # Helper to recursively remove extra keys
+        def remove_keys(dst, prefix=""):
+            keys_to_remove = []
+            for k, v in list(dst.items()):
+                full_key = f"{prefix}.{k}" if prefix else k
+                if full_key in extra_keys:
+                    keys_to_remove.append(k)
+                elif isinstance(v, dict):
+                    remove_keys(v, full_key)
+                    # Remove empty dictionaries after recursion
+                    if not v:
+                        keys_to_remove.append(k)
+            for k in keys_to_remove:
+                del dst[k]
+
+        remove_keys(lang_data)
+
+        def natural_key_sort(obj):
+            if isinstance(obj, dict):
+                return {k: natural_key_sort(obj[k]) for k in sorted(obj)}
+            return obj
+
+        lang_data = natural_key_sort(lang_data)
+        with open(lang_path, "w", encoding="utf-8") as f:
+            json.dump(lang_data, f, ensure_ascii=False, indent=2)
+            f.write("\n")  # Ensure newline at the end of the file
+        console.print(f"[green]Removed {len(extra_keys)} extra translations 
from {lang_path}[/green]")
+
+
 if __name__ == "__main__":
     cli()

Reply via email to