1
1
import {
2
2
currentSupportedLanguages ,
3
3
dayjsLocaleImportMap ,
4
- defaultNS ,
5
4
} from "@renderer/@types/constants"
6
5
import { defaultResources } from "@renderer/@types/default-resource"
7
- import { getGeneralSettings } from "@renderer/atoms/settings/general"
8
- import { i18nAtom } from "@renderer/i18n"
6
+ import { getGeneralSettings , setGeneralSetting } from "@renderer/atoms/settings/general"
7
+ import { fallbackLanguage , i18nAtom , LocaleCache } from "@renderer/i18n"
9
8
import { EventBus } from "@renderer/lib/event-bus"
10
9
import { jotaiStore } from "@renderer/lib/jotai"
11
10
import { isEmptyObject } from "@renderer/lib/utils"
12
11
import dayjs from "dayjs"
13
12
import i18next from "i18next"
13
+ import LanguageDetector from "i18next-browser-languagedetector"
14
14
import { useAtom } from "jotai"
15
15
import type { FC , PropsWithChildren } from "react"
16
16
import { useEffect , useLayoutEffect , useRef } from "react"
17
17
import { I18nextProvider } from "react-i18next"
18
18
import { toast } from "sonner"
19
19
20
20
const loadingLangLock = new Set < string > ( )
21
+ const loadedLangs = new Set < string > ( [ fallbackLanguage ] )
21
22
22
23
const langChangedHandler = async ( lang : string ) => {
23
24
const dayjsImport = dayjsLocaleImportMap [ lang ]
@@ -35,7 +36,7 @@ const langChangedHandler = async (lang: string) => {
35
36
if ( ! isSupport ) {
36
37
return
37
38
}
38
- const loaded = i18next . getResourceBundle ( lang , defaultNS )
39
+ const loaded = loadedLangs . has ( lang )
39
40
40
41
if ( loaded ) {
41
42
return
@@ -68,8 +69,8 @@ const langChangedHandler = async (lang: string) => {
68
69
}
69
70
}
70
71
} else {
71
- const res = await import ( ` /locales/${ lang } .js`)
72
- . then ( ( res ) => res ?. default || res )
72
+ const res = await eval ( `import(' /locales/${ lang } .js') `)
73
+ . then ( ( res : any ) => res ?. default || res )
73
74
. catch ( ( ) => {
74
75
toast . error ( `${ t ( "common:tips.load-lng-error" ) } : ${ lang } ` )
75
76
loadingLangLock . delete ( lang )
@@ -86,10 +87,10 @@ const langChangedHandler = async (lang: string) => {
86
87
87
88
await i18next . reloadResources ( )
88
89
await i18next . changeLanguage ( lang )
90
+ LocaleCache . shared . set ( lang )
91
+ loadedLangs . add ( lang )
89
92
loadingLangLock . delete ( lang )
90
93
}
91
-
92
- langChangedHandler ( getGeneralSettings ( ) . language )
93
94
export const I18nProvider : FC < PropsWithChildren > = ( { children } ) => {
94
95
const [ currentI18NInstance , update ] = useAtom ( i18nAtom )
95
96
@@ -108,6 +109,18 @@ export const I18nProvider: FC<PropsWithChildren> = ({ children }) => {
108
109
)
109
110
110
111
const callOnce = useRef ( false )
112
+ const detectOnce = useRef ( false )
113
+ useLayoutEffect ( ( ) => {
114
+ if ( detectOnce . current ) return
115
+ const languageDetector = new LanguageDetector ( )
116
+ const userLang = languageDetector . detect ( )
117
+ if ( ! userLang ) return
118
+ const firstUserLang = Array . isArray ( userLang ) ? userLang [ 0 ] : userLang
119
+ if ( currentSupportedLanguages . includes ( firstUserLang ) ) {
120
+ setGeneralSetting ( "language" , firstUserLang )
121
+ }
122
+ detectOnce . current = true
123
+ } , [ ] )
111
124
112
125
useLayoutEffect ( ( ) => {
113
126
const i18next = currentI18NInstance
0 commit comments