/** * i18n.ts 国际化模块单元测试 */ import { describe, it, expect, beforeEach } from 'vitest'; import { t, setLocale, getLocale } from '../src/i18n'; describe('setLocale / getLocale', () => { beforeEach(() => { setLocale('zh-CN'); }); it('默认语言为 zh-CN', () => { expect(getLocale()).toBe('zh-CN'); }); it('切换为英文', () => { setLocale('en'); expect(getLocale()).toBe('en'); }); it('匹配语言前缀(zh → zh-CN)', () => { setLocale('zh'); expect(getLocale()).toBe('zh-CN'); }); it('未知语言保持默认 zh-CN', () => { setLocale('fr'); expect(getLocale()).toBe('zh-CN'); }); }); describe('t()', () => { beforeEach(() => { setLocale('zh-CN'); }); it('返回中文翻译', () => { expect(t('send')).toBe('发送'); expect(t('close')).toBe('关闭'); }); it('切换英文后返回英文翻译', () => { setLocale('en'); expect(t('send')).toBe('Send'); expect(t('close')).toBe('Close'); }); it('未知 key 返回 key 本身', () => { expect(t('nonexistent_key')).toBe('nonexistent_key'); }); it('支持插值参数替换', () => { setLocale('zh-CN'); expect(t('source_count', { n: 3 })).toBe('3 条参考来源'); }); it('英文插值参数替换', () => { setLocale('en'); expect(t('source_count', { n: 5 })).toBe('5 source(s)'); }); it('中英文字典 key 数量一致', () => { // 验证中英文字典完整性:所有中文 key 在英文中都有对应 setLocale('zh-CN'); const zhKeys = Object.keys(getAllKeys('zh-CN')); setLocale('en'); const enKeys = Object.keys(getAllKeys('en')); // 每个中文 key 在英文字典中也应存在 for (const key of zhKeys) { setLocale('en'); const translated = t(key); expect(translated).not.toBe(key); // 不应回退到 key 本身 } }); }); /** 辅助函数:获取指定语言的所有 key(通过遍历测试已知 key) */ function getAllKeys(_locale: string): Record { const knownKeys = [ 'title', 'minimize', 'close', 'status_online', 'welcome_title', 'welcome_desc', 'placeholder', 'send', 'stop', 'new_message', 'copy', 'copied', 'retry', 'loading', 'stream_interrupted', 'category_all', 'source_count', 'clear', 'clear_confirm', 'history_title', 'history_empty', 'history_search', 'feedback_up', 'feedback_down', 'teaser_text', 'new_msg_announce', 'error_network', 'error_timeout', 'error_send', 'history_group_today', 'history_group_yesterday', 'history_group_week', 'history_group_earlier', ]; const result: Record = {}; for (const key of knownKeys) { result[key] = t(key); } return result; }