소스 검색

i18n: apply l10n selector

master
jason.lam 1 년 전
부모
커밋
afb430b981
10개의 변경된 파일236개의 추가작업 그리고 4개의 파일을 삭제
  1. +1
    -0
      package.json
  2. +47
    -0
      src/components/I18nProvider.js
  3. +5
    -2
      src/index.js
  4. +142
    -0
      src/layout/MainLayout/Header/HeaderContent/LocaleSelector.js
  5. +2
    -1
      src/layout/MainLayout/Header/HeaderContent/index.js
  6. +3
    -0
      src/layout/MainLayout/Header/index.js
  7. +6
    -1
      src/pages/authentication/auth-forms/AuthLoginCustom.js
  8. +10
    -0
      src/translations/en.json
  9. +10
    -0
      src/translations/zh-CN.json
  10. +10
    -0
      src/translations/zh-HK.json

+ 1
- 0
package.json 파일 보기

@@ -50,6 +50,7 @@
"react-to-print": "^2.14.13",
"react-toastify": "^9.1.3",
"react-window": "^1.8.7",
"react-intl": "^6.4.7",
"redux": "^4.2.0",
"simplebar": "^5.3.8",
"simplebar-react": "^2.4.1",


+ 47
- 0
src/components/I18nProvider.js 파일 보기

@@ -0,0 +1,47 @@
import React, {useState, useEffect, createContext} from 'react';
import { IntlProvider } from 'react-intl';
import enMessages from '../translations/en.json';
import cnMessages from '../translations/zh-CN.json';
import hkMessages from '../translations/zh-HK.json';

const LocaleContext = createContext();

export const I18nProvider = ({ children }) => {
const systemMessages = {
"en": enMessages,
"zh": hkMessages,
"zh-HK": hkMessages,
"zh-CN": cnMessages
};

const [locale, setLocale] = useState('en'); // Default locale, you can change this as per your requirement
const [messages, setMessages] = useState(systemMessages[locale]);

useEffect(() => {
if(localStorage.getItem('locale') === null){
//no locale case
localStorage.setItem('locale','en');
}
else{
setLocale(localStorage.getItem('locale'));
}
}, []);
useEffect(() => {
// Load the messages for the selected locale
const fetchMessages = async () => {
setMessages(systemMessages[locale]);
};

fetchMessages();
}, [locale]);

return (
<LocaleContext.Provider value={{ locale, setLocale }} >
<IntlProvider locale={locale} messages={messages}>
{children}
</IntlProvider>
</LocaleContext.Provider>
);
}

export default LocaleContext;

+ 5
- 2
src/index.js 파일 보기

@@ -16,6 +16,7 @@ import 'assets/third-party/apex-chart.css';
import App from './App';
import { store } from 'store';
import reportWebVitals from './reportWebVitals';
import {I18nProvider} from "./components/I18nProvider";

// ==============================|| MAIN - REACT DOM RENDER ||============================== //

@@ -26,9 +27,11 @@ const root = createRoot(container); // createRoot(container!) if you use TypeScr
root.render(
<StrictMode>
<ReduxProvider store={store}>
<BrowserRouter basename="/">
<I18nProvider>
<BrowserRouter basename="/">
<App />
</BrowserRouter>
</BrowserRouter>
</I18nProvider>
</ReduxProvider>
</StrictMode>
);


+ 142
- 0
src/layout/MainLayout/Header/HeaderContent/LocaleSelector.js 파일 보기

@@ -0,0 +1,142 @@
import {useContext, useRef, useState} from 'react';
import ListItem from '@mui/material/ListItem';
// material-ui
import { useTheme } from '@mui/material/styles';
import {
Box,
ClickAwayListener,
IconButton,
List,
ListItemButton,
ListItemText,
Paper,
Popper,
useMediaQuery
} from '@mui/material';

import Transitions from 'components/@extended/Transitions';
import LanguageIcon from '@mui/icons-material/Language';
import {FormattedMessage} from "react-intl";
import * as React from "react";
import LocaleContext from "../../../../components/I18nProvider";

// ==============================|| HEADER CONTENT - NOTIFICATION ||============================== //

