mirror of
https://github.com/YFGaia/dify-plus.git
synced 2026-06-12 18:11:42 +08:00
refactor(i18n): about locales (#30336)
Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
This commit is contained in:
@@ -14,15 +14,13 @@ import type { Mock } from 'vitest'
|
||||
*/
|
||||
import { renderHook } from '@testing-library/react'
|
||||
// Import after mock to get the mocked version
|
||||
import { useI18N } from '@/context/i18n'
|
||||
import { useLocale } from '@/context/i18n'
|
||||
|
||||
import { useFormatTimeFromNow } from './use-format-time-from-now'
|
||||
|
||||
// Mock the i18n context
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useI18N: vi.fn(() => ({
|
||||
locale: 'en-US',
|
||||
})),
|
||||
useLocale: vi.fn(() => 'en-US'),
|
||||
}))
|
||||
|
||||
describe('useFormatTimeFromNow', () => {
|
||||
@@ -47,7 +45,7 @@ describe('useFormatTimeFromNow', () => {
|
||||
* Should return human-readable relative time strings
|
||||
*/
|
||||
it('should format time from now in English', () => {
|
||||
;(useI18N as Mock).mockReturnValue({ locale: 'en-US' })
|
||||
;(useLocale as Mock).mockReturnValue('en-US')
|
||||
|
||||
const { result } = renderHook(() => useFormatTimeFromNow())
|
||||
|
||||
@@ -65,7 +63,7 @@ describe('useFormatTimeFromNow', () => {
|
||||
* Very recent timestamps should show seconds
|
||||
*/
|
||||
it('should format very recent times', () => {
|
||||
;(useI18N as Mock).mockReturnValue({ locale: 'en-US' })
|
||||
;(useLocale as Mock).mockReturnValue('en-US')
|
||||
|
||||
const { result } = renderHook(() => useFormatTimeFromNow())
|
||||
|
||||
@@ -81,7 +79,7 @@ describe('useFormatTimeFromNow', () => {
|
||||
* Should handle day-level granularity
|
||||
*/
|
||||
it('should format times from days ago', () => {
|
||||
;(useI18N as Mock).mockReturnValue({ locale: 'en-US' })
|
||||
;(useLocale as Mock).mockReturnValue('en-US')
|
||||
|
||||
const { result } = renderHook(() => useFormatTimeFromNow())
|
||||
|
||||
@@ -98,7 +96,7 @@ describe('useFormatTimeFromNow', () => {
|
||||
* dayjs fromNow also supports future times (e.g., "in 2 hours")
|
||||
*/
|
||||
it('should format future times', () => {
|
||||
;(useI18N as Mock).mockReturnValue({ locale: 'en-US' })
|
||||
;(useLocale as Mock).mockReturnValue('en-US')
|
||||
|
||||
const { result } = renderHook(() => useFormatTimeFromNow())
|
||||
|
||||
@@ -117,7 +115,7 @@ describe('useFormatTimeFromNow', () => {
|
||||
* Should use Chinese characters for time units
|
||||
*/
|
||||
it('should format time in Chinese (Simplified)', () => {
|
||||
;(useI18N as Mock).mockReturnValue({ locale: 'zh-Hans' })
|
||||
;(useLocale as Mock).mockReturnValue('zh-Hans')
|
||||
|
||||
const { result } = renderHook(() => useFormatTimeFromNow())
|
||||
|
||||
@@ -134,7 +132,7 @@ describe('useFormatTimeFromNow', () => {
|
||||
* Should use Spanish words for relative time
|
||||
*/
|
||||
it('should format time in Spanish', () => {
|
||||
;(useI18N as Mock).mockReturnValue({ locale: 'es-ES' })
|
||||
;(useLocale as Mock).mockReturnValue('es-ES')
|
||||
|
||||
const { result } = renderHook(() => useFormatTimeFromNow())
|
||||
|
||||
@@ -151,7 +149,7 @@ describe('useFormatTimeFromNow', () => {
|
||||
* Should use French words for relative time
|
||||
*/
|
||||
it('should format time in French', () => {
|
||||
;(useI18N as Mock).mockReturnValue({ locale: 'fr-FR' })
|
||||
;(useLocale as Mock).mockReturnValue('fr-FR')
|
||||
|
||||
const { result } = renderHook(() => useFormatTimeFromNow())
|
||||
|
||||
@@ -168,7 +166,7 @@ describe('useFormatTimeFromNow', () => {
|
||||
* Should use Japanese characters
|
||||
*/
|
||||
it('should format time in Japanese', () => {
|
||||
;(useI18N as Mock).mockReturnValue({ locale: 'ja-JP' })
|
||||
;(useLocale as Mock).mockReturnValue('ja-JP')
|
||||
|
||||
const { result } = renderHook(() => useFormatTimeFromNow())
|
||||
|
||||
@@ -185,7 +183,7 @@ describe('useFormatTimeFromNow', () => {
|
||||
* Should use pt-br locale mapping
|
||||
*/
|
||||
it('should format time in Portuguese (Brazil)', () => {
|
||||
;(useI18N as Mock).mockReturnValue({ locale: 'pt-BR' })
|
||||
;(useLocale as Mock).mockReturnValue('pt-BR')
|
||||
|
||||
const { result } = renderHook(() => useFormatTimeFromNow())
|
||||
|
||||
@@ -202,7 +200,7 @@ describe('useFormatTimeFromNow', () => {
|
||||
* Unknown locales should default to English
|
||||
*/
|
||||
it('should fallback to English for unsupported locale', () => {
|
||||
;(useI18N as Mock).mockReturnValue({ locale: 'xx-XX' as any })
|
||||
;(useLocale as Mock).mockReturnValue('xx-XX' as any)
|
||||
|
||||
const { result } = renderHook(() => useFormatTimeFromNow())
|
||||
|
||||
@@ -222,7 +220,7 @@ describe('useFormatTimeFromNow', () => {
|
||||
* Should format as a very old date
|
||||
*/
|
||||
it('should handle timestamp 0', () => {
|
||||
;(useI18N as Mock).mockReturnValue({ locale: 'en-US' })
|
||||
;(useLocale as Mock).mockReturnValue('en-US')
|
||||
|
||||
const { result } = renderHook(() => useFormatTimeFromNow())
|
||||
|
||||
@@ -238,7 +236,7 @@ describe('useFormatTimeFromNow', () => {
|
||||
* Should handle dates far in the future
|
||||
*/
|
||||
it('should handle very large timestamps', () => {
|
||||
;(useI18N as Mock).mockReturnValue({ locale: 'en-US' })
|
||||
;(useLocale as Mock).mockReturnValue('en-US')
|
||||
|
||||
const { result } = renderHook(() => useFormatTimeFromNow())
|
||||
|
||||
@@ -260,12 +258,12 @@ describe('useFormatTimeFromNow', () => {
|
||||
const oneHourAgo = now - (60 * 60 * 1000)
|
||||
|
||||
// First render with English
|
||||
;(useI18N as Mock).mockReturnValue({ locale: 'en-US' })
|
||||
;(useLocale as Mock).mockReturnValue('en-US')
|
||||
rerender()
|
||||
const englishResult = result.current.formatTimeFromNow(oneHourAgo)
|
||||
|
||||
// Second render with Spanish
|
||||
;(useI18N as Mock).mockReturnValue({ locale: 'es-ES' })
|
||||
;(useLocale as Mock).mockReturnValue('es-ES')
|
||||
rerender()
|
||||
const spanishResult = result.current.formatTimeFromNow(oneHourAgo)
|
||||
|
||||
@@ -280,7 +278,7 @@ describe('useFormatTimeFromNow', () => {
|
||||
* dayjs should automatically choose the appropriate unit
|
||||
*/
|
||||
it('should use appropriate time units for different durations', () => {
|
||||
;(useI18N as Mock).mockReturnValue({ locale: 'en-US' })
|
||||
;(useLocale as Mock).mockReturnValue('en-US')
|
||||
|
||||
const { result } = renderHook(() => useFormatTimeFromNow())
|
||||
|
||||
@@ -342,7 +340,7 @@ describe('useFormatTimeFromNow', () => {
|
||||
const oneHourAgo = now - (60 * 60 * 1000)
|
||||
|
||||
locales.forEach((locale) => {
|
||||
;(useI18N as Mock).mockReturnValue({ locale })
|
||||
;(useLocale as Mock).mockReturnValue(locale)
|
||||
|
||||
const { result } = renderHook(() => useFormatTimeFromNow())
|
||||
const formatted = result.current.formatTimeFromNow(oneHourAgo)
|
||||
@@ -360,7 +358,7 @@ describe('useFormatTimeFromNow', () => {
|
||||
* The formatTimeFromNow function should be memoized with useCallback
|
||||
*/
|
||||
it('should memoize formatTimeFromNow function', () => {
|
||||
;(useI18N as Mock).mockReturnValue({ locale: 'en-US' })
|
||||
;(useLocale as Mock).mockReturnValue('en-US')
|
||||
|
||||
const { result, rerender } = renderHook(() => useFormatTimeFromNow())
|
||||
|
||||
@@ -379,11 +377,11 @@ describe('useFormatTimeFromNow', () => {
|
||||
it('should create new function when locale changes', () => {
|
||||
const { result, rerender } = renderHook(() => useFormatTimeFromNow())
|
||||
|
||||
;(useI18N as Mock).mockReturnValue({ locale: 'en-US' })
|
||||
;(useLocale as Mock).mockReturnValue('en-US')
|
||||
rerender()
|
||||
const englishFunction = result.current.formatTimeFromNow
|
||||
|
||||
;(useI18N as Mock).mockReturnValue({ locale: 'es-ES' })
|
||||
;(useLocale as Mock).mockReturnValue('es-ES')
|
||||
rerender()
|
||||
const spanishFunction = result.current.formatTimeFromNow
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import dayjs from 'dayjs'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
import { useCallback } from 'react'
|
||||
import { useI18N } from '@/context/i18n'
|
||||
import { useLocale } from '@/context/i18n'
|
||||
import { localeMap } from '@/i18n-config/language'
|
||||
import 'dayjs/locale/de'
|
||||
import 'dayjs/locale/es'
|
||||
@@ -27,7 +27,7 @@ import 'dayjs/locale/zh-tw'
|
||||
dayjs.extend(relativeTime)
|
||||
|
||||
export const useFormatTimeFromNow = () => {
|
||||
const { locale } = useI18N()
|
||||
const locale = useLocale()
|
||||
const formatTimeFromNow = useCallback((time: number) => {
|
||||
const dayjsLocale = localeMap[locale] ?? 'en'
|
||||
return dayjs(time).locale(dayjsLocale).fromNow()
|
||||
|
||||
Reference in New Issue
Block a user