Implementing I18N
This commit is contained in:
@@ -8,8 +8,10 @@ import * as React from "react";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Box from "@mui/material/Box";
|
||||
import Stack from "@mui/material/Stack";
|
||||
import { useTranslation } from "@refinedev/core";
|
||||
|
||||
export const Login = () => {
|
||||
const { translate } = useTranslation();
|
||||
const [searchParams] = useSearchParams();
|
||||
if (searchParams.get("oauth") == "success") {
|
||||
const redirect_to = localStorage.getItem("redirect_after_login")
|
||||
@@ -24,12 +26,12 @@ export const Login = () => {
|
||||
rememberMe={false}
|
||||
providers={[{
|
||||
name: "google",
|
||||
label: "Sign in with Google",
|
||||
label: translate("pages.login.oauth.google"),
|
||||
icon: (<GoogleIcon style={{ fontSize: 24, }} />),
|
||||
},
|
||||
{
|
||||
name: "discord",
|
||||
label: "Sign in with Discord",
|
||||
label: translate("pages.login.oauth.discord"),
|
||||
icon: (<DiscordIcon style={{ fontSize: 24, }} />),
|
||||
},
|
||||
]}
|
||||
@@ -50,7 +52,7 @@ export const Login = () => {
|
||||
underline="none"
|
||||
to="/auth/forgot-password"
|
||||
>
|
||||
Forgot password?
|
||||
{translate("pages.login.buttons.forgotPassword")}
|
||||
</MuiLink>
|
||||
</Stack>
|
||||
}
|
||||
@@ -69,7 +71,7 @@ export const Login = () => {
|
||||
component="span"
|
||||
fontSize="12px"
|
||||
>
|
||||
Don’t have an account?
|
||||
{translate("pages.login.buttons.noAccount")}
|
||||
</Typography>
|
||||
<MuiLink
|
||||
ml="4px"
|
||||
@@ -81,7 +83,7 @@ export const Login = () => {
|
||||
to="/auth/register"
|
||||
fontWeight="bold"
|
||||
>
|
||||
Sign up
|
||||
{translate("pages.login.signup")}
|
||||
</MuiLink>
|
||||
</Box>
|
||||
}
|
||||
|
||||
@@ -1,5 +1,51 @@
|
||||
import { AuthPage } from "@refinedev/mui";
|
||||
import Box from "@mui/material/Box";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import MuiLink from "@mui/material/Link";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "@refinedev/core";
|
||||
import { Link } from "react-router";
|
||||
|
||||
export const Register = () => {
|
||||
return <AuthPage type="register" />;
|
||||
const { translate } = useTranslation();
|
||||
const loginLink = (
|
||||
<Box
|
||||
display="flex"
|
||||
justifyContent="flex-end"
|
||||
alignItems="center"
|
||||
sx={{
|
||||
mt: "24px",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Typography variant="body2" component="span" fontSize="12px">
|
||||
{translate(
|
||||
"pages.register.buttons.haveAccount",
|
||||
translate(
|
||||
"pages.login.buttons.haveAccount",
|
||||
"Have an account?",
|
||||
),
|
||||
)}
|
||||
</Typography>
|
||||
<MuiLink
|
||||
ml="4px"
|
||||
variant="body2"
|
||||
color="primary"
|
||||
component={Link}
|
||||
underline="none"
|
||||
to="/auth/login"
|
||||
fontSize="12px"
|
||||
fontWeight="bold"
|
||||
>
|
||||
{translate(
|
||||
"pages.register.signin",
|
||||
translate("pages.login.signin", "Sign in"),
|
||||
)}
|
||||
</MuiLink>
|
||||
</Box>
|
||||
)
|
||||
|
||||
return <AuthPage type="register" loginLink={loginLink}/>;
|
||||
};
|
||||
|
||||
41
gui/rpk-gui/src/components/header/I18nPicker.tsx
Normal file
41
gui/rpk-gui/src/components/header/I18nPicker.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import Autocomplete from "@mui/material/Autocomplete";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import Box from "@mui/material/Box";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation as useRefineTranslation } from "@refinedev/core";
|
||||
|
||||
const I18nPicker = () => {
|
||||
const { i18n } = useTranslation();
|
||||
const { getLocale, changeLocale } = useRefineTranslation();
|
||||
const currentLocale = getLocale();
|
||||
|
||||
return (
|
||||
<Autocomplete
|
||||
value={currentLocale}
|
||||
options={i18n.languages}
|
||||
disableClearable={true}
|
||||
renderInput={(params) => {
|
||||
return <TextField {...params} label={ "Language" } variant="outlined" />
|
||||
}}
|
||||
renderOption={(props, option) => {
|
||||
const { key, ...optionProps } = props;
|
||||
return (
|
||||
<Box
|
||||
key={key}
|
||||
component="li"
|
||||
sx={{ '& > img': { mr: 2, flexShrink: 0 } }}
|
||||
{...optionProps}
|
||||
>
|
||||
{ option }
|
||||
</Box>
|
||||
);
|
||||
}}
|
||||
onChange={(event, value) => {
|
||||
changeLocale(value);
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default I18nPicker;
|
||||
@@ -18,17 +18,11 @@ import { FirmContext } from "../../contexts/FirmContext";
|
||||
import { Logout } from "../auth/Logout";
|
||||
import { IUser } from "../../interfaces";
|
||||
import MuiLink from "@mui/material/Link";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation as useTranslationR } from "@refinedev/core";
|
||||
import { useSetLocale } from "@refinedev/core";
|
||||
import I18nPicker from "./I18nPicker";
|
||||
|
||||
export const Header: React.FC<RefineThemedLayoutV2HeaderProps> = ({
|
||||
sticky = true,
|
||||
}) => {
|
||||
const { i18n } = useTranslation();
|
||||
const { getLocale, changeLocale } = useTranslationR();
|
||||
const currentLocale = getLocale();
|
||||
|
||||
const collapsed = false;
|
||||
const { mode, setMode } = useContext(ColorModeContext);
|
||||
const { currentFirm } = useContext(FirmContext);
|
||||
@@ -44,16 +38,6 @@ export const Header: React.FC<RefineThemedLayoutV2HeaderProps> = ({
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const [anchorIn, setAnchorIn] = React.useState<null | HTMLElement>(null);
|
||||
const openI18nMenu = Boolean(anchorEl);
|
||||
const handleOpenI18nMenu = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
setAnchorIn(event.currentTarget);
|
||||
}
|
||||
const handleCloseI18nMenu = () => {
|
||||
setAnchorIn(null);
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<AppBar position={sticky ? "sticky" : "relative"}>
|
||||
<Toolbar>
|
||||
@@ -149,43 +133,7 @@ export const Header: React.FC<RefineThemedLayoutV2HeaderProps> = ({
|
||||
{!user && (
|
||||
<Link to="/auth/login"><Button>Login</Button></Link>
|
||||
)}
|
||||
<Button
|
||||
id="i18n-button"
|
||||
aria-controls={openI18nMenu ? 'i18n-menu' : undefined}
|
||||
aria-haspopup="true"
|
||||
aria-expanded={openI18nMenu ? 'true' : undefined}
|
||||
onClick={handleOpenI18nMenu}>
|
||||
<Typography
|
||||
sx={{
|
||||
display: {
|
||||
xs: "none",
|
||||
sm: "inline-block",
|
||||
},
|
||||
}}
|
||||
variant="subtitle2"
|
||||
>
|
||||
{currentLocale}
|
||||
</Typography>
|
||||
<Avatar src={`/images/flags/${currentLocale}.svg`} alt={currentLocale}/>
|
||||
</Button>
|
||||
<Menu
|
||||
id="i18n-menu"
|
||||
open={openI18nMenu}
|
||||
anchorEl={anchorIn}
|
||||
onClose={handleCloseI18nMenu}
|
||||
>
|
||||
{[...(i18n.languages || [])].sort().map((lang: string) => (
|
||||
<MenuItem
|
||||
key={lang}
|
||||
onClick={() => changeLocale(lang)}
|
||||
>
|
||||
<span style={{ marginRight: 8 }}>
|
||||
<Avatar src={`/images/flags/${lang}.svg`} alt={lang}/>
|
||||
</span>
|
||||
{lang === "en" ? "English" : "Français"}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Menu>
|
||||
<I18nPicker />
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Toolbar>
|
||||
|
||||
@@ -8,13 +8,13 @@ i18n
|
||||
.use(detector)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
supportedLngs: ["en", "fr"],
|
||||
supportedLngs: ["EN", "FR"],
|
||||
backend: {
|
||||
loadPath: "/locales/{{lng}}/{{ns}}.json", // locale files path
|
||||
},
|
||||
ns: ["common"],
|
||||
defaultNS: "common",
|
||||
fallbackLng: ["en", "fr"],
|
||||
fallbackLng: ["EN", "FR"],
|
||||
});
|
||||
|
||||
export default i18n;
|
||||
|
||||
Reference in New Issue
Block a user