import { t, resolveLocale, setI18nProvider, getI18nProvider } from '../../src/i18n'; import type { I18nProvider, SupportedLocale } from '../../src/i18n'; describe('i18n Core', () => { // Save and restore the original provider let originalProvider: I18nProvider; beforeAll(() => { originalProvider = getI18nProvider(); }); afterAll(() => { setI18nProvider(originalProvider); }); describe('t() - Translation Function', () => { it('should return English translation for a valid key', () => { const result = t('en', 'voice.responses.channelLocked'); expect(result).toBe('Channel Locked! Only you and invited members can join.'); }); it('should return Korean translation for a valid key', () => { const result = t('ko', 'voice.responses.channelLocked'); expect(result).toBe('채널이 잠겼습니다! 초대된 멤버만 참여할 수 있습니다.'); }); it('should fallback to English when key is missing in target locale', () => { // en.ts has all keys, so simulate a missing key by testing a deep key // All keys should exist in ko, so this test verifies the mechanism const result = t('en', 'errorTitles.USER_INPUT'); expect(result).toBe('Please check your input'); }); it('should return the key itself when not found in any locale', () => { const result = t('en', 'nonExistent.key.path'); expect(result).toBe('nonExistent.key.path'); }); it('should interpolate template variables {{var}}', () => { const result = t('en', 'voice.channelReady', { owner: '<@123>' }); expect(result).toBe('<@123>, your temporary channel is ready! Use the dropdown menu below to manage it.'); }); it('should interpolate Korean template variables', () => { const result = t('ko', 'voice.channelReady', { owner: '<@456>' }); expect(result).toBe('<@456>, 임시 채널이 준비되었습니다! 아래 드롭다운 메뉴로 관리하세요.'); }); it('should replace multiple occurrences of the same variable', () => { // Test with a key that has a variable const result = t('en', 'voice.defaultRoomName', { username: 'TestUser' }); expect(result).toBe("TestUser's Room"); }); it('should return Korean default room name', () => { const result = t('ko', 'voice.defaultRoomName', { username: '테스터' }); expect(result).toBe('테스터의 방'); }); it('should handle error message lookups', () => { const result = t('en', 'errors.E1001.userMessage'); expect(result).toBe('The user limit value is invalid.'); }); it('should handle Korean error message lookups', () => { const result = t('ko', 'errors.E1001.userMessage'); expect(result).toBe('사용자 제한 값이 올바르지 않습니다.'); }); it('should handle error resolution lookups', () => { const result = t('en', 'errors.E1001.resolution'); expect(result).toBe('Please enter a number between 0 and 99. (0 = unlimited)'); }); }); describe('resolveLocale() - Locale Resolution', () => { it('should return default "en" when no options given', () => { const result = resolveLocale(); expect(result).toBe('en'); }); it('should prefer userLocale over guildLocale', () => { const result = resolveLocale({ userLocale: 'ko', guildLocale: 'en', discordLocale: 'en-US', }); expect(result).toBe('ko'); }); it('should use guildLocale when userLocale is null', () => { const result = resolveLocale({ userLocale: null, guildLocale: 'ko', discordLocale: 'en-US', }); expect(result).toBe('ko'); }); it('should use discordLocale when DB settings are null', () => { const result = resolveLocale({ userLocale: null, guildLocale: null, discordLocale: 'ko', }); expect(result).toBe('ko'); }); it('should normalize Discord locale "en-US" to "en"', () => { const result = resolveLocale({ userLocale: null, guildLocale: null, discordLocale: 'en-US', }); expect(result).toBe('en'); }); it('should fallback to "en" for unsupported locale', () => { const result = resolveLocale({ userLocale: 'fr', // Not supported guildLocale: null, discordLocale: 'ja', // Not supported }); expect(result).toBe('en'); }); }); describe('I18nProvider Interface - Swappable Provider', () => { it('should allow swapping to a custom provider', () => { const customProvider: I18nProvider = { get: (locale: SupportedLocale, key: string) => { if (key === 'test.key') return `Custom: ${locale}`; return undefined; }, isSupported: (locale: string): locale is SupportedLocale => locale === 'en', getSupportedLocales: () => ['en'] as const, }; setI18nProvider(customProvider); const result = t('en', 'test.key'); expect(result).toBe('Custom: en'); // Restore original setI18nProvider(originalProvider); }); it('should fallback correctly with custom provider', () => { const customProvider: I18nProvider = { get: () => undefined, isSupported: (locale: string): locale is SupportedLocale => locale === 'en', getSupportedLocales: () => ['en'] as const, }; setI18nProvider(customProvider); const result = t('en', 'unknown.key'); expect(result).toBe('unknown.key'); // Should return key as final fallback setI18nProvider(originalProvider); }); }); });