mirror of
https://github.com/iflytek/skillhub.git
synced 2026-09-24 00:55:35 +00:00
fix(web): align language switcher fallback
This commit is contained in:
parent
c888be7212
commit
0d4f149e8a
3 changed files with 67 additions and 14 deletions
|
|
@ -1,12 +0,0 @@
|
|||
import { describe, expect, it } from 'vitest'
|
||||
import * as mod from './language-switcher'
|
||||
|
||||
/**
|
||||
* LanguageSwitcher renders an in-tree locale menu (no Radix portal) driven by i18next.
|
||||
* There are no exported pure helpers; verify the export contract only.
|
||||
*/
|
||||
describe('language-switcher module exports', () => {
|
||||
it('exports the LanguageSwitcher component', () => {
|
||||
expect(mod.LanguageSwitcher).toBeTypeOf('function')
|
||||
})
|
||||
})
|
||||
64
web/src/shared/components/language-switcher.test.tsx
Normal file
64
web/src/shared/components/language-switcher.test.tsx
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
// @vitest-environment jsdom
|
||||
|
||||
import { cleanup, fireEvent, render, screen } from '@testing-library/react'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { LanguageSwitcher } from './language-switcher'
|
||||
|
||||
const mockI18n = vi.hoisted(() => ({
|
||||
language: undefined as string | undefined,
|
||||
resolvedLanguage: undefined as string | undefined,
|
||||
changeLanguage: vi.fn(),
|
||||
}))
|
||||
|
||||
vi.mock('react-i18next', () => ({
|
||||
useTranslation: () => ({ i18n: mockI18n }),
|
||||
}))
|
||||
|
||||
describe('LanguageSwitcher', () => {
|
||||
beforeEach(() => {
|
||||
mockI18n.language = undefined
|
||||
mockI18n.resolvedLanguage = undefined
|
||||
mockI18n.changeLanguage.mockImplementation((language: string) => {
|
||||
mockI18n.language = language
|
||||
mockI18n.resolvedLanguage = language
|
||||
return Promise.resolve()
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
cleanup()
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
it('exports the LanguageSwitcher component', () => {
|
||||
expect(LanguageSwitcher).toBeTypeOf('function')
|
||||
})
|
||||
|
||||
it('falls back to English when i18next has not resolved a language yet', () => {
|
||||
render(<LanguageSwitcher />)
|
||||
|
||||
expect(screen.getByRole('button', { name: /English/i })).toBeTruthy()
|
||||
})
|
||||
|
||||
it('uses the resolved language before the raw detected language', () => {
|
||||
mockI18n.language = 'zh-CN'
|
||||
mockI18n.resolvedLanguage = 'en'
|
||||
|
||||
render(<LanguageSwitcher />)
|
||||
|
||||
expect(screen.getByRole('button', { name: /English/i })).toBeTruthy()
|
||||
})
|
||||
|
||||
it('updates the displayed language after selecting English', () => {
|
||||
mockI18n.language = 'zh'
|
||||
mockI18n.resolvedLanguage = 'zh'
|
||||
|
||||
render(<LanguageSwitcher />)
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: /中文/i }))
|
||||
fireEvent.click(screen.getByRole('menuitem', { name: /English/i }))
|
||||
|
||||
expect(mockI18n.changeLanguage).toHaveBeenCalledWith('en')
|
||||
expect(screen.getByRole('button', { name: /English/i })).toBeTruthy()
|
||||
})
|
||||
})
|
||||
|
|
@ -27,9 +27,10 @@ export function LanguageSwitcher({ className }: LanguageSwitcherProps) {
|
|||
{ code: 'ru', name: 'Русский' },
|
||||
]
|
||||
|
||||
const fallbackLanguage = languages.find((lang) => lang.code === 'en') ?? languages[0]
|
||||
// Primary language code only (strip region, e.g. ru-RU → ru).
|
||||
const currentLangCode = i18n.language?.split('-')[0] || 'zh'
|
||||
const currentLanguage = languages.find((lang) => lang.code === currentLangCode) || languages[0]
|
||||
const currentLangCode = (i18n.resolvedLanguage || i18n.language || fallbackLanguage.code).split('-')[0]
|
||||
const currentLanguage = languages.find((lang) => lang.code === currentLangCode) || fallbackLanguage
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue