Skip to content

Commit e8948af

Browse files
author
Developer
committed
fix: add i18n to PITRDetailPage
1 parent ac8e272 commit e8948af

1 file changed

Lines changed: 50 additions & 35 deletions

File tree

web/src/pages/pitr/PITRDetailPage.tsx

Lines changed: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,13 @@ import {
55
} from 'antd';
66
import { ArrowLeftOutlined } from '@ant-design/icons';
77
import dayjs from 'dayjs';
8+
import relativeTime from 'dayjs/plugin/relativeTime';
9+
import 'dayjs/locale/zh-cn';
10+
import { useLocale } from '../../hooks/useLocale';
811
import { getPITRStatus } from '../../api/pitr';
912

13+
dayjs.extend(relativeTime);
14+
1015
const { Title, Text } = Typography;
1116

1217
const stateColors: Record<string, 'processing' | 'success' | 'error' | 'default'> = {
@@ -20,9 +25,19 @@ const stateColors: Record<string, 'processing' | 'success' | 'error' | 'default'
2025
cancelled: 'default',
2126
};
2227

28+
function fmtTime(ts: string | undefined | null): string {
29+
if (!ts) return '-';
30+
const d = dayjs(ts);
31+
if (!d.isValid() || d.year() < 2000) return '-';
32+
const daysDiff = dayjs().diff(d, 'day');
33+
if (daysDiff < 7) return d.locale('zh-cn').fromNow();
34+
return d.format('YYYY年M月D日 HH:mm');
35+
}
36+
2337
export default function PITRDetailPage() {
2438
const { id } = useParams<{ id: string }>();
2539
const navigate = useNavigate();
40+
const { t } = useLocale();
2641

2742
const { data: operation, isLoading, error } = useQuery({
2843
queryKey: ['pitr-status', id],
@@ -38,18 +53,18 @@ export default function PITRDetailPage() {
3853
});
3954

4055
if (isLoading) {
41-
return <div style={{ textAlign: 'center', padding: 48 }}><Spin size="large" tip="Loading operation..." /></div>;
56+
return <div style={{ textAlign: 'center', padding: 48 }}><Spin size="large" tip={t('pitr.loadingPreview')} /></div>;
4257
}
4358

4459
if (error || !operation) {
4560
return (
4661
<Card>
4762
<div style={{ textAlign: 'center', padding: 48 }}>
48-
<Typography.Text type="danger">Failed to load operation details.</Typography.Text>
63+
<Typography.Text type="danger">{t('common.error')}</Typography.Text>
4964
<br /><br />
5065
<Space>
51-
<Button onClick={() => navigate(-1)}>Go Back</Button>
52-
<Button onClick={() => navigate('/audit')}>Audit Log</Button>
66+
<Button onClick={() => navigate(-1)}>{t('pitr.stepBack')}</Button>
67+
<Button onClick={() => navigate('/audit')}>{t('audit.title')}</Button>
5368
</Space>
5469
</div>
5570
</Card>
@@ -69,43 +84,43 @@ export default function PITRDetailPage() {
6984
<Card>
7085
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 24 }}>
7186
<div>
72-
<Title level={4} style={{ margin: 0 }}>PITR Operation Detail</Title>
87+
<Title level={4} style={{ margin: 0 }}>{t('pitr.detail')}</Title>
7388
<Text type="secondary">ID: {operation.id}</Text>
7489
</div>
7590
<Badge status={stateColor} text={operation.state} />
7691
</div>
7792

7893
<Descriptions bordered column={1}>
79-
<Descriptions.Item label="Operation ID">{operation.id}</Descriptions.Item>
80-
<Descriptions.Item label="Agent ID">{operation.agentId}</Descriptions.Item>
81-
<Descriptions.Item label="Target Table">{operation.targetTable}</Descriptions.Item>
82-
<Descriptions.Item label="Recovery Time">
94+
<Descriptions.Item label={t('audit.operationId')}>{operation.id}</Descriptions.Item>
95+
<Descriptions.Item label={t('audit.agentId')}>{operation.agentId}</Descriptions.Item>
96+
<Descriptions.Item label={t('pitr.targetTable')}>{operation.targetTable}</Descriptions.Item>
97+
<Descriptions.Item label={t('pitr.recoveryTime')}>
8398
{dayjs(operation.recoveryTime).format('YYYY-MM-DD HH:mm:ss')}
8499
</Descriptions.Item>
85-
<Descriptions.Item label="Mode">{operation.mode}</Descriptions.Item>
86-
<Descriptions.Item label="State">
100+
<Descriptions.Item label={t('pitr.mode')}>{operation.mode}</Descriptions.Item>
101+
<Descriptions.Item label={t('pitr.state')}>
87102
<Tag color={stateColor}>{operation.state}</Tag>
88103
</Descriptions.Item>
89-
<Descriptions.Item label="Created At">
104+
<Descriptions.Item label={t('pitr.createdAt')}>
90105
{dayjs(operation.createdAt).format('YYYY-MM-DD HH:mm:ss')}
91106
</Descriptions.Item>
92-
<Descriptions.Item label="Updated At">
107+
<Descriptions.Item label="更新时间">
93108
{dayjs(operation.updatedAt).format('YYYY-MM-DD HH:mm:ss')}
94109
</Descriptions.Item>
95110
</Descriptions>
96111

97112
{operation.preflightResult && (
98-
<Card size="small" title="Preflight Results" style={{ marginTop: 16 }}>
113+
<Card size="small" title={t('pitr.preflightCompleted')} style={{ marginTop: 16 }}>
99114
<Descriptions bordered column={1} size="small">
100-
<Descriptions.Item label="Binlog Files">
115+
<Descriptions.Item label={t('pitr.binlogFiles')}>
101116
{operation.preflightResult.binlogFiles?.join(', ') || '-'}
102117
</Descriptions.Item>
103-
<Descriptions.Item label="Earliest Time">
118+
<Descriptions.Item label={t('pitr.earliestTime')}>
104119
{operation.preflightResult.earliestTime
105120
? dayjs(operation.preflightResult.earliestTime).format('YYYY-MM-DD HH:mm:ss')
106121
: '-'}
107122
</Descriptions.Item>
108-
<Descriptions.Item label="Estimated Size">
123+
<Descriptions.Item label={t('pitr.estimatedSize')}>
109124
{operation.preflightResult.estimatedSize
110125
? `${(operation.preflightResult.estimatedSize / 1024 / 1024).toFixed(1)} MB`
111126
: '-'}
@@ -115,16 +130,16 @@ export default function PITRDetailPage() {
115130
)}
116131

117132
{operation.parseResult && (
118-
<Card size="small" title="Parse Results" style={{ marginTop: 16 }}>
133+
<Card size="small" title={t('pitr.estimatedChanges')} style={{ marginTop: 16 }}>
119134
<Descriptions bordered column={1} size="small">
120-
<Descriptions.Item label="Rows Affected">
135+
<Descriptions.Item label={t('pitr.rowsAffected')}>
121136
{operation.parseResult.rowsAffected?.toLocaleString() || '0'}
122137
</Descriptions.Item>
123138
</Descriptions>
124139

125140
{operation.parseResult.reverseSql && operation.parseResult.reverseSql.length > 0 ? (
126141
<div style={{ marginTop: 16 }}>
127-
<Text strong style={{ marginBottom: 8, display: 'block' }}>Reverse SQL</Text>
142+
<Text strong style={{ marginBottom: 8, display: 'block' }}>{t('pitr.sampleSql')}</Text>
128143
<Table
129144
dataSource={operation.parseResult.reverseSql}
130145
rowKey="sequence"
@@ -138,7 +153,7 @@ export default function PITRDetailPage() {
138153
width: 40,
139154
},
140155
{
141-
title: 'Type',
156+
title: {t('pitr.mode')},
142157
dataIndex: 'sqlType',
143158
key: 'sqlType',
144159
width: 80,
@@ -148,13 +163,13 @@ export default function PITRDetailPage() {
148163
},
149164
},
150165
{
151-
title: 'Table',
166+
title: {t('pitr.targetTable')},
152167
dataIndex: 'tableName',
153168
key: 'tableName',
154169
width: 120,
155170
},
156171
{
157-
title: 'Reverse SQL',
172+
title: {t('pitr.sampleSql')},
158173
dataIndex: 'reverseSql',
159174
key: 'reverseSql',
160175
ellipsis: true,
@@ -165,7 +180,7 @@ export default function PITRDetailPage() {
165180
),
166181
},
167182
{
168-
title: 'Rows',
183+
title: {t('pitr.rowsAffected')},
169184
dataIndex: 'rowsAffected',
170185
key: 'rowsAffected',
171186
width: 60,
@@ -175,7 +190,7 @@ export default function PITRDetailPage() {
175190
</div>
176191
) : operation.parseResult.sqlSample ? (
177192
<div style={{ marginTop: 16 }}>
178-
<Text strong style={{ marginBottom: 8, display: 'block' }}>SQL Sample</Text>
193+
<Text strong style={{ marginBottom: 8, display: 'block' }}>{t('pitr.sampleSql')}</Text>
179194
<pre style={{
180195
background: '#f5f5f5',
181196
padding: 8,
@@ -190,22 +205,22 @@ export default function PITRDetailPage() {
190205
</div>
191206
) : (
192207
<div style={{ marginTop: 16 }}>
193-
<Text type="secondary">No reverse SQL available</Text>
208+
<Text type="secondary">{t('common.noData')}</Text>
194209
</div>
195210
)}
196211
</Card>
197212
)}
198213

199214
{operation.execResult && (
200-
<Card size="small" title="Execution Results" style={{ marginTop: 16 }}>
215+
<Card size="small" title={t('pitr.executingRecovery')} style={{ marginTop: 16 }}>
201216
<Descriptions bordered column={1} size="small">
202-
<Descriptions.Item label="Rows Restored">
217+
<Descriptions.Item label={t('pitr.rowsRestored')}>
203218
{operation.execResult.rowsRestored?.toLocaleString() || '0'}
204219
</Descriptions.Item>
205-
<Descriptions.Item label="Duration">
220+
<Descriptions.Item label={t('pitr.duration')}>
206221
{operation.execResult.duration || '-'}
207222
</Descriptions.Item>
208-
<Descriptions.Item label="Executed At">
223+
<Descriptions.Item label={t('pitr.createdAt')}>
209224
{operation.execResult.executedAt
210225
? dayjs(operation.execResult.executedAt).format('YYYY-MM-DD HH:mm:ss')
211226
: '-'}
@@ -215,21 +230,21 @@ export default function PITRDetailPage() {
215230
)}
216231

217232
{operation.error && (
218-
<Card size="small" title="Error" style={{ marginTop: 16 }}>
233+
<Card size="small" title={t('common.error')} style={{ marginTop: 16 }}>
219234
<Text type="danger">{operation.error}</Text>
220235
</Card>
221236
)}
222237

223238
{operation.progress && (
224-
<Card size="small" title="Progress" style={{ marginTop: 16 }}>
239+
<Card size="small" title={t('pitr.batchProgress')} style={{ marginTop: 16 }}>
225240
<Descriptions bordered column={1} size="small">
226-
<Descriptions.Item label="Batches">
241+
<Descriptions.Item label={t('pitr.batches')}>
227242
{operation.progress.batchesComplete} / {operation.progress.batchesTotal}
228243
</Descriptions.Item>
229-
<Descriptions.Item label="Rows Restored">
244+
<Descriptions.Item label={t('pitr.rowsRestored')}>
230245
{operation.progress.rowsRestored?.toLocaleString() || '0'}
231246
</Descriptions.Item>
232-
<Descriptions.Item label="Estimated Remaining">
247+
<Descriptions.Item label={t('pitr.estRemaining')}>
233248
{operation.progress.estimatedRemaining || '-'}
234249
</Descriptions.Item>
235250
</Descriptions>

0 commit comments

Comments
 (0)