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 2c02285ae9b Add translation completeness lint (#51166)
2c02285ae9b is described below
commit 2c02285ae9b9586ecc32e93653be186519db1490
Author: Guan Ming(Wesley) Chiu <[email protected]>
AuthorDate: Thu May 29 23:45:12 2025 +0800
Add translation completeness lint (#51166)
---
airflow-core/src/airflow/ui/eslint.config.js | 2 +
airflow-core/src/airflow/ui/rules/i18n.js | 167 +++++++++++++++++++++
.../src/airflow/ui/src/i18n/locales/de/common.json | 128 ++++++++--------
.../airflow/ui/src/i18n/locales/de/dashboard.json | 34 ++---
.../src/airflow/ui/src/i18n/locales/en/common.json | 130 ++++++++--------
.../airflow/ui/src/i18n/locales/en/dashboard.json | 34 ++---
.../src/airflow/ui/src/i18n/locales/ko/common.json | 102 ++++++-------
.../airflow/ui/src/i18n/locales/ko/dashboard.json | 34 ++---
.../src/airflow/ui/src/i18n/locales/nl/common.json | 102 ++++++-------
.../airflow/ui/src/i18n/locales/nl/dashboard.json | 34 ++---
.../airflow/ui/src/i18n/locales/zh-TW/common.json | 86 +++++------
.../ui/src/i18n/locales/zh-TW/dashboard.json | 28 ++--
12 files changed, 525 insertions(+), 356 deletions(-)
diff --git a/airflow-core/src/airflow/ui/eslint.config.js
b/airflow-core/src/airflow/ui/eslint.config.js
index e6fc770f1f7..e9edfa5ace7 100644
--- a/airflow-core/src/airflow/ui/eslint.config.js
+++ b/airflow-core/src/airflow/ui/eslint.config.js
@@ -21,6 +21,7 @@
* @import { FlatConfig } from "@typescript-eslint/utils/ts-eslint";
*/
import { coreRules } from "./rules/core.js";
+import { i18nRules } from "./rules/i18n.js";
import { i18nextRules } from "./rules/i18next.js";
import { perfectionistRules } from "./rules/perfectionist.js";
import { prettierRules } from "./rules/prettier.js";
@@ -46,4 +47,5 @@ export default /** @type {const} @satisfies
{ReadonlyArray<FlatConfig.Config>} *
stylisticRules,
unicornRules,
i18nextRules,
+ i18nRules,
]);
diff --git a/airflow-core/src/airflow/ui/rules/i18n.js
b/airflow-core/src/airflow/ui/rules/i18n.js
new file mode 100644
index 00000000000..f96e71b37b7
--- /dev/null
+++ b/airflow-core/src/airflow/ui/rules/i18n.js
@@ -0,0 +1,167 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+import fs from "node:fs";
+import path from "node:path";
+import { fileURLToPath } from "node:url";
+
+export const i18nNamespace = "i18n";
+
+/**
+ * Extract all nested keys from translation object
+ * @param {Record<string, any>} obj
+ * @param {string} [prefix]
+ * @returns {string[]}
+ */
+const getKeys = (obj, prefix = "") => {
+ if (Array.isArray(obj)) {
+ return [];
+ }
+
+ return Object.keys(obj).flatMap((key) => {
+ const newPrefix = prefix ? `${prefix}.${key}` : key;
+ const value = obj[key];
+
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
+ return [newPrefix, ...getKeys(value, newPrefix)];
+ }
+
+ return [newPrefix];
+ });
+};
+
+// Path to locales directory
+const localesDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)),
"../src/i18n/locales");
+
+// Default language (English) as reference
+const defaultLanguage = "en";
+const defaultLanguageKeys = /** @type {Record<string, string[]>} */ ({});
+const defaultLanguageDir = path.join(localesDir, defaultLanguage);
+
+// Load translation keys from default language files
+fs.readdirSync(defaultLanguageDir)
+ .filter((file) => file.endsWith(".json"))
+ .forEach((jsonFile) => {
+ const ns = path.basename(jsonFile, ".json");
+ const filePath = path.join(defaultLanguageDir, jsonFile);
+ const fileContent = fs.readFileSync(filePath, "utf8");
+ const parsedJson = JSON.parse(fileContent);
+
+ if (typeof parsedJson === "object" && parsedJson !== null &&
!Array.isArray(parsedJson)) {
+ defaultLanguageKeys[ns] = getKeys(parsedJson);
+ }
+ });
+
+export const i18nPlugin = {
+ files: ["**/i18n/locales/**/*.json"],
+ rules: {
+ "check-translation-completeness": {
+ /** @param
{import('@typescript-eslint/utils').TSESLint.RuleContext<'missingKeys' |
'fileError', []>} context */
+ create(context) {
+ return {
+ /** @param {import('@typescript-eslint/utils').TSESTree.Program}
node */
+ Program(node) {
+ // Get language code and namespace from file path
+ const currentFilePath = context.filename;
+ const langCode = path.dirname(path.relative(localesDir,
currentFilePath));
+ const namespace = path.basename(currentFilePath, ".json");
+
+ if (langCode === defaultLanguage) {
+ return;
+ }
+
+ // Get keys from current file
+ const referenceKeys = defaultLanguageKeys[namespace];
+ let langKeys;
+
+ try {
+ const parsedLangJson = JSON.parse(context.sourceCode.text);
+
+ if (
+ typeof parsedLangJson === "object" &&
+ parsedLangJson !== null &&
+ !Array.isArray(parsedLangJson)
+ ) {
+ langKeys = getKeys(parsedLangJson);
+ } else {
+ context.report({
+ data: { error: "Invalid JSON object.", filePath:
currentFilePath },
+ messageId: "fileError",
+ node,
+ });
+
+ return;
+ }
+ } catch (error) {
+ const message = error instanceof Error ? error.message :
String(error);
+
+ context.report({
+ data: { error: message, filePath: currentFilePath },
+ messageId: "fileError",
+ node,
+ });
+
+ return;
+ }
+
+ // Check for missing translations
+ const langKeysSet = new Set(langKeys);
+ const missingKeys = referenceKeys.filter((key) =>
!langKeysSet.has(key));
+
+ if (missingKeys.length > 0) {
+ context.report({
+ data: { keys: missingKeys.join(", "), lang: langCode,
namespace },
+ messageId: "missingKeys",
+ node,
+ });
+ }
+ },
+ };
+ },
+ meta: {
+ docs: {
+ category: "Best Practices",
+ description: "Ensures non-default lang files have all keys from
default.",
+ recommended: "warn",
+ },
+ messages: {
+ fileError: "Failed to read/parse {{filePath}}. Error: {{error}}",
+ missingKeys: "Lang '{{lang}}' (namespace: {{namespace}}) missing
keys: {{keys}}",
+ },
+ type: "problem",
+ },
+ },
+ },
+};
+
+/** @type {import("@typescript-eslint/utils/ts-eslint").FlatConfig.Config} */
+export const i18nRules = {
+ files: ["**/i18n/locales/**/*.json"],
+ plugins: {
+ [i18nNamespace]: i18nPlugin,
+ },
+ rules: {
+ "@typescript-eslint/no-unused-expressions": "off",
+ [`${i18nNamespace}/check-translation-completeness`]: "warn",
+ "no-unused-expressions": "off",
+ },
+};
diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/de/common.json
b/airflow-core/src/airflow/ui/src/i18n/locales/de/common.json
index 7fc04de18eb..04b2403506a 100644
--- a/airflow-core/src/airflow/ui/src/i18n/locales/de/common.json
+++ b/airflow-core/src/airflow/ui/src/i18n/locales/de/common.json
@@ -1,92 +1,92 @@
{
+ "admin": {
+ "Config": "Konfiguration",
+ "Connections": "Verbindungen",
+ "Plugins": "Plug-ins",
+ "Pools": "Pools",
+ "Providers": "Providers",
+ "Variables": "Variablen"
+ },
+ "assetEvent_one": "Ereignis zu Datensets (Asset)",
+ "assetEvent_other": "Ereignisse zu Datensets (Asset)",
+ "browse": {
+ "auditLog": "Prüf-Log",
+ "xcoms": "Task Kommunikation (XComs)"
+ },
+ "dagRun_one": "Dag Lauf",
+ "dagRun_other": "Dag Läufe",
"defaultToGraphView": "Graph-Ansicht als Standard",
"defaultToGridView": "Gitter-Ansicht als Standard",
+ "docs": {
+ "documentation": "Dokumentation",
+ "githubRepo": "GitHub Ablage",
+ "restApiReference": "REST API Referenz"
+ },
"logout": "Abmelden",
"logoutConfirmation": "Sie sind dabei sich von dem System abzumelden.",
- "switchToDarkMode": "Zum Dunkelmodus wechseln",
- "switchToLightMode": "Zum Hellmodus wechseln",
- "timezone": "Zeitzone",
- "user": "Benutzer",
- "selectLanguage": "Sprache wählen",
+ "modal": {
+ "cancel": "Abbrechen",
+ "confirm": "Bestätigen"
+ },
"nav": {
- "home": "Start",
+ "admin": "Verwaltung",
"assets": "Datensets (Assets)",
"browse": "Browsen",
- "admin": "Verwaltung",
- "security": "Sicherheit",
"docs": "Doku",
- "plugins": "Plug-ins"
- },
- "browse": {
- "auditLog": "Prüf-Log",
- "xcoms": "Task Kommunikation (XComs)"
+ "home": "Start",
+ "plugins": "Plug-ins",
+ "security": "Sicherheit"
},
- "admin": {
- "Variables": "Variablen",
- "Pools": "Pools",
- "Providers": "Providers",
- "Plugins": "Plug-ins",
- "Connections": "Verbindungen",
- "Config": "Konfiguration"
+ "pools": {
+ "deferred": "Delegiert",
+ "open": "Frei",
+ "pools_one": "Pool",
+ "pools_other": "Pools",
+ "queued": "Wartend",
+ "running": "Laufend",
+ "scheduled": "Geplant"
},
"security": {
- "users": "Benutzer",
- "roles": "Rollen",
"actions": "Aktionen",
+ "permissions": "Berechtigungen",
"resources": "Ressourcen",
- "permissions": "Berechtigungen"
- },
- "timeRange": {
- "duration": "Laufzeit",
- "lastHour": "Letzte Stunde",
- "last12Hours": "Letzte 12 Stunden",
- "last24Hours": "Letzte 24 Stunden",
- "pastWeek": "Letzte Woche"
- },
- "docs": {
- "documentation": "Dokumentation",
- "githubRepo": "GitHub Ablage",
- "restApiReference": "REST API Referenz"
+ "roles": "Rollen",
+ "users": "Benutzer"
},
+ "selectLanguage": "Sprache wählen",
"states": {
- "queued": "Wartend",
- "running": "Laufend",
- "success": "Erfolgreich",
+ "deferred": "Delegiert",
"failed": "Fehlgeschlagen",
- "skipped": "Übersprungen",
+ "no_status": "Kein Status",
+ "queued": "Wartend",
"removed": "Entfernt",
- "scheduled": "Geplant",
"restarting": "Im Neustart",
- "up_for_retry": "Wartet auf neuen Versuch",
+ "running": "Laufend",
+ "scheduled": "Geplant",
+ "skipped": "Übersprungen",
+ "success": "Erfolgreich",
"up_for_reschedule": "Wartet auf Neuplanung",
- "upstream_failed": "Vorgelagerte fehlgeschlagen",
- "deferred": "Delegiert",
- "no_status": "Kein Status"
+ "up_for_retry": "Wartet auf neuen Versuch",
+ "upstream_failed": "Vorgelagerte fehlgeschlagen"
},
- "dagRun_one": "Dag Lauf",
- "dagRun_other": "Dag Läufe",
+ "switchToDarkMode": "Zum Dunkelmodus wechseln",
+ "switchToLightMode": "Zum Hellmodus wechseln",
"taskInstance_one": "Task Instanz",
"taskInstance_other": "Task Instanzen",
- "assetEvent_one": "Ereignis zu Datensets (Asset)",
- "assetEvent_other": "Ereignisse zu Datensets (Asset)",
- "triggered": "Angestoßen",
- "pools": {
- "open": "Frei",
- "running": "Laufend",
- "queued": "Wartend",
- "scheduled": "Geplant",
- "deferred": "Delegiert",
- "pools_one": "Pool",
- "pools_other": "Pools"
- },
- "modal": {
- "cancel": "Abbrechen",
- "confirm": "Bestätigen"
+ "timeRange": {
+ "duration": "Laufzeit",
+ "last12Hours": "Letzte 12 Stunden",
+ "last24Hours": "Letzte 24 Stunden",
+ "lastHour": "Letzte Stunde",
+ "pastWeek": "Letzte Woche"
},
+ "timezone": "Zeitzone",
"timezoneModal": {
- "title": "Auswahl der Zeitzone",
- "placeholder": "Wählen Sie eine Zeitzone",
"current-timezone": "Aktuelle Zeit in",
+ "placeholder": "Wählen Sie eine Zeitzone",
+ "title": "Auswahl der Zeitzone",
"utc": "UTC (Koordinierte Weltzeit)"
- }
+ },
+ "triggered": "Angestoßen",
+ "user": "Benutzer"
}
diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/de/dashboard.json
b/airflow-core/src/airflow/ui/src/i18n/locales/de/dashboard.json
index 53e27af44aa..dc53117a11b 100644
--- a/airflow-core/src/airflow/ui/src/i18n/locales/de/dashboard.json
+++ b/airflow-core/src/airflow/ui/src/i18n/locales/de/dashboard.json
@@ -1,38 +1,38 @@
{
- "welcome": "Willkommen",
- "stats": {
- "stats": "Statistiken",
- "failedDags": "Fehlgeschlagene Dags",
- "runningDags": "Laufende Dags",
- "activeDags": "Aktive Dags",
- "queuedDags": "Dags in Warteschlange"
- },
+ "group": "Gruppe",
"health": {
+ "dagProcessor": "Dag Prozessor",
"health": "System-Gesundheit",
+ "healthy": "Gut",
+ "lastHeartbeat": "Letztes Lebenszeichen",
"metaDatabase": "Meta-Datenbank",
"scheduler": "Planer",
- "triggerer": "Triggerer",
- "dagProcessor": "Dag Prozessor",
"status": "Status",
- "lastHeartbeat": "Letztes Lebenszeichen",
- "healthy": "Gut",
+ "triggerer": "Triggerer",
"unhealthy": "Nicht in Ordnung"
},
+ "history": "Historie",
"importErrors": {
- "searchByFile": "Nach Datei suchen",
"dagImportError_one": "Fehler beim Laden des Dags",
"dagImportError_other": "Fehler beim Laden der Dags",
+ "searchByFile": "Nach Datei suchen",
"timestamp": "Zeitstempel"
},
- "poolSlots": "Pool Belegung",
"managePools": "Pools verwalten",
- "history": "Historie",
+ "noAssetEvents": "Keine Ereignisse zu Datensets vorliegend.",
+ "poolSlots": "Pool Belegung",
"sortBy": {
"newestFirst": "Neueste zuerst",
"oldestFirst": "Älteste zuerst"
},
"source": "Quellcode",
- "group": "Gruppe",
+ "stats": {
+ "activeDags": "Aktive Dags",
+ "failedDags": "Fehlgeschlagene Dags",
+ "queuedDags": "Dags in Warteschlange",
+ "runningDags": "Laufende Dags",
+ "stats": "Statistiken"
+ },
"uri": "Uri",
- "noAssetEvents": "Keine Ereignisse zu Datensets vorliegend."
+ "welcome": "Willkommen"
}
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 7cc03e6b1bb..b1a3a0d0c42 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
@@ -1,93 +1,93 @@
{
+ "admin": {
+ "Config": "Config",
+ "Connections": "Connections",
+ "Plugins": "Plugins",
+ "Pools": "Pools",
+ "Providers": "Providers",
+ "Variables": "Variables"
+ },
+ "assetEvent_one": "Asset Event",
+ "assetEvent_other": "Asset Events",
+ "browse": {
+ "auditLog": "Audit Log",
+ "xcoms": "XComs"
+ },
+ "dagRun_one": "Dag Run",
+ "dagRun_other": "Dag Runs",
"defaultToGraphView": "Default to graph view",
"defaultToGridView": "Default to grid view",
+ "docs": {
+ "documentation": "Documentation",
+ "githubRepo": "GitHub Repo",
+ "restApiReference": "REST API Reference"
+ },
"logout": "Logout",
"logoutConfirmation": "You are about to logout from the application.",
- "switchToDarkMode": "Switch to Dark Mode",
- "switchToLightMode": "Switch to Light Mode",
- "timezone": "timezone",
- "user": "User",
- "selectLanguage": "Select Language",
+ "modal": {
+ "cancel": "Cancel",
+ "confirm": "Confirm"
+ },
"nav": {
- "home": "Home",
- "dags": "Dags",
+ "admin": "Admin",
"assets": "Assets",
"browse": "Browse",
- "admin": "Admin",
- "security": "Security",
+ "dags": "Dags",
"docs": "Docs",
- "plugins": "Plugins"
- },
- "browse": {
- "auditLog": "Audit Log",
- "xcoms": "XComs"
+ "home": "Home",
+ "plugins": "Plugins",
+ "security": "Security"
},
- "admin": {
- "Variables": "Variables",
- "Pools": "Pools",
- "Providers": "Providers",
- "Plugins": "Plugins",
- "Connections": "Connections",
- "Config": "Config"
+ "pools": {
+ "deferred": "Deferred",
+ "open": "Open",
+ "pools_one": "pool",
+ "pools_other": "pools",
+ "queued": "Queued",
+ "running": "Running",
+ "scheduled": "Scheduled"
},
"security": {
- "users": "Users",
- "roles": "Roles",
"actions": "Actions",
+ "permissions": "Permissions",
"resources": "Resources",
- "permissions": "Permissions"
- },
- "timeRange": {
- "duration": "Duration",
- "lastHour": "Last Hour",
- "last12Hours": "Last 12 Hours",
- "last24Hours": "Last 24 Hours",
- "pastWeek": "Past Week"
- },
- "docs": {
- "documentation": "Documentation",
- "githubRepo": "GitHub Repo",
- "restApiReference": "REST API Reference"
+ "roles": "Roles",
+ "users": "Users"
},
+ "selectLanguage": "Select Language",
"states": {
- "queued": "Queued",
- "running": "Running",
- "success": "Success",
+ "deferred": "Deferred",
"failed": "Failed",
- "skipped": "Skipped",
+ "no_status": "No Status",
+ "queued": "Queued",
"removed": "Removed",
- "scheduled": "Scheduled",
"restarting": "Restarting",
- "up_for_retry": "Up For Retry",
+ "running": "Running",
+ "scheduled": "Scheduled",
+ "skipped": "Skipped",
+ "success": "Success",
"up_for_reschedule": "Up For Reschedule",
- "upstream_failed": "Upstream Failed",
- "deferred": "Deferred",
- "no_status": "No Status"
+ "up_for_retry": "Up For Retry",
+ "upstream_failed": "Upstream Failed"
},
- "dagRun_one": "Dag Run",
- "dagRun_other": "Dag Runs",
+ "switchToDarkMode": "Switch to Dark Mode",
+ "switchToLightMode": "Switch to Light Mode",
"taskInstance_one": "Task Instance",
"taskInstance_other": "Task Instances",
- "assetEvent_one": "Asset Event",
- "assetEvent_other": "Asset Events",
- "triggered": "Triggered",
- "pools": {
- "open": "Open",
- "running": "Running",
- "queued": "Queued",
- "scheduled": "Scheduled",
- "deferred": "Deferred",
- "pools_one": "pool",
- "pools_other": "pools"
- },
- "modal": {
- "cancel": "Cancel",
- "confirm": "Confirm"
+ "timeRange": {
+ "duration": "Duration",
+ "last12Hours": "Last 12 Hours",
+ "last24Hours": "Last 24 Hours",
+ "lastHour": "Last Hour",
+ "pastWeek": "Past Week"
},
+ "timezone": "timezone",
"timezoneModal": {
- "title": "Select Timezone",
- "placeholder": "Select a timezone",
"current-timezone": "Current time in",
+ "placeholder": "Select a timezone",
+ "title": "Select Timezone",
"utc": "UTC (Coordinated Universal Time)"
- }
+ },
+ "triggered": "Triggered",
+ "user": "User"
}
diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/en/dashboard.json
b/airflow-core/src/airflow/ui/src/i18n/locales/en/dashboard.json
index 2c24501203b..3b945abbb45 100644
--- a/airflow-core/src/airflow/ui/src/i18n/locales/en/dashboard.json
+++ b/airflow-core/src/airflow/ui/src/i18n/locales/en/dashboard.json
@@ -1,38 +1,38 @@
{
- "welcome": "Welcome",
- "stats": {
- "stats": "Stats",
- "failedDags": "Failed Dags",
- "runningDags": "Running Dags",
- "activeDags": "Active Dags",
- "queuedDags": "Queued Dags"
- },
+ "group": "Group",
"health": {
+ "dagProcessor": "Dag Processor",
"health": "Health",
+ "healthy": "Healthy",
+ "lastHeartbeat": "Last Heartbeat",
"metaDatabase": "MetaDatabase",
"scheduler": "Scheduler",
- "triggerer": "Triggerer",
- "dagProcessor": "Dag Processor",
"status": "Status",
- "lastHeartbeat": "Last Heartbeat",
- "healthy": "Healthy",
+ "triggerer": "Triggerer",
"unhealthy": "Unhealthy"
},
+ "history": "History",
"importErrors": {
- "searchByFile": "Search by file",
"dagImportError_one": "Dag Import Error",
"dagImportError_other": "Dag Import Errors",
+ "searchByFile": "Search by file",
"timestamp": "Timestamp"
},
- "poolSlots": "Pool Slots",
"managePools": "Manage Pools",
- "history": "History",
+ "noAssetEvents": "No Asset Events found.",
+ "poolSlots": "Pool Slots",
"sortBy": {
"newestFirst": "Newest First",
"oldestFirst": "Oldest First"
},
"source": "Source",
- "group": "Group",
+ "stats": {
+ "activeDags": "Active Dags",
+ "failedDags": "Failed Dags",
+ "queuedDags": "Queued Dags",
+ "runningDags": "Running Dags",
+ "stats": "Stats"
+ },
"uri": "Uri",
- "noAssetEvents": "No Asset Events found."
+ "welcome": "Welcome"
}
diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/ko/common.json
b/airflow-core/src/airflow/ui/src/i18n/locales/ko/common.json
index 0412aea4444..b35a100d506 100644
--- a/airflow-core/src/airflow/ui/src/i18n/locales/ko/common.json
+++ b/airflow-core/src/airflow/ui/src/i18n/locales/ko/common.json
@@ -1,73 +1,73 @@
{
- "defaultToGraphView": "그래프 뷰 기본 보기",
- "defaultToGridView": "그리드 뷰 기본 보기",
- "logout": "로그아웃",
- "switchToDarkMode": "다크 모드로 전환",
- "switchToLightMode": "라이트 모드로 전환",
- "timezone": "시간대",
- "user": "사용자",
- "selectLanguage": "언어 선택",
- "nav": {
- "home": "홈",
- "assets": "에셋",
- "browse": "탐색",
- "admin": "관리자",
- "docs": "문서",
- "plugins": "플러그인"
- },
- "browse": {
- "auditLog": "감사 로그",
- "xcoms": "XComs"
- },
"admin": {
- "Variables": "변수들",
+ "Config": "설정",
+ "Connections": "연결들",
+ "Plugins": "플러그인들",
"Pools": "Pools",
"Providers": "제공자들",
- "Plugins": "플러그인들",
- "Connections": "연결들",
- "Config": "설정"
+ "Variables": "변수들"
},
- "timeRange": {
- "duration": "지속 시간",
- "lastHour": "지난 1시간",
- "last12Hours": "지난 12 시간",
- "last24Hours": "지난 24 시간",
- "pastWeek": "지난 주"
+ "assetEvent_one": "에셋 이벤트",
+ "assetEvent_other": "에셋 이벤트들",
+ "browse": {
+ "auditLog": "감사 로그",
+ "xcoms": "XComs"
},
+ "dagRun_one": "Dag 실행",
+ "dagRun_other": "Dag 실행들",
+ "defaultToGraphView": "그래프 뷰 기본 보기",
+ "defaultToGridView": "그리드 뷰 기본 보기",
"docs": {
"documentation": "문서",
"githubRepo": "GitHub 저장소",
"restApiReference": "REST API 참조"
},
- "states": {
+ "logout": "로그아웃",
+ "nav": {
+ "admin": "관리자",
+ "assets": "에셋",
+ "browse": "탐색",
+ "docs": "문서",
+ "home": "홈",
+ "plugins": "플러그인"
+ },
+ "pools": {
+ "deferred": "연기됨",
+ "open": "열림",
+ "pools_one": "pool",
+ "pools_other": "pools",
"queued": "대기 중",
"running": "실행 중",
- "success": "성공",
+ "scheduled": "예약됨"
+ },
+ "selectLanguage": "언어 선택",
+ "states": {
+ "deferred": "연기됨",
"failed": "실패",
- "skipped": "건너뜀",
+ "no_status": "상태 없음",
+ "queued": "대기 중",
"removed": "제거됨",
- "scheduled": "예약됨",
"restarting": "다시 시작 중",
- "up_for_retry": "재시도 대기 중",
+ "running": "실행 중",
+ "scheduled": "예약됨",
+ "skipped": "건너뜀",
+ "success": "성공",
"up_for_reschedule": "재예약 대기 중",
- "upstream_failed": "업스트림 실패",
- "deferred": "연기됨",
- "no_status": "상태 없음"
+ "up_for_retry": "재시도 대기 중",
+ "upstream_failed": "업스트림 실패"
},
- "dagRun_one": "Dag 실행",
- "dagRun_other": "Dag 실행들",
+ "switchToDarkMode": "다크 모드로 전환",
+ "switchToLightMode": "라이트 모드로 전환",
"taskInstance_one": "작업 인스턴스",
"taskInstance_other": "작업 인스턴스들",
- "assetEvent_one": "에셋 이벤트",
- "assetEvent_other": "에셋 이벤트들",
+ "timeRange": {
+ "duration": "지속 시간",
+ "last12Hours": "지난 12 시간",
+ "last24Hours": "지난 24 시간",
+ "lastHour": "지난 1시간",
+ "pastWeek": "지난 주"
+ },
+ "timezone": "시간대",
"triggered": "트리거됨",
- "pools": {
- "open": "열림",
- "running": "실행 중",
- "queued": "대기 중",
- "scheduled": "예약됨",
- "deferred": "연기됨",
- "pools_one": "pool",
- "pools_other": "pools"
- }
+ "user": "사용자"
}
diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/ko/dashboard.json
b/airflow-core/src/airflow/ui/src/i18n/locales/ko/dashboard.json
index a9121295b34..c8f200c8eaf 100644
--- a/airflow-core/src/airflow/ui/src/i18n/locales/ko/dashboard.json
+++ b/airflow-core/src/airflow/ui/src/i18n/locales/ko/dashboard.json
@@ -1,38 +1,38 @@
{
- "welcome": "환영합니다",
- "stats": {
- "stats": "통계",
- "failedDags": "실패한 Dags",
- "runningDags": "실행 중인 Dags",
- "activeDags": "활성 Dags",
- "queuedDags": "대기 중인 Dags"
- },
+ "group": "그룹",
"health": {
+ "dagProcessor": "Dag 프로세서",
"health": "상태",
+ "healthy": "정상",
+ "lastHeartbeat": "마지막 Heartbeat",
"metaDatabase": "메타데이터베이스",
"scheduler": "스케줄러",
- "triggerer": "트리거러",
- "dagProcessor": "Dag 프로세서",
"status": "상태",
- "lastHeartbeat": "마지막 Heartbeat",
- "healthy": "정상",
+ "triggerer": "트리거러",
"unhealthy": "비정상"
},
+ "history": "기록",
"importErrors": {
- "searchByFile": "파일로 검색",
"dagImportError_one": "Dag 가져오기 오류",
"dagImportError_other": "Dag 가져오기 오류들",
+ "searchByFile": "파일로 검색",
"timestamp": "타임스탬프"
},
- "poolSlots": "Pool 슬롯",
"managePools": "Pools 관리",
- "history": "기록",
+ "noAssetEvents": "자산 이벤트를 찾을 수 없습니다.",
+ "poolSlots": "Pool 슬롯",
"sortBy": {
"newestFirst": "최신순",
"oldestFirst": "오래된 순"
},
"source": "소스",
- "group": "그룹",
+ "stats": {
+ "activeDags": "활성 Dags",
+ "failedDags": "실패한 Dags",
+ "queuedDags": "대기 중인 Dags",
+ "runningDags": "실행 중인 Dags",
+ "stats": "통계"
+ },
"uri": "Uri",
- "noAssetEvents": "자산 이벤트를 찾을 수 없습니다."
+ "welcome": "환영합니다"
}
diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/nl/common.json
b/airflow-core/src/airflow/ui/src/i18n/locales/nl/common.json
index 656886d0ebb..a68a472f207 100644
--- a/airflow-core/src/airflow/ui/src/i18n/locales/nl/common.json
+++ b/airflow-core/src/airflow/ui/src/i18n/locales/nl/common.json
@@ -1,73 +1,73 @@
{
- "defaultToGraphView": "Standaard grafiekweergave",
- "defaultToGridView": "Standaard rasterweergave",
- "logout": "Uitloggen",
- "switchToDarkMode": "Schakel over naar donkere modus",
- "switchToLightMode": "Schakel over naar lichte modus",
- "timezone": "Tijdzone",
- "user": "Gebruiker",
- "selectLanguage": "Selecteer taal",
- "nav": {
- "home": "Home",
- "assets": "Assets",
- "browse": "Verken",
- "admin": "Beheer",
- "docs": "Documentatie",
- "plugins": "Plugins"
- },
- "browse": {
- "auditLog": "Audit Log",
- "xcoms": "XComs"
- },
"admin": {
- "Variables": "Variabelen",
+ "Config": "Configuratie",
+ "Connections": "Connecties",
+ "Plugins": "Plugins",
"Pools": "Pools",
"Providers": "Providers",
- "Plugins": "Plugins",
- "Connections": "Connecties",
- "Config": "Configuratie"
+ "Variables": "Variabelen"
},
- "timeRange": {
- "duration": "Duur",
- "lastHour": "Laatste uur",
- "last12Hours": "Laatste 12 uur",
- "last24Hours": "Laatste 24 uur",
- "pastWeek": "Laatste week"
+ "assetEvent_one": "Asset Event",
+ "assetEvent_other": "Asset Events",
+ "browse": {
+ "auditLog": "Audit Log",
+ "xcoms": "XComs"
},
+ "dagRun_one": "Dag Run",
+ "dagRun_other": "Dag Runs",
+ "defaultToGraphView": "Standaard grafiekweergave",
+ "defaultToGridView": "Standaard rasterweergave",
"docs": {
"documentation": "Documentatie",
"githubRepo": "GitHub Repo",
"restApiReference": "REST API referentie"
},
- "states": {
+ "logout": "Uitloggen",
+ "nav": {
+ "admin": "Beheer",
+ "assets": "Assets",
+ "browse": "Verken",
+ "docs": "Documentatie",
+ "home": "Home",
+ "plugins": "Plugins"
+ },
+ "pools": {
+ "deferred": "Uitgesteld",
+ "open": "Open",
+ "pools_one": "pool",
+ "pools_other": "pools",
"queued": "Wachtend",
"running": "Lopend",
- "success": "Succesvol",
+ "scheduled": "Gepland"
+ },
+ "selectLanguage": "Selecteer taal",
+ "states": {
+ "deferred": "Uitgesteld",
"failed": "Mislukt",
- "skipped": "Overgeslagen",
+ "no_status": "Geen Status",
+ "queued": "Wachtend",
"removed": "Verwijderd",
- "scheduled": "Gepland",
"restarting": "Herstartend",
- "up_for_retry": "Wachtend op een nieuwe poging",
+ "running": "Lopend",
+ "scheduled": "Gepland",
+ "skipped": "Overgeslagen",
+ "success": "Succesvol",
"up_for_reschedule": "Wachtend op herplanning",
- "upstream_failed": "Upstream mislukt",
- "deferred": "Uitgesteld",
- "no_status": "Geen Status"
+ "up_for_retry": "Wachtend op een nieuwe poging",
+ "upstream_failed": "Upstream mislukt"
},
- "dagRun_one": "Dag Run",
- "dagRun_other": "Dag Runs",
+ "switchToDarkMode": "Schakel over naar donkere modus",
+ "switchToLightMode": "Schakel over naar lichte modus",
"taskInstance_one": "Task Instance",
"taskInstance_other": "Task Instances",
- "assetEvent_one": "Asset Event",
- "assetEvent_other": "Asset Events",
+ "timeRange": {
+ "duration": "Duur",
+ "last12Hours": "Laatste 12 uur",
+ "last24Hours": "Laatste 24 uur",
+ "lastHour": "Laatste uur",
+ "pastWeek": "Laatste week"
+ },
+ "timezone": "Tijdzone",
"triggered": "Triggered",
- "pools": {
- "open": "Open",
- "running": "Lopend",
- "queued": "Wachtend",
- "scheduled": "Gepland",
- "deferred": "Uitgesteld",
- "pools_one": "pool",
- "pools_other": "pools"
- }
+ "user": "Gebruiker"
}
diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/nl/dashboard.json
b/airflow-core/src/airflow/ui/src/i18n/locales/nl/dashboard.json
index 0577d6cfbcf..3243ef47f40 100644
--- a/airflow-core/src/airflow/ui/src/i18n/locales/nl/dashboard.json
+++ b/airflow-core/src/airflow/ui/src/i18n/locales/nl/dashboard.json
@@ -1,38 +1,38 @@
{
- "welcome": "Welkom",
- "stats": {
- "stats": "Statistieken",
- "failedDags": "Mislukte Dags",
- "runningDags": "Lopende Dags",
- "activeDags": "Actieve Dags",
- "queuedDags": "Dags in de wachtrij"
- },
+ "group": "Groep",
"health": {
+ "dagProcessor": "Dag Processor",
"health": "Status",
+ "healthy": "OK",
+ "lastHeartbeat": "Laatste hartslag",
"metaDatabase": "MetaDatabase",
"scheduler": "Scheduler",
- "triggerer": "Triggerer",
- "dagProcessor": "Dag Processor",
"status": "Status",
- "lastHeartbeat": "Laatste hartslag",
- "healthy": "OK",
+ "triggerer": "Triggerer",
"unhealthy": "Fout"
},
+ "history": "Geschiedenis",
"importErrors": {
- "searchByFile": "Zoek op bestand",
"dagImportError_one": "Dag leesfout",
"dagImportError_other": "Dag leesfouten",
+ "searchByFile": "Zoek op bestand",
"timestamp": "Tijd"
},
- "poolSlots": "Pool Slots",
"managePools": "Beheer Pools",
- "history": "Geschiedenis",
+ "noAssetEvents": "Geen Asset Events gevonden.",
+ "poolSlots": "Pool Slots",
"sortBy": {
"newestFirst": "Nieuwste eerst",
"oldestFirst": "Oudste eerst"
},
"source": "Bron",
- "group": "Groep",
+ "stats": {
+ "activeDags": "Actieve Dags",
+ "failedDags": "Mislukte Dags",
+ "queuedDags": "Dags in de wachtrij",
+ "runningDags": "Lopende Dags",
+ "stats": "Statistieken"
+ },
"uri": "Uri",
- "noAssetEvents": "Geen Asset Events gevonden."
+ "welcome": "Welkom"
}
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 9c46b155bdd..16a7f4588a2 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,63 +1,63 @@
{
- "defaultToGraphView": "預設使用圖形視圖",
- "defaultToGridView": "預設使用網格視圖",
- "logout": "登出",
- "switchToDarkMode": "切換到深色模式",
- "switchToLightMode": "切換到淺色模式",
- "timezone": "時區",
- "user": "使用者",
- "selectLanguage": "選擇語言",
- "nav": {
- "home": "首頁",
- "assets": "資源",
- "browse": "瀏覽",
- "admin": "管理者",
- "docs": "文件",
- "plugins": "插件"
- },
- "browse": {
- "auditLog": "審計日誌",
- "xcoms": "XComs"
- },
"admin": {
- "Variables": "變數",
+ "Config": "設定",
+ "Connections": "連結",
+ "Plugins": "插件",
"Pools": "資源池",
"Providers": "Providers",
- "Plugins": "插件",
- "Connections": "連結",
- "Config": "設定"
+ "Variables": "變數"
},
- "timeRange": {
- "duration": "時間範圍",
- "lastHour": "最近 1 小時",
- "last12Hours": "最近 12 小時",
- "last24Hours": "最近 24 小時",
- "pastWeek": "過去一週"
+ "assetEvent_one": "資源事件",
+ "assetEvent_other": "資源事件",
+ "browse": {
+ "auditLog": "審計日誌",
+ "xcoms": "XComs"
},
+ "dagRun_one": "Dag 執行",
+ "dagRun_other": "Dag 執行",
+ "defaultToGraphView": "預設使用圖形視圖",
+ "defaultToGridView": "預設使用網格視圖",
"docs": {
"documentation": "文件",
"githubRepo": "GitHub 倉庫",
"restApiReference": "REST API 參考"
},
+ "logout": "登出",
+ "nav": {
+ "admin": "管理者",
+ "assets": "資源",
+ "browse": "瀏覽",
+ "docs": "文件",
+ "home": "首頁",
+ "plugins": "插件"
+ },
+ "selectLanguage": "選擇語言",
"states": {
- "queued": "排隊中",
- "running": "執行中",
- "success": "成功",
+ "deferred": "已延後",
"failed": "失敗",
- "skipped": "已跳過",
+ "no_status": "無狀態",
+ "queued": "排隊中",
"removed": "已移除",
- "scheduled": "已排程",
"restarting": "重啟中",
- "up_for_retry": "等待重試",
+ "running": "執行中",
+ "scheduled": "已排程",
+ "skipped": "已跳過",
+ "success": "成功",
"up_for_reschedule": "等待重新排程",
- "upstream_failed": "上游任務失敗",
- "deferred": "已延後",
- "no_status": "無狀態"
+ "up_for_retry": "等待重試",
+ "upstream_failed": "上游任務失敗"
},
- "dagRun_one": "Dag 執行",
- "dagRun_other": "Dag 執行",
+ "switchToDarkMode": "切換到深色模式",
+ "switchToLightMode": "切換到淺色模式",
"taskInstance_one": "任務實例",
"taskInstance_other": "任務實例",
- "assetEvent_one": "資源事件",
- "assetEvent_other": "資源事件"
+ "timeRange": {
+ "duration": "時間範圍",
+ "last12Hours": "最近 12 小時",
+ "last24Hours": "最近 24 小時",
+ "lastHour": "最近 1 小時",
+ "pastWeek": "過去一週"
+ },
+ "timezone": "時區",
+ "user": "使用者"
}
diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/dashboard.json
b/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/dashboard.json
index fd5aa0c97b6..05e83e40b64 100644
--- a/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/dashboard.json
+++ b/airflow-core/src/airflow/ui/src/i18n/locales/zh-TW/dashboard.json
@@ -1,28 +1,28 @@
{
- "welcome": "歡迎",
- "stats": {
- "stats": "統計",
- "failedDags": "失敗的 Dags",
- "runningDags": "執行中的 Dags",
- "activeDags": "啟用中的 Dags",
- "queuedDags": "排隊中的 Dags"
- },
+ "group": "群組",
"health": {
+ "dagProcessor": "Dag 處理器",
"health": "健康狀態",
"metaDatabase": "系統資料庫",
"scheduler": "排程器",
- "triggerer": "觸發器",
- "dagProcessor": "Dag 處理器"
+ "triggerer": "觸發器"
},
- "poolSlots": "資源池配額",
- "managePools": "管理資源池",
"history": "歷史記錄",
+ "managePools": "管理資源池",
+ "noAssetEvents": "未找到資源事件",
+ "poolSlots": "資源池配額",
"sortBy": {
"newestFirst": "由新到舊",
"oldestFirst": "由舊到新"
},
"source": "來源",
- "group": "群組",
+ "stats": {
+ "activeDags": "啟用中的 Dags",
+ "failedDags": "失敗的 Dags",
+ "queuedDags": "排隊中的 Dags",
+ "runningDags": "執行中的 Dags",
+ "stats": "統計"
+ },
"uri": "Uri",
- "noAssetEvents": "未找到資源事件"
+ "welcome": "歡迎"
}