const LocaleSelector = () => {
const theme = useTheme();
const matchesXs = useMediaQuery(theme.breakpoints.down('md'));
const { setLocale } = useContext(LocaleContext);

const anchorRef = useRef(null);
const [open, setOpen] = useState(false);
const handleToggle = () => {
setOpen((prevOpen) => !prevOpen);
};


const handleClose = (event) => {
if (anchorRef.current && anchorRef.current.contains(event.target)) {
return;
}
setOpen(false);
};

const iconBackColorOpen = 'grey.300';
const iconBackColor = 'grey.100';

return (
<Box sx={{ flexShrink: 0, ml: 0.75 }}>
<IconButton
disableRipple
color="secondary"
sx={{ color: 'text.primary', bgcolor: open ? iconBackColorOpen : iconBackColor }}
aria-label="open profile"
ref={anchorRef}
aria-controls={open ? 'profile-grow' : undefined}
aria-haspopup="true"
onClick={handleToggle}
>
<LanguageIcon />
</IconButton>
<Popper
placement={matchesXs ? 'bottom' : 'bottom-end'}
open={open}
anchorEl={anchorRef.current}
role={undefined}
transition
disablePortal
popperOptions={{
modifiers: [
{
name: 'offset',
options: {
offset: [matchesXs ? -5 : 0, 9]
}
}
]
}}
>
{({ TransitionProps }) => (
<Transitions type="fade" in={open} {...TransitionProps}>
<Paper
sx={{
boxShadow: theme.customShadows.z1,
width: '100%',
minWidth: 285,
maxWidth: 420,
[theme.breakpoints.down('md')]: {
maxWidth: 285
}
}}
>
<ClickAwayListener onClickAway={handleClose}>
<List
component="nav"
>
<ListItem disablePadding>
<ListItemButton
onClick={() => {
setLocale("en")
localStorage.setItem('locale','en');
}}
>
<ListItemText
primary= <FormattedMessage id="en"/>
/>
</ListItemButton>
</ListItem>
<ListItem disablePadding>
<ListItemButton
onClick={() => {
setLocale("zh-HK")
localStorage.setItem('locale','zh-HK');
}}
>
<ListItemText
primary= <FormattedMessage id="zh-HK"/>
/>
</ListItemButton>
</ListItem>
<ListItem disablePadding>
<ListItemButton
onClick={() => {
setLocale("zh-CN")
localStorage.setItem('locale','zh-CN');
}}
>
<ListItemText
primary= <FormattedMessage id="zh-CN"/>
/>
</ListItemButton>
</ListItem>
</List>
</ClickAwayListener>
</Paper>
</Transitions>
)}
</Popper>
</Box>
);
};

export default LocaleSelector;

+ 2
- 1
src/layout/MainLayout/Header/HeaderContent/index.js 파일 보기

@@ -7,6 +7,7 @@ import { Button ,Box } from '@mui/material';
// project import
// import Search from './Search';
import Profile from './Profile';
import LocaleSelector from "./LocaleSelector";
// import Notification from './Notification';
// import MobileSection from './MobileSection';

@@ -34,7 +35,7 @@ const HeaderContent = () => {
>
<GithubOutlined />
</IconButton> */}
<LocaleSelector/>
{/* <Notification /> */}
<Profile />
{/* <MobileSection /> */}


+ 3
- 0
src/layout/MainLayout/Header/index.js 파일 보기

@@ -50,6 +50,7 @@ import * as UrlUtils from "utils/ApiPathConst"
// import { MenuFoldOutlined,MenuOutlined } from '@ant-design/icons';
// import { AppBar } from '../../../../node_modules/@mui/material/index';
import { Link } from "react-router-dom";
import LocaleSelector from "./HeaderContent/LocaleSelector";

const drawerWidth = 240;

@@ -383,6 +384,8 @@ function Header(props) {
<ul id="navbar" width="100%" >
{logoutContent}
</ul>
<LocaleSelector/>

{/* <Profile /> */}
</Stack>
</Box>


+ 6
- 1
src/pages/authentication/auth-forms/AuthLoginCustom.js 파일 보기

@@ -43,6 +43,7 @@ import { useDispatch } from "react-redux";
import { handleLogin } from "auth/index";
import useJwt from "../../../auth/jwt/useJwt";
import { handleLogoutFunction } from 'auth/index';
import {FormattedMessage} from "react-intl";
// ============================|| FIREBASE - LOGIN ||============================ //

const AuthLoginCustom = () => {
@@ -214,7 +215,11 @@ const AuthLoginCustom = () => {
<Grid container spacing={3}>
<Grid item xs={12}>
<Stack spacing={1}>
<InputLabel htmlFor="email-login"><Typography variant="h5">用戶登入名稱</Typography></InputLabel>
<InputLabel htmlFor="email-login">
<Typography variant="h5">
<FormattedMessage id="userLoginName"/>
</Typography>
</InputLabel>
<OutlinedInput
id="username"
name="username"


+ 10
- 0
src/translations/en.json 파일 보기

@@ -0,0 +1,10 @@
{
"en": "English",
"zh-HK": "Traditional Chinese",
"zh-CN": "Simplified Chinese",

"userLoginName": "User login name",

"Dashboard": "Dashboard",
"event": "Event"
}

+ 10
- 0
src/translations/zh-CN.json 파일 보기

@@ -0,0 +1,10 @@
{
"en": "英文",
"zh-HK": "繁体中文",
"zh-CN": "简体中文",

"userLoginName": "用戶登入名稱",

"Dashboard": "仪表板",
"event": "活动"
}

+ 10
- 0
src/translations/zh-HK.json 파일 보기

@@ -0,0 +1,10 @@
{
"en": "英文",
"zh-HK": "繁體中文",
"zh-CN": "簡體中文",

"userLoginName": "用戶登入名稱",

"Dashboard": "儀表板",
"event": "活動"
}

불러오는 중...
취소
저장