Skip to content

Commit fb3e276

Browse files
authored
feat: Save Selected Language in Local Storage (#1131)
1 parent 773958b commit fb3e276

File tree

2 files changed

+60
-65
lines changed

2 files changed

+60
-65
lines changed

src/layout/ThemeContext.tsx

Lines changed: 60 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,73 +3,91 @@ import { enUS, heIL } from '@mui/material/locale'
33
import { LocalizationProvider } from '@mui/x-date-pickers'
44
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'
55
import { enUS as dateEnUS, heIL as dateHeIL } from '@mui/x-date-pickers/locales'
6-
import { ConfigProvider, theme } from 'antd'
6+
import { ConfigProvider, ConfigProviderProps, theme as antdlgorithm } from 'antd'
7+
import antdEnUS from 'antd/es/locale/en_US'
78
import antdHeIL from 'antd/es/locale/he_IL'
8-
import { FC, PropsWithChildren, createContext, useContext, useMemo } from 'react'
9+
import {
10+
PropsWithChildren,
11+
createContext,
12+
useCallback,
13+
useContext,
14+
useEffect,
15+
useMemo,
16+
} from 'react'
917
import { useTranslation } from 'react-i18next'
18+
import { useLocalStorage } from 'usehooks-ts'
1019
import dayjs from 'src/dayjs'
11-
import { useLocalStorage } from 'src/locale/useLocalStorage'
1220

1321
export interface ThemeContextInterface {
1422
toggleTheme: () => void
1523
toggleLanguage: () => void
1624
isDarkTheme?: boolean
1725
}
1826

19-
const ThemeContext = createContext({} as ThemeContextInterface)
27+
const ThemeContext = createContext<ThemeContextInterface>({} as ThemeContextInterface)
2028

21-
const { defaultAlgorithm, darkAlgorithm } = theme
22-
23-
export const ThemeProvider: FC<PropsWithChildren> = ({ children }) => {
24-
const [isDarkTheme, setIsDarkTheme] = useLocalStorage<boolean>('isDarkTheme')
29+
export const ThemeProvider = ({ children }: PropsWithChildren) => {
30+
const [isDarkTheme, setIsDarkTheme] = useLocalStorage<boolean>('isDarkTheme', false)
31+
const [language, setLanguage] = useLocalStorage<string>('language', 'he')
2532
const { i18n } = useTranslation()
2633

27-
const toggleTheme = () => {
28-
setIsDarkTheme((prevTheme: boolean) => !prevTheme)
29-
}
34+
const toggleTheme = useCallback(() => setIsDarkTheme((prev) => !prev), [setIsDarkTheme])
3035

31-
const toggleLanguage = () => {
32-
const newLanguage = i18n.language === 'en' ? 'he' : 'en'
36+
const toggleLanguage = useCallback(() => {
37+
const newLanguage = language === 'en' ? 'he' : 'en'
38+
setLanguage(newLanguage)
3339
i18n.changeLanguage(newLanguage)
34-
}
40+
}, [language, i18n, setLanguage])
41+
42+
const contextValue = useMemo(
43+
() => ({
44+
isDarkTheme,
45+
toggleLanguage,
46+
toggleTheme,
47+
}),
48+
[isDarkTheme, toggleLanguage, toggleTheme],
49+
)
3550

36-
const contextValue = {
37-
isDarkTheme,
38-
toggleLanguage,
39-
toggleTheme,
40-
}
51+
useEffect(() => {
52+
const forceLang = language === 'en' ? 'en' : 'he'
53+
if (i18n.language !== forceLang) i18n.changeLanguage(forceLang)
54+
if (language !== forceLang) setLanguage(forceLang)
55+
}, [language, i18n, setLanguage])
4156

42-
// Re-create the theme when the theme changes or the language changes
43-
const theme = useMemo(() => {
44-
const direction = i18n.language === 'he' ? 'rtl' : 'ltr'
57+
const muiTheme = useMemo(() => {
58+
const isEnglish = language === 'en'
59+
const direction = isEnglish ? 'ltr' : 'rtl'
4560
document.documentElement.dir = direction
46-
document.documentElement.lang = i18n.language
47-
dayjs.locale(i18n.language)
61+
document.documentElement.lang = language || 'he'
62+
dayjs.locale(language)
4863
return createTheme(
4964
{
5065
direction,
51-
palette: {
52-
mode: isDarkTheme ? 'dark' : 'light',
53-
},
66+
palette: { mode: isDarkTheme ? 'dark' : 'light' },
5467
},
55-
i18n.language === 'he' ? heIL : enUS,
56-
i18n.language === 'he' ? dateHeIL : dateEnUS,
68+
isEnglish ? enUS : heIL,
69+
isEnglish ? dateEnUS : dateHeIL,
5770
)
58-
}, [isDarkTheme, i18n.language])
71+
}, [isDarkTheme, language])
72+
73+
const antdTheme = useMemo<ConfigProviderProps>(() => {
74+
return {
75+
direction: language === 'en' ? 'ltr' : 'rtl',
76+
locale: language === 'en' ? antdEnUS : antdHeIL,
77+
theme: {
78+
algorithm: isDarkTheme ? antdlgorithm.darkAlgorithm : antdlgorithm.defaultAlgorithm,
79+
token: {
80+
colorBgBase: isDarkTheme ? '#1c1d1c' : '#ffffff',
81+
colorTextBase: isDarkTheme ? '#ffffff' : '#000000',
82+
},
83+
},
84+
}
85+
}, [isDarkTheme, language])
5986

6087
return (
61-
<LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale={i18n.language}>
62-
<ConfigProvider
63-
direction={i18n.language === 'he' ? 'rtl' : 'ltr'}
64-
locale={antdHeIL}
65-
theme={{
66-
algorithm: isDarkTheme ? darkAlgorithm : defaultAlgorithm,
67-
token: {
68-
colorBgBase: isDarkTheme ? '#1c1d1c' : '#ffffff',
69-
colorTextBase: isDarkTheme ? '#ffffff' : '#000000',
70-
},
71-
}}>
72-
<MuiThemeProvider theme={theme}>
88+
<LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale={language}>
89+
<ConfigProvider {...antdTheme}>
90+
<MuiThemeProvider theme={muiTheme}>
7391
<ScopedCssBaseline enableColorScheme>
7492
<ThemeContext.Provider value={contextValue}>{children}</ThemeContext.Provider>
7593
</ScopedCssBaseline>

src/locale/useLocalStorage.ts

Lines changed: 0 additions & 23 deletions
This file was deleted.

0 commit comments

Comments
 (0)