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 57d5c7103 fix(web): localize the About tab (#6481)
57d5c7103 is described below
commit 57d5c71036abe09935cfdb0b3a6acbf32fb37270
Author: 0 <[email protected]>
AuthorDate: Thu Oct 15 20:21:08 2026 +0800
fix(web): localize the About tab (#6481)
* fix(web): localize the About tab
The nine About tab labels render as hardcoded Chinese literals, so an en
locale user still sees the Settings > About page in Chinese. Wire them
through t() and add the settings.about* keys on top of the current content
values (3.0.0, Spring Boot 4.1), plus an identity-t test so a literal
cannot creep back in silently.
Resubmission of #4803 / #5233 (original author @Wang1rrr). Neither landed
in trunk, so this localizes the tab rather than restoring a change that
was lost from it.
Fixes #5221
* docs(web): state the fact in the About tab localization test comment
The comment claimed the #4803 localization was lost in a branch fold, but
neither #4803 nor #5233 ever landed in trunk: the labels were hardcoded
Chinese literals all along. Reword it to describe what the assertions
actually pin down.
---------
Co-authored-by: lizhimins <[email protected]>
---
web/src/i18n/translations.ts | 9 +++
web/src/pages/settings/AboutTab.tsx | 92 ++++++++++++++--------
web/src/pages/settings/__tests__/AboutTab.test.tsx | 27 +++++++
3 files changed, 93 insertions(+), 35 deletions(-)
diff --git a/web/src/i18n/translations.ts b/web/src/i18n/translations.ts
index 9de093590..d101d2f76 100644
--- a/web/src/i18n/translations.ts
+++ b/web/src/i18n/translations.ts
@@ -2469,6 +2469,15 @@ const translations: Record<string, Record<Lang, string>>
= {
'settings.tabCredential': { zh: '云凭据管理', en: 'Cloud Credentials' },
'settings.tabDatasource': { zh: '数据源管理', en: 'Data Sources' },
'settings.tabAbout': { zh: '关于', en: 'About' },
+ 'settings.aboutVersion': { zh: '版本', en: 'Version' },
+ 'settings.aboutBuildCommit': { zh: '构建提交', en: 'Build commit' },
+ 'settings.aboutBuildTime': { zh: '构建时间', en: 'Build time' },
+ 'settings.aboutSupportedVersions': { zh: 'RocketMQ 支持版本', en: 'Supported
RocketMQ versions' },
+ 'settings.aboutFrontendStack': { zh: '前端框架', en: 'Frontend stack' },
+ 'settings.aboutBackendStack': { zh: '后端框架', en: 'Backend stack' },
+ 'settings.aboutRelatedLinks': { zh: '相关链接', en: 'Related links' },
+ 'settings.aboutDocs': { zh: '文档中心', en: 'Documentation' },
+ 'settings.aboutCommunity': { zh: 'RocketMQ 社区', en: 'RocketMQ community' },
'settings.dataSourceNotTested': { zh: '未检测', en: 'Not tested' },
'settings.loadFailed': {
zh: '设置加载失败,请稍后重试',
diff --git a/web/src/pages/settings/AboutTab.tsx
b/web/src/pages/settings/AboutTab.tsx
index 3042044fc..daf2cde55 100644
--- a/web/src/pages/settings/AboutTab.tsx
+++ b/web/src/pages/settings/AboutTab.tsx
@@ -18,42 +18,64 @@
import { Descriptions, Divider, Space, Typography } from 'antd';
import { BookOutlined, GithubOutlined, GlobalOutlined } from
'@ant-design/icons';
+import { useLang } from '../../i18n/LangContext';
+
const { Title, Text, Link: TypoLink } = Typography;
-export const AboutTab = () => (
- <div style={{ maxWidth: 800 }}>
- <Descriptions column={1} bordered size="small">
- <Descriptions.Item label="版本">3.0.0</Descriptions.Item>
- <Descriptions.Item label="构建提交">{__BUILD_COMMIT__}</Descriptions.Item>
- <Descriptions.Item label="构建时间">{__BUILD_TIME__}</Descriptions.Item>
- <Descriptions.Item label="RocketMQ 支持版本">4.x / 5.x</Descriptions.Item>
- <Descriptions.Item label="前端框架">React 18 + Ant Design
5</Descriptions.Item>
- <Descriptions.Item label="后端框架">Spring Boot 4.1 + RocketMQ MCP
Server</Descriptions.Item>
- <Descriptions.Item label="License">Apache 2.0</Descriptions.Item>
- </Descriptions>
-
- <Divider />
-
- <Title level={5}>相关链接</Title>
- <Space size="middle" style={{ marginBottom: 24 }}>
- <TypoLink href="https://github.com/apache/rocketmq" target="_blank"
rel="noopener noreferrer">
- <GithubOutlined /> GitHub
- </TypoLink>
- <TypoLink href="https://rocketmq.apache.org/docs/" target="_blank"
rel="noopener noreferrer">
- <BookOutlined /> 文档中心
- </TypoLink>
- <TypoLink href="https://rocketmq.apache.org/" target="_blank"
rel="noopener noreferrer">
- <GlobalOutlined /> RocketMQ 社区
- </TypoLink>
- </Space>
-
- <Divider />
-
- <Text type="secondary">
- Copyright © {__BUILD_TIME__.slice(0, 4)} Apache Software Foundation.
Licensed under the Apache
- License, Version 2.0.
- </Text>
- </div>
-);
+export const AboutTab = () => {
+ const { t } = useLang();
+
+ return (
+ <div style={{ maxWidth: 800 }}>
+ <Descriptions column={1} bordered size="small">
+ <Descriptions.Item
label={t('settings.aboutVersion')}>3.0.0</Descriptions.Item>
+ <Descriptions.Item label={t('settings.aboutBuildCommit')}>
+ {__BUILD_COMMIT__}
+ </Descriptions.Item>
+ <Descriptions.Item
label={t('settings.aboutBuildTime')}>{__BUILD_TIME__}</Descriptions.Item>
+ <Descriptions.Item label={t('settings.aboutSupportedVersions')}>
+ 4.x / 5.x
+ </Descriptions.Item>
+ <Descriptions.Item label={t('settings.aboutFrontendStack')}>
+ React 18 + Ant Design 5
+ </Descriptions.Item>
+ <Descriptions.Item label={t('settings.aboutBackendStack')}>
+ Spring Boot 4.1 + RocketMQ MCP Server
+ </Descriptions.Item>
+ <Descriptions.Item label="License">Apache 2.0</Descriptions.Item>
+ </Descriptions>
+
+ <Divider />
+
+ <Title level={5}>{t('settings.aboutRelatedLinks')}</Title>
+ <Space size="middle" style={{ marginBottom: 24 }}>
+ <TypoLink
+ href="https://github.com/apache/rocketmq"
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ <GithubOutlined /> GitHub
+ </TypoLink>
+ <TypoLink
+ href="https://rocketmq.apache.org/docs/"
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ <BookOutlined /> {t('settings.aboutDocs')}
+ </TypoLink>
+ <TypoLink href="https://rocketmq.apache.org/" target="_blank"
rel="noopener noreferrer">
+ <GlobalOutlined /> {t('settings.aboutCommunity')}
+ </TypoLink>
+ </Space>
+
+ <Divider />
+
+ <Text type="secondary">
+ Copyright © {__BUILD_TIME__.slice(0, 4)} Apache Software Foundation.
Licensed under the
+ Apache License, Version 2.0.
+ </Text>
+ </div>
+ );
+};
export default AboutTab;
diff --git a/web/src/pages/settings/__tests__/AboutTab.test.tsx
b/web/src/pages/settings/__tests__/AboutTab.test.tsx
index 0927baa35..05b044c3c 100644
--- a/web/src/pages/settings/__tests__/AboutTab.test.tsx
+++ b/web/src/pages/settings/__tests__/AboutTab.test.tsx
@@ -19,6 +19,10 @@ import { render, screen } from '@testing-library/react';
import { beforeAll, describe, expect, it, vi } from 'vitest';
import { AboutTab } from '../AboutTab';
+vi.mock('../../../i18n/LangContext', () => ({
+ useLang: () => ({ t: (key: string) => key }),
+}));
+
beforeAll(() => {
Object.defineProperty(window, 'matchMedia', {
writable: true,
@@ -48,4 +52,27 @@ describe('AboutTab', () => {
).toBeInTheDocument();
expect(screen.queryByText('2024-01-15 14:30:00')).not.toBeInTheDocument();
});
+
+ it('reads every label from the language context', () => {
+ render(<AboutTab />);
+
+ // t is mocked to identity, so a rendered key proves the label came from
the dictionary
+ // instead of a literal left in the component. Every one of these labels
was a hardcoded
+ // Chinese literal before this change, so the loop below pins the t()
wiring in place.
+ for (const key of [
+ 'settings.aboutVersion',
+ 'settings.aboutBuildCommit',
+ 'settings.aboutBuildTime',
+ 'settings.aboutSupportedVersions',
+ 'settings.aboutFrontendStack',
+ 'settings.aboutBackendStack',
+ 'settings.aboutRelatedLinks',
+ 'settings.aboutDocs',
+ 'settings.aboutCommunity',
+ ]) {
+ expect(screen.getByText(key)).toBeInTheDocument();
+ }
+ expect(screen.queryByText('版本')).not.toBeInTheDocument();
+ expect(screen.queryByText('相关链接')).not.toBeInTheDocument();
+ });
});