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

lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git


The following commit(s) were added to refs/heads/rocketmq-studio by this push:
     new 4e7ac54dc fix(audit): route the audit page's remaining hardcoded 
strings through the dictionary (#6480)
4e7ac54dc is described below

commit 4e7ac54dc70dc832505c2e954caacb3088f8f63b
Author: 0 <[email protected]>
AuthorDate: Thu Oct 15 18:12:43 2026 +0800

    fix(audit): route the audit page's remaining hardcoded strings through the 
dictionary (#6480)
    
    * fix(audit): take the remaining audit-page strings through the translation 
table
    
    Four error toasts (record load, summary load, cleanup, export) and the
    cleanup-window suffix rendered hardcoded Chinese on an otherwise
    localized page. They now resolve through t() with audit.* keys for both
    languages, and a test renders the page in English to pin the load toast
    and the cleanup suffix.
    
    Fixes #5223
    
    * fix(audit): cover every localized toast and keep t in the effect deps
---
 web/src/i18n/translations.ts                   | 17 +++++++++++
 web/src/pages/ops/__tests__/AuditPage.test.tsx | 41 ++++++++++++++++++++++++++
 web/src/pages/ops/audit.tsx                    | 13 ++++----
 3 files changed, 65 insertions(+), 6 deletions(-)

diff --git a/web/src/i18n/translations.ts b/web/src/i18n/translations.ts
index f7d9cf1e3..7e743b4ec 100644
--- a/web/src/i18n/translations.ts
+++ b/web/src/i18n/translations.ts
@@ -1637,6 +1637,23 @@ const translations: Record<string, Record<Lang, string>> 
= {
   'audit.cleanupDays': { zh: '清理 {n} 天之前的日志', en: 'Clean logs older than {n} 
days' },
   'audit.cleanupConfirm': { zh: '确认清理', en: 'Confirm Cleanup' },
   'audit.cleanupSuccess': { zh: '已清理 {n} 天之前的日志', en: 'Cleaned logs older than 
{n} days' },
+  'audit.loadFailed': {
+    zh: '审计日志加载失败,请稍后重试',
+    en: 'Failed to load audit logs, please retry later',
+  },
+  'audit.summaryLoadFailed': {
+    zh: '审计概览加载失败,请稍后重试',
+    en: 'Failed to load the audit summary, please retry later',
+  },
+  'audit.cleanupFailed': {
+    zh: '清理审计日志失败,请稍后重试',
+    en: 'Failed to clean audit logs, please retry later',
+  },
+  'audit.exportFailed': {
+    zh: '导出审计日志失败,请稍后重试',
+    en: 'Failed to export audit logs, please retry later',
+  },
+  'audit.cleanupDaysSuffix': { zh: '天之前的日志', en: 'days and older' },
   'audit.summaryMatched': { zh: '匹配记录', en: 'Matched Records' },
   'audit.summarySuccessRate': { zh: '成功率', en: 'Success Rate' },
   'audit.summaryOperators': { zh: '操作人数', en: 'Operators' },
diff --git a/web/src/pages/ops/__tests__/AuditPage.test.tsx 
b/web/src/pages/ops/__tests__/AuditPage.test.tsx
index fc5fd5108..283ed6e7b 100644
--- a/web/src/pages/ops/__tests__/AuditPage.test.tsx
+++ b/web/src/pages/ops/__tests__/AuditPage.test.tsx
@@ -338,6 +338,47 @@ describe('Audit page', () => {
     expect(container.querySelector('.ant-spin-spinning')).not.toBeNull();
   });
 
+  it('renders the cleanup window and the error toasts in the display 
language', async () => {
+    window.localStorage.setItem('rocketmq-studio-language', 'en');
+    const user = userEvent.setup();
+    vi.mocked(opsService.listAuditRecords).mockRejectedValueOnce(new 
Error('boom'));
+    vi.mocked(opsService.getAuditSummary).mockRejectedValueOnce(new 
Error('boom'));
+
+    renderWithProviders(<AuditPage />);
+
+    // The load failure toast and the cleanup-window suffix were hardcoded 
Chinese.
+    expect(
+      await screen.findByText('Failed to load audit logs, please retry later'),
+    ).toBeInTheDocument();
+    expect(
+      await screen.findByText('Failed to load the audit summary, please retry 
later'),
+    ).toBeInTheDocument();
+    await user.click(screen.getByRole('button', { name: /Cleanup/ }));
+    expect(await screen.findByText('days and older')).toBeInTheDocument();
+    expect(screen.queryByText('天之前的日志')).not.toBeInTheDocument();
+  });
+
+  it('renders the cleanup and export failure toasts in the display language', 
async () => {
+    window.localStorage.setItem('rocketmq-studio-language', 'en');
+    const user = userEvent.setup();
+    vi.mocked(opsService.cleanupAuditLogs).mockRejectedValueOnce(new 
Error('boom'));
+    vi.mocked(opsService.exportAuditLogs).mockRejectedValueOnce(new 
Error('boom'));
+
+    renderWithProviders(<AuditPage />);
+    expect(await screen.findByText('topic-a')).toBeInTheDocument();
+
+    await user.click(screen.getByRole('button', { name: /export/i }));
+    expect(
+      await screen.findByText('Failed to export audit logs, please retry 
later'),
+    ).toBeInTheDocument();
+
+    await user.click(screen.getByRole('button', { name: /cleanup/i }));
+    await user.click(await screen.findByRole('button', { name: /confirm 
cleanup/i }));
+    expect(
+      await screen.findByText('Failed to clean audit logs, please retry 
later'),
+    ).toBeInTheDocument();
+  });
+
   it('ignores stale filter-option responses after cleanup refreshes', async () 
=> {
     const user = userEvent.setup();
     const staleOptions = deferred<Awaited<ReturnType<typeof 
opsService.getAuditFilterOptions>>>();
diff --git a/web/src/pages/ops/audit.tsx b/web/src/pages/ops/audit.tsx
index 5a8533ac3..bee2c6ac5 100644
--- a/web/src/pages/ops/audit.tsx
+++ b/web/src/pages/ops/audit.tsx
@@ -165,7 +165,7 @@ const AuditPage: React.FC = () => {
       })
       .catch(() => {
         if (recordsRequestRef.current === requestId) {
-          message.error('审计日志加载失败,请稍后重试');
+          message.error(t('audit.loadFailed'));
         }
       })
       .finally(() => {
@@ -181,6 +181,7 @@ const AuditPage: React.FC = () => {
     dateRange,
     resultFilter,
     refreshKey,
+    t,
   ]);
 
   useEffect(
@@ -224,7 +225,7 @@ const AuditPage: React.FC = () => {
         if (!cancelled) setSummary(value);
       })
       .catch(() => {
-        if (!cancelled) message.error('审计概览加载失败,请稍后重试');
+        if (!cancelled) message.error(t('audit.summaryLoadFailed'));
       })
       .finally(() => {
         if (!cancelled) setSummaryLoading(false);
@@ -232,7 +233,7 @@ const AuditPage: React.FC = () => {
     return () => {
       cancelled = true;
     };
-  }, [activeFilter, refreshKey]);
+  }, [activeFilter, refreshKey, t]);
 
   const { Text } = Typography;
 
@@ -302,7 +303,7 @@ const AuditPage: React.FC = () => {
       message.success(t('audit.cleanupSuccess', { n: cleanupDays }));
       setCleanupModalOpen(false);
     } catch {
-      message.error('清理审计日志失败,请稍后重试');
+      message.error(t('audit.cleanupFailed'));
     } finally {
       cleanupInFlightRef.current = false;
       setCleaning(false);
@@ -316,7 +317,7 @@ const AuditPage: React.FC = () => {
       const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
       downloadBlob(blob, 
`rocketmq-audit-logs-${dayjs().format('YYYY-MM-DD')}.csv`);
     } catch {
-      message.error('导出审计日志失败,请稍后重试');
+      message.error(t('audit.exportFailed'));
     } finally {
       setExporting(false);
     }
@@ -601,7 +602,7 @@ const AuditPage: React.FC = () => {
               value={cleanupDays}
               onChange={(v) => setCleanupDays(v ?? 30)}
             />
-            <span>天之前的日志</span>
+            <span>{t('audit.cleanupDaysSuffix')}</span>
           </Flex>
         </Flex>
       </Modal>

Reply via email to