Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 42d558e

Browse files
bbovenzisanederchik
authored andcommittedJun 7, 2025
Migrate dags list plaintext to translate files (apache#51181)
* Migrate dags list plaintext to translate files * Update SearchBar, DagOwners and fix asset schedule * Fix test * Alphabetically sort json
1 parent 60954ee commit 42d558e

25 files changed

+770
-446
lines changed
 

‎airflow-core/src/airflow/ui/src/components/DagActions/DeleteDagButton.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
* under the License.
1818
*/
1919
import { useDisclosure } from "@chakra-ui/react";
20+
import { useTranslation } from "react-i18next";
2021
import { FiTrash2 } from "react-icons/fi";
2122
import { useNavigate } from "react-router-dom";
2223

@@ -33,7 +34,7 @@ type DeleteDagButtonProps = {
3334
const DeleteDagButton = ({ dagDisplayName, dagId, withText = true }: DeleteDagButtonProps) => {
3435
const { onClose, onOpen, open } = useDisclosure();
3536
const navigate = useNavigate();
36-
37+
const { t: translate } = useTranslation("dags");
3738
const { isPending, mutate: deleteDag } = useDeleteDag({
3839
dagId,
3940
onSuccessConfirm: () => {
@@ -45,11 +46,11 @@ const DeleteDagButton = ({ dagDisplayName, dagId, withText = true }: DeleteDagBu
4546
return (
4647
<>
4748
<ActionButton
48-
actionName="Delete DAG"
49+
actionName={translate("actions.delete")}
4950
colorPalette="red"
5051
icon={<FiTrash2 />}
5152
onClick={onOpen}
52-
text="Delete DAG"
53+
text={translate("actions.delete")}
5354
variant="solid"
5455
withText={withText}
5556
/>
@@ -60,8 +61,8 @@ const DeleteDagButton = ({ dagDisplayName, dagId, withText = true }: DeleteDagBu
6061
onDelete={() => deleteDag({ dagId })}
6162
open={open}
6263
resourceName={dagDisplayName}
63-
title="Delete DAG"
64-
warningText="This will remove all metadata related to the DAG, including DAG Runs and Tasks."
64+
title={translate("actions.delete")}
65+
warningText={translate("actions.deleteDagWarning")}
6566
/>
6667
</>
6768
);

‎airflow-core/src/airflow/ui/src/components/DataTable/FilterMenuButton.tsx

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
import { IconButton } from "@chakra-ui/react";
2020
import { flexRender, type Header, type Table } from "@tanstack/react-table";
21+
import { useTranslation } from "react-i18next";
2122
import { MdFilterList } from "react-icons/md";
2223

2324
import { Menu } from "src/components/ui";
@@ -27,44 +28,43 @@ type Props<TData> = {
2728
readonly table: Table<TData>;
2829
};
2930

30-
const FilterMenuButton = <TData,>({ table }: Props<TData>) => (
31-
<Menu.Root closeOnSelect={false} positioning={{ placement: "bottom" }}>
32-
<Menu.Trigger asChild>
33-
<IconButton
34-
aria-label="Filter table columns"
35-
margin={1}
36-
padding={0}
37-
title="Filter table columns"
38-
variant="ghost"
39-
>
40-
<MdFilterList size="1" />
41-
</IconButton>
42-
</Menu.Trigger>
43-
<Menu.Content>
44-
{table.getAllLeafColumns().map((column) => {
45-
const text = flexRender(column.columnDef.header, {
46-
column,
47-
header: { column } as Header<TData, unknown>,
48-
table,
49-
});
31+
const FilterMenuButton = <TData,>({ table }: Props<TData>) => {
32+
const { t: translate } = useTranslation("common");
33+
const filterLabel = translate("table.filterColumns");
5034

51-
return text?.toString ? (
52-
<Menu.Item asChild key={column.id} value={column.id}>
53-
<Checkbox
54-
checked={column.getIsVisible()}
55-
// At least one item needs to be visible
56-
disabled={table.getVisibleFlatColumns().length < 2 && column.getIsVisible()}
57-
onChange={() => {
58-
column.toggleVisibility();
59-
}}
60-
>
61-
{text}
62-
</Checkbox>
63-
</Menu.Item>
64-
) : undefined;
65-
})}
66-
</Menu.Content>
67-
</Menu.Root>
68-
);
35+
return (
36+
<Menu.Root closeOnSelect={false} positioning={{ placement: "bottom" }}>
37+
<Menu.Trigger asChild>
38+
<IconButton aria-label={filterLabel} margin={1} padding={0} title={filterLabel} variant="ghost">
39+
<MdFilterList size="1" />
40+
</IconButton>
41+
</Menu.Trigger>
42+
<Menu.Content>
43+
{table.getAllLeafColumns().map((column) => {
44+
const text = flexRender(column.columnDef.header, {
45+
column,
46+
header: { column } as Header<TData, unknown>,
47+
table,
48+
});
49+
50+
return text?.toString ? (
51+
<Menu.Item asChild key={column.id} value={column.id}>
52+
<Checkbox
53+
checked={column.getIsVisible()}
54+
// At least one item needs to be visible
55+
disabled={table.getVisibleFlatColumns().length < 2 && column.getIsVisible()}
56+
onChange={() => {
57+
column.toggleVisibility();
58+
}}
59+
>
60+
{text}
61+
</Checkbox>
62+
</Menu.Item>
63+
) : undefined;
64+
})}
65+
</Menu.Content>
66+
</Menu.Root>
67+
);
68+
};
6969

7070
export default FilterMenuButton;

‎airflow-core/src/airflow/ui/src/components/DeleteDialog.tsx

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
import { Text, Heading, HStack } from "@chakra-ui/react";
2020
import React from "react";
21+
import { useTranslation } from "react-i18next";
2122
import { FiTrash2 } from "react-icons/fi";
2223

2324
import { Button, Dialog } from "src/components/ui";
@@ -34,41 +35,44 @@ type DeleteDialogProps = {
3435
};
3536

3637
const DeleteDialog: React.FC<DeleteDialogProps> = ({
37-
deleteButtonText = "Delete",
38+
deleteButtonText,
3839
isDeleting,
3940
onClose,
4041
onDelete,
4142
open,
4243
resourceName,
4344
title,
4445
warningText,
45-
}) => (
46-
<Dialog.Root lazyMount onOpenChange={onClose} open={open} size="md" unmountOnExit>
47-
<Dialog.Content backdrop>
48-
<Dialog.Header>
49-
<Heading size="lg">{title}</Heading>
50-
</Dialog.Header>
51-
<Dialog.CloseTrigger />
52-
<Dialog.Body>
53-
<Text>
54-
Are you sure you want to delete <strong>{resourceName}</strong>? This action cannot be undone.
55-
</Text>
56-
<Text color="red.500" fontWeight="bold" mt={4}>
57-
{warningText}
58-
</Text>
59-
</Dialog.Body>
60-
<Dialog.Footer>
61-
<HStack justifyContent="flex-end" width="100%">
62-
<Button onClick={onClose} variant="outline">
63-
Cancel
64-
</Button>
65-
<Button colorPalette="red" loading={isDeleting} onClick={onDelete}>
66-
<FiTrash2 style={{ marginRight: "8px" }} /> {deleteButtonText}
67-
</Button>
68-
</HStack>
69-
</Dialog.Footer>
70-
</Dialog.Content>
71-
</Dialog.Root>
72-
);
46+
}) => {
47+
const { t: translate } = useTranslation("common");
48+
49+
return (
50+
<Dialog.Root lazyMount onOpenChange={onClose} open={open} size="md" unmountOnExit>
51+
<Dialog.Content backdrop>
52+
<Dialog.Header>
53+
<Heading size="lg">{title}</Heading>
54+
</Dialog.Header>
55+
<Dialog.CloseTrigger />
56+
<Dialog.Body>
57+
<Text>{translate("modal.delete.confirmation", { resourceName })}</Text>
58+
<Text color="red.500" fontWeight="bold" mt={4}>
59+
{warningText}
60+
</Text>
61+
</Dialog.Body>
62+
<Dialog.Footer>
63+
<HStack justifyContent="flex-end" width="100%">
64+
<Button onClick={onClose} variant="outline">
65+
{translate("modal.cancel")}
66+
</Button>
67+
<Button colorPalette="red" loading={isDeleting} onClick={onDelete}>
68+
<FiTrash2 style={{ marginRight: "8px" }} />{" "}
69+
{deleteButtonText ?? translate("modal.delete.button")}
70+
</Button>
71+
</HStack>
72+
</Dialog.Footer>
73+
</Dialog.Content>
74+
</Dialog.Root>
75+
);
76+
};
7377

7478
export default DeleteDialog;

‎airflow-core/src/airflow/ui/src/components/SearchBar.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ describe("Test SearchBar", () => {
3131

3232
const input = screen.getByTestId("search-dags");
3333

34-
expect(screen.getByText("Advanced Search")).toBeDefined();
34+
expect(screen.getByText("advancedSearch")).toBeDefined();
3535
expect(screen.queryByTestId("clear-search")).toBeNull();
3636

3737
fireEvent.change(input, { target: { value: "search" } });

‎airflow-core/src/airflow/ui/src/components/SearchBar.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import { Button, Input, Kbd, type ButtonProps } from "@chakra-ui/react";
2020
import { useState, useRef, type ChangeEvent } from "react";
2121
import { useHotkeys } from "react-hotkeys-hook";
22+
import { useTranslation } from "react-i18next";
2223
import { FiSearch } from "react-icons/fi";
2324
import { useDebouncedCallback } from "use-debounce";
2425

@@ -51,7 +52,7 @@ export const SearchBar = ({
5152
const searchRef = useRef<HTMLInputElement>(null);
5253
const [value, setValue] = useState(defaultValue);
5354
const metaKey = getMetaKey();
54-
55+
const { t: translate } = useTranslation(["dags"]);
5556
const onSearchChange = (event: ChangeEvent<HTMLInputElement>) => {
5657
setValue(event.target.value);
5758
handleSearchChange(event.target.value);
@@ -73,7 +74,7 @@ export const SearchBar = ({
7374
<>
7475
{Boolean(value) ? (
7576
<CloseButton
76-
aria-label="Clear search"
77+
aria-label={translate("clearSearch")}
7778
colorPalette="gray"
7879
data-testid="clear-search"
7980
onClick={() => {
@@ -85,7 +86,7 @@ export const SearchBar = ({
8586
) : undefined}
8687
{Boolean(hideAdvanced) ? undefined : (
8788
<Button fontWeight="normal" height="1.75rem" variant="ghost" width={140} {...buttonProps}>
88-
Advanced Search
89+
{translate("advancedSearch")}
8990
</Button>
9091
)}
9192
{!hotkeyDisabled && <Kbd size="sm">{metaKey}+K</Kbd>}

‎airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGButton.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
import { Box } from "@chakra-ui/react";
2020
import { useDisclosure } from "@chakra-ui/react";
21+
import { useTranslation } from "react-i18next";
2122
import { FiPlay } from "react-icons/fi";
2223

2324
import type { DAGResponse, DAGWithLatestDagRunsResponse } from "openapi/requests/types.gen";
@@ -32,15 +33,16 @@ type Props = {
3233

3334
const TriggerDAGButton: React.FC<Props> = ({ dag, withText = true }) => {
3435
const { onClose, onOpen, open } = useDisclosure();
36+
const { t: translate } = useTranslation("dags");
3537

3638
return (
3739
<Box>
3840
<ActionButton
39-
actionName="Trigger Dag"
41+
actionName={translate("actions.triggerDag")}
4042
colorPalette="blue"
4143
icon={<FiPlay />}
4244
onClick={onOpen}
43-
text="Trigger"
45+
text={translate("actions.trigger")}
4446
variant="solid"
4547
withText={withText}
4648
/>

‎airflow-core/src/airflow/ui/src/constants/sortParams.ts

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,42 @@
1717
* under the License.
1818
*/
1919
import { createListCollection } from "@chakra-ui/react/collection";
20+
import type { TFunction } from "i18next";
2021

21-
export const dagSortOptions = createListCollection({
22-
items: [
23-
{ label: "Sort by Display Name (A-Z)", value: "dag_display_name" },
24-
{ label: "Sort by Display Name (Z-A)", value: "-dag_display_name" },
25-
{ label: "Sort by Next DAG Run (Earliest-Latest)", value: "next_dagrun" },
26-
{ label: "Sort by Next DAG Run (Latest-Earliest)", value: "-next_dagrun" },
27-
{ label: "Sort by Latest Run State (A-Z)", value: "last_run_state" },
28-
{ label: "Sort by Latest Run State (Z-A)", value: "-last_run_state" },
29-
{
30-
label: "Sort by Latest Run Start Date (Earliest-Latest)",
31-
value: "last_run_start_date",
32-
},
33-
{
34-
label: "Sort by Latest Run Start Date (Latest-Earliest)",
35-
value: "-last_run_start_date",
36-
},
37-
],
38-
});
22+
export const createDagSortOptions = (translate: TFunction) =>
23+
createListCollection({
24+
items: [
25+
{
26+
label: translate("sort.displayName.asc"),
27+
value: "dag_display_name",
28+
},
29+
{
30+
label: translate("sort.displayName.desc"),
31+
value: "-dag_display_name",
32+
},
33+
{
34+
label: translate("sort.nextDagRun.asc"),
35+
value: "next_dagrun",
36+
},
37+
{
38+
label: translate("sort.nextDagRun.desc"),
39+
value: "-next_dagrun",
40+
},
41+
{
42+
label: translate("sort.lastRunState.asc"),
43+
value: "last_run_state",
44+
},
45+
{
46+
label: translate("sort.lastRunState.desc"),
47+
value: "-last_run_state",
48+
},
49+
{
50+
label: translate("sort.lastRunStartDate.asc"),
51+
value: "last_run_start_date",
52+
},
53+
{
54+
label: translate("sort.lastRunStartDate.desc"),
55+
value: "-last_run_start_date",
56+
},
57+
],
58+
});

‎airflow-core/src/airflow/ui/src/i18n/config.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { initReactI18next } from "react-i18next";
2323
import deCommon from "./locales/de/common.json";
2424
import deDashboard from "./locales/de/dashboard.json";
2525
import enCommon from "./locales/en/common.json";
26+
import enDags from "./locales/en/dags.json";
2627
import enDashboard from "./locales/en/dashboard.json";
2728
import koCommon from "./locales/ko/common.json";
2829
import koDashboard from "./locales/ko/dashboard.json";
@@ -43,7 +44,7 @@ export const supportedLanguages = [
4344
] as const;
4445

4546
export const defaultLanguage = "en";
46-
export const namespaces = ["common", "dashboard"] as const;
47+
export const namespaces = ["common", "dashboard", "dags"] as const;
4748

4849
const resources = {
4950
de: {
@@ -52,6 +53,7 @@ const resources = {
5253
},
5354
en: {
5455
common: enCommon,
56+
dags: enDags,
5557
dashboard: enDashboard,
5658
},
5759
ko: {

0 commit comments

Comments
 (0)
Please sign in to comment.