mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-16 13:03:31 +08:00
Add jp / kr / zh-TW translations and wire them into the i18n runtime so the desktop app can switch among English, Simplified Chinese, Traditional Chinese, Japanese, and Korean. - new locale files jp.ts / kr.ts / zh-TW.ts with full TranslationKey coverage - register the locales in the i18n index and extend the Locale union - accept the new codes in settingsStore.getStoredLocale (default stays zh) - add language-switcher entries (简体中文 / 繁體中文 / 日本語 / 한국어) - localize chat message timestamps: Han 年月日 for zh/zh-TW/jp, Intl ko-KR for kr - extend the DATE_LOCALES map in ActivitySettings (ja-JP / ko-KR / zh-TW) - tests: formatMessageTimestamp locale branches + i18n locale resolution Korean terminology follows the Microsoft Korean localization style guide (새로 고침 / 사용·사용 안 함 / 이름 바꾸기, 합니다-style sentences). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
60 lines
2.5 KiB
TypeScript
60 lines
2.5 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { translate, type Locale } from '../i18n'
|
|
import { formatMessageTimestamp } from './formatMessageTimestamp'
|
|
|
|
const t = (locale: Locale) => (
|
|
key: Parameters<typeof translate>[1],
|
|
params?: Parameters<typeof translate>[2],
|
|
) => translate(locale, key, params)
|
|
|
|
describe('formatMessageTimestamp', () => {
|
|
const now = new Date(2026, 4, 29, 16, 0).getTime()
|
|
|
|
it('uses relative labels for recent messages', () => {
|
|
expect(formatMessageTimestamp(now - 5 * 60_000, t('zh'), 'zh', now)).toBe('5分钟前')
|
|
expect(formatMessageTimestamp(now - 2 * 60 * 60_000, t('en'), 'en', now)).toBe('2h ago')
|
|
})
|
|
|
|
it('uses weekday and clock time for recent history', () => {
|
|
const value = new Date(2026, 4, 24, 15, 50).getTime()
|
|
|
|
expect(formatMessageTimestamp(value, t('zh'), 'zh', now)).toBe('星期日15:50')
|
|
})
|
|
|
|
it('includes the calendar date for older messages', () => {
|
|
const value = new Date(2026, 3, 20, 9, 30).getTime()
|
|
|
|
expect(formatMessageTimestamp(value, t('zh'), 'zh', now)).toBe('4月20日 09:30')
|
|
})
|
|
|
|
it('formats Japanese history with Han year/month/day characters', () => {
|
|
const weekday = new Date(2026, 4, 24, 15, 50).getTime()
|
|
expect(formatMessageTimestamp(weekday, t('jp'), 'jp', now)).toContain('15:50')
|
|
|
|
const monthDay = new Date(2026, 3, 20, 9, 30).getTime()
|
|
expect(formatMessageTimestamp(monthDay, t('jp'), 'jp', now)).toBe('4月20日 09:30')
|
|
|
|
const yearMonthDay = new Date(2025, 11, 15, 9, 30).getTime()
|
|
expect(formatMessageTimestamp(yearMonthDay, t('jp'), 'jp', now)).toBe('2025年12月15日 09:30')
|
|
|
|
expect(formatMessageTimestamp(now - 5 * 60_000, t('jp'), 'jp', now)).toBe('5 分前')
|
|
})
|
|
|
|
it('formats Traditional Chinese history with Han year/month/day characters', () => {
|
|
const monthDay = new Date(2026, 3, 20, 9, 30).getTime()
|
|
expect(formatMessageTimestamp(monthDay, t('zh-TW'), 'zh-TW', now)).toBe('4月20日 09:30')
|
|
|
|
const yearMonthDay = new Date(2025, 11, 15, 9, 30).getTime()
|
|
expect(formatMessageTimestamp(yearMonthDay, t('zh-TW'), 'zh-TW', now)).toBe('2025年12月15日 09:30')
|
|
})
|
|
|
|
it('formats Korean history via Intl (ko-KR) without Han characters', () => {
|
|
const monthDay = new Date(2026, 3, 20, 9, 30).getTime()
|
|
const out = formatMessageTimestamp(monthDay, t('kr'), 'kr', now)
|
|
expect(out).toContain('09:30')
|
|
expect(out).not.toContain('月') // Korean uses 월, never the Han 月
|
|
|
|
expect(formatMessageTimestamp(now - 5 * 60_000, t('kr'), 'kr', now)).toBe('5분 전')
|
|
})
|
|
})
|