From 5a4a4052228c1e00b95a018ae59ae03c28529369 Mon Sep 17 00:00:00 2001 From: Zhao Jianing <18910855655@163.com> Date: Wed, 21 Oct 2026 14:11:14 +0800 Subject: [PATCH] fix: sticky topic navbar translates the Overview entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit useTopicNavbarScroll 对 topic_overview 卡片硬编码返回英文字符串 'Overview':中文环境下吸顶面包屑显示 "Overview / 稳健性" 中英混排, 且 TopicNavbar 图标映射里的 '概览' 分支成为死代码(其余标题均取自 卡片标题的 DOM 文本,天然本地化)。 改用 t('analyze:overview')(LineChart.tsx:45 已使用同一键)。 --- .../hooks/useTopicNavbarScroll.test.tsx | 33 +++++++++++++++++++ .../analyze/hooks/useTopicNavbarScroll.ts | 4 ++- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 apps/web/src/modules/analyze/hooks/useTopicNavbarScroll.test.tsx diff --git a/apps/web/src/modules/analyze/hooks/useTopicNavbarScroll.test.tsx b/apps/web/src/modules/analyze/hooks/useTopicNavbarScroll.test.tsx new file mode 100644 index 0000000000..8b69ad25f0 --- /dev/null +++ b/apps/web/src/modules/analyze/hooks/useTopicNavbarScroll.test.tsx @@ -0,0 +1,33 @@ +import { act, renderHook } from '@testing-library/react'; +import useTopicNavbarScroll from './useTopicNavbarScroll'; + +jest.mock('next-i18next', () => ({ + useTranslation: () => ({ t: (key: string) => `t:${key}` }), +})); + +describe('useTopicNavbarScroll', () => { + it('resolves the overview title through i18n, not a hardcoded English string', () => { + jest.useFakeTimers(); + const card = document.createElement('div'); + card.id = 'topic_overview'; + card.className = 'base-card'; + card.getBoundingClientRect = () => + ({ top: 0, bottom: 100 }) as DOMRect; + document.body.appendChild(card); + Object.defineProperty(document.documentElement, 'scrollTop', { + value: 200, + configurable: true, + writable: true, + }); + + const { result } = renderHook(() => useTopicNavbarScroll()); + act(() => { + document.dispatchEvent(new Event('scroll')); + jest.advanceTimersByTime(600); + }); + + expect(result.current.topicTitle).toBe('t:analyze:overview'); + expect(result.current.topicTitle).not.toBe('Overview'); + document.body.removeChild(card); + }); +}); diff --git a/apps/web/src/modules/analyze/hooks/useTopicNavbarScroll.ts b/apps/web/src/modules/analyze/hooks/useTopicNavbarScroll.ts index 6f3af16933..029e37a5b8 100644 --- a/apps/web/src/modules/analyze/hooks/useTopicNavbarScroll.ts +++ b/apps/web/src/modules/analyze/hooks/useTopicNavbarScroll.ts @@ -1,4 +1,5 @@ import { useEffect, useMemo, useState } from 'react'; +import { useTranslation } from 'next-i18next'; import { throttle } from 'lodash'; const isCardInView = (rect: DOMRect) => { @@ -47,6 +48,7 @@ function lookupParentSiblingH2(element: HTMLElement): HTMLElement | null { const useTopicNavbarScroll = () => { const [inViewCardId, setInViewCardId] = useState(''); + const { t } = useTranslation(); useEffect(() => { const scrollEventListener = throttle(() => { @@ -79,7 +81,7 @@ const useTopicNavbarScroll = () => { } if (inViewCardId === 'topic_overview') { - return { topicTitle: 'Overview', subTitle: '' }; + return { topicTitle: t('analyze:overview'), subTitle: '' }; } let topicTitle = '';