feat(ui): i18n for workflow runs

This commit is contained in:
吹雪 2026-06-11 07:45:19 +09:00
parent 4ccd5c188c
commit 20b4eb3fdb
3 changed files with 62 additions and 18 deletions

View file

@ -1,6 +1,7 @@
import React, { useState, useEffect, useCallback } from "react";
import { Button, Collapse, Drawer, Empty, Spin, Table, Tooltip, Typography } from "antd";
import { ReloadOutlined } from "@ant-design/icons";
import { useTranslation } from "react-i18next";
import { proxyBaseUrl } from "@/components/networking";
const { Text } = Typography;
@ -118,6 +119,7 @@ const StatusDot: React.FC<{ status: RunStatus; size?: number }> = ({ status, siz
const TRUNCATE_AT = 120;
const TruncatedValue: React.FC<{ value: string }> = ({ value }) => {
const { t } = useTranslation();
const [expanded, setExpanded] = useState(false);
if (value.length <= TRUNCATE_AT) {
return <span style={{ color: "#27272a", wordBreak: "break-all" }}>{value}</span>;
@ -137,7 +139,7 @@ const TruncatedValue: React.FC<{ value: string }> = ({ value }) => {
flexShrink: 0,
}}
>
{expanded ? "less" : "more"}
{expanded ? t("workflowRuns.index.less") : t("workflowRuns.index.more")}
</button>
</span>
);
@ -274,10 +276,11 @@ const GanttTimeline: React.FC<{
run: WorkflowRun;
events: WorkflowRunEvent[];
}> = ({ run, events }) => {
const { t } = useTranslation();
if (events.length === 0) {
return (
<div style={{ padding: "16px 0", color: "#a1a1aa", fontSize: 12, fontFamily: "monospace" }}>
No events recorded
{t("workflowRuns.index.noEvents")}
</div>
);
}
@ -473,6 +476,7 @@ const MessageRow: React.FC<{ msg: WorkflowRunMessage }> = ({ msg }) => {
// ── main component ────────────────────────────────────────────────────────────
const WorkflowRuns: React.FC<WorkflowRunsProps> = ({ accessToken }) => {
const { t } = useTranslation();
const [runs, setRuns] = useState<WorkflowRun[]>([]);
const [loadingRuns, setLoadingRuns] = useState(false);
const [selectedRun, setSelectedRun] = useState<WorkflowRun | null>(null);
@ -543,7 +547,7 @@ const WorkflowRuns: React.FC<WorkflowRunsProps> = ({ accessToken }) => {
const columns = [
{
title: "Run",
title: t("workflowRuns.index.colRun"),
dataIndex: "run_id",
key: "run",
render: (_: string, run: WorkflowRun) => (
@ -557,13 +561,13 @@ const WorkflowRuns: React.FC<WorkflowRunsProps> = ({ accessToken }) => {
),
},
{
title: "Type",
title: t("workflowRuns.index.colType"),
dataIndex: "workflow_type",
key: "workflow_type",
render: (v: string) => <span style={{ fontFamily: "monospace", fontSize: 12, color: "#71717a" }}>{v}</span>,
},
{
title: "Status",
title: t("workflowRuns.index.colStatus"),
dataIndex: "status",
key: "status",
render: (status: RunStatus, run: WorkflowRun) => {
@ -577,7 +581,7 @@ const WorkflowRuns: React.FC<WorkflowRunsProps> = ({ accessToken }) => {
},
},
{
title: "Created",
title: t("workflowRuns.index.colCreated"),
dataIndex: "created_at",
key: "created_at",
render: (v: string) => <span style={{ fontSize: 12, color: "#a1a1aa" }}>{timeAgo(v)}</span>,
@ -604,10 +608,8 @@ const WorkflowRuns: React.FC<WorkflowRunsProps> = ({ accessToken }) => {
}}
>
<div>
<div style={{ fontSize: 18, fontWeight: 600, color: "#18181b" }}>Workflow Runs</div>
<div style={{ fontSize: 13, color: "#71717a", marginTop: 2 }}>
Durable state tracking for agents and automated workflows
</div>
<div style={{ fontSize: 18, fontWeight: 600, color: "#18181b" }}>{t("workflowRuns.index.pageTitle")}</div>
<div style={{ fontSize: 13, color: "#71717a", marginTop: 2 }}>{t("workflowRuns.index.pageSubtitle")}</div>
</div>
<Button
icon={<ReloadOutlined />}
@ -615,7 +617,7 @@ const WorkflowRuns: React.FC<WorkflowRunsProps> = ({ accessToken }) => {
loading={loadingRuns}
style={{ color: "#71717a", borderColor: "#e4e4e7" }}
>
Refresh
{t("common.refresh")}
</Button>
</div>
@ -635,7 +637,9 @@ const WorkflowRuns: React.FC<WorkflowRunsProps> = ({ accessToken }) => {
locale={{
emptyText: (
<Empty
description={<span style={{ color: "#a1a1aa", fontSize: 13 }}>No workflow runs yet</span>}
description={
<span style={{ color: "#a1a1aa", fontSize: 13 }}>{t("workflowRuns.index.noRunsYet")}</span>
}
image={Empty.PRESENTED_IMAGE_SIMPLE}
/>
),
@ -689,7 +693,7 @@ const WorkflowRuns: React.FC<WorkflowRunsProps> = ({ accessToken }) => {
gap: 4,
}}
>
← close
{t("workflowRuns.index.closeDrawer")}
</button>
<Button
size="small"
@ -698,7 +702,7 @@ const WorkflowRuns: React.FC<WorkflowRunsProps> = ({ accessToken }) => {
loading={loadingDetail}
style={{ color: "#71717a", borderColor: "#e4e4e7" }}
>
Refresh
{t("common.refresh")}
</Button>
</div>
@ -715,9 +719,9 @@ const WorkflowRuns: React.FC<WorkflowRunsProps> = ({ accessToken }) => {
key: "timeline",
label: (
<span style={{ fontSize: 12, fontWeight: 500, color: "#3f3f46" }}>
Timeline
{t("workflowRuns.index.timeline")}
<span style={{ marginLeft: 6, fontSize: 11, color: "#a1a1aa", fontWeight: 400 }}>
{events.length} {events.length === 1 ? "event" : "events"}
{t("workflowRuns.index.eventCount", { count: events.length })}
</span>
</span>
),
@ -731,7 +735,7 @@ const WorkflowRuns: React.FC<WorkflowRunsProps> = ({ accessToken }) => {
key: "messages",
label: (
<span style={{ fontSize: 12, fontWeight: 500, color: "#3f3f46" }}>
Messages
{t("workflowRuns.index.messages")}
<span style={{ marginLeft: 6, fontSize: 11, color: "#a1a1aa", fontWeight: 400 }}>
{messages.length}
</span>
@ -740,7 +744,7 @@ const WorkflowRuns: React.FC<WorkflowRunsProps> = ({ accessToken }) => {
children:
messages.length === 0 ? (
<div style={{ padding: "12px 4px", color: "#a1a1aa", fontSize: 12, fontFamily: "monospace" }}>
No messages
{t("workflowRuns.index.noMessages")}
</div>
) : (
<div style={{ paddingBottom: 4 }}>

View file

@ -8492,5 +8492,25 @@
"roleInternalUser": "Internal User",
"roleInternalUserViewer": "Internal User Viewer"
}
},
"workflowRuns": {
"index": {
"pageTitle": "Workflow Runs",
"pageSubtitle": "Durable state tracking for agents and automated workflows",
"colRun": "Run",
"colType": "Type",
"colStatus": "Status",
"colCreated": "Created",
"noRunsYet": "No workflow runs yet",
"closeDrawer": "← close",
"timeline": "Timeline",
"messages": "Messages",
"eventCount_one": "{{count}} event",
"eventCount_other": "{{count}} events",
"noEvents": "No events recorded",
"noMessages": "No messages",
"less": "less",
"more": "more"
}
}
}

View file

@ -8492,5 +8492,25 @@
"roleInternalUser": "内部用户",
"roleInternalUserViewer": "内部用户(只读)"
}
},
"workflowRuns": {
"index": {
"pageTitle": "工作流运行",
"pageSubtitle": "为 Agent 和自动化工作流提供持久状态追踪",
"colRun": "运行",
"colType": "类型",
"colStatus": "状态",
"colCreated": "创建时间",
"noRunsYet": "暂无工作流运行记录",
"closeDrawer": "← 关闭",
"timeline": "时间线",
"messages": "消息",
"eventCount_one": "{{count}} 个事件",
"eventCount_other": "{{count}} 个事件",
"noEvents": "暂无事件记录",
"noMessages": "暂无消息",
"less": "收起",
"more": "展开"
}
}
}