feat(lang): add language switcher on the landing page, in the footer
This commit is contained in:
parent
036adbfc96
commit
8bc7d2599e
|
@ -63,13 +63,13 @@ const Settings = () => {
|
|||
|
||||
const handleChangeLanguage = (value: Language | null) => {
|
||||
const { pathname, asPath, query } = router;
|
||||
const locale = value?.code || 'en';
|
||||
const code = value?.code || 'en';
|
||||
|
||||
dayjs.locale(locale);
|
||||
dispatch(setLanguage({ language: locale || 'en' }));
|
||||
document.cookie = `NEXT_LOCALE=${locale}; path=/; expires=2147483647`;
|
||||
dayjs.locale(code);
|
||||
dispatch(setLanguage({ language: code }));
|
||||
document.cookie = `NEXT_LOCALE=${code}; path=/; expires=2147483647`;
|
||||
|
||||
router.push({ pathname, query }, asPath, { locale });
|
||||
router.push({ pathname, query }, asPath, { locale: code });
|
||||
};
|
||||
|
||||
const handleLoadSampleData = async () => {
|
||||
|
|
|
@ -9,7 +9,7 @@ const Footer: React.FC<Props> = ({ className }) => {
|
|||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<footer className={clsx('text-xs', className)}>
|
||||
<div className={clsx('text-xs', className)}>
|
||||
<p>{t('common.footer.license')}</p>
|
||||
|
||||
<p>
|
||||
|
@ -20,7 +20,7 @@ const Footer: React.FC<Props> = ({ className }) => {
|
|||
</a>
|
||||
</Trans>
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
.popover {
|
||||
width: 460px;
|
||||
|
||||
@apply px-4 py-2;
|
||||
}
|
||||
|
||||
.container {
|
||||
@apply grid grid-cols-3 items-center justify-center gap-x-2;
|
||||
}
|
||||
|
||||
.language {
|
||||
@apply py-2 px-4 cursor-pointer text-center hover:underline;
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
import { Language } from '@mui/icons-material';
|
||||
import { IconButton, Popover } from '@mui/material';
|
||||
import dayjs from 'dayjs';
|
||||
import { useRouter } from 'next/router';
|
||||
import { MouseEvent, useState } from 'react';
|
||||
|
||||
import { languages } from '@/config/languages';
|
||||
import { setLanguage } from '@/store/build/buildSlice';
|
||||
import { useAppDispatch } from '@/store/hooks';
|
||||
|
||||
import styles from './LanguageSwitcher.module.scss';
|
||||
|
||||
const LanguageSwitcher = () => {
|
||||
const router = useRouter();
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
|
||||
|
||||
const handleClick = (event: MouseEvent<HTMLButtonElement>) => setAnchorEl(event.currentTarget);
|
||||
|
||||
const handleClose = () => setAnchorEl(null);
|
||||
|
||||
const handleChangeLanguage = (locale: string) => {
|
||||
const { pathname, asPath, query } = router;
|
||||
|
||||
dayjs.locale(locale);
|
||||
dispatch(setLanguage({ language: locale }));
|
||||
document.cookie = `NEXT_LOCALE=${locale}; path=/; expires=2147483647`;
|
||||
|
||||
router.push({ pathname, query }, asPath, { locale });
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<IconButton onClick={handleClick}>
|
||||
<Language />
|
||||
</IconButton>
|
||||
|
||||
<Popover
|
||||
anchorEl={anchorEl}
|
||||
open={Boolean(anchorEl)}
|
||||
onClose={handleClose}
|
||||
anchorOrigin={{
|
||||
vertical: 'top',
|
||||
horizontal: 'right',
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: 'bottom',
|
||||
horizontal: 'right',
|
||||
}}
|
||||
>
|
||||
<div className={styles.popover}>
|
||||
<div className={styles.container}>
|
||||
{languages.map(({ code, name, localName }) => (
|
||||
<p key={code} className={styles.language} onClick={() => handleChangeLanguage(code)}>
|
||||
{name} {localName && `(${localName})`}
|
||||
</p>
|
||||
))}
|
||||
|
||||
<a href="https://translate.rxresu.me" target="_blank" rel="noreferrer" className={styles.language}>
|
||||
Missing your language?
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LanguageSwitcher;
|
|
@ -9,6 +9,7 @@ import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
|
|||
|
||||
import Testimony from '@/components/landing/Testimony';
|
||||
import Footer from '@/components/shared/Footer';
|
||||
import LanguageSwitcher from '@/components/shared/LanguageSwitcher';
|
||||
import Logo from '@/components/shared/Logo';
|
||||
import NoSSR from '@/components/shared/NoSSR';
|
||||
import { screenshots } from '@/config/screenshots';
|
||||
|
@ -180,9 +181,13 @@ const Home: NextPage = () => {
|
|||
</section>
|
||||
|
||||
<footer>
|
||||
<div className={styles.version}>
|
||||
<Footer className="font-semibold leading-5 opacity-50" />
|
||||
|
||||
<div>v{process.env.appVersion}</div>
|
||||
</div>
|
||||
|
||||
<LanguageSwitcher />
|
||||
</footer>
|
||||
</main>
|
||||
);
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
"testimonials": {
|
||||
"heading": "Testimonials",
|
||||
"body": "Good or bad, I would love to hear your opinion on Reactive Resume and how the experience has been for you.<br/>Here are some of the messages sent in by users across the world.",
|
||||
"contact": "You can reach out to me through <1>my email</1> or through the contact form on <2>my website</2>."
|
||||
"contact": "You can reach out to me through <1>my email</1> or through the contact form on <3>my website</3>."
|
||||
},
|
||||
"summary": {
|
||||
"body": "Reactive Resume is a free and open source resume builder that's built to make the mundane tasks of creating, updating and sharing your resume as easy as 1, 2, 3. With this app, you can create multiple resumes, share them with recruiters or friends through a unique link and print it as a PDF, all for free, no ads, no tracking, without losing the integrity and privacy of your data.",
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
"testimonials": {
|
||||
"heading": "ಪ್ರಶಂಸಾಪತ್ರಗಳು",
|
||||
"body": "ಒಳ್ಳೆಯದು ಅಥವಾ ಕೆಟ್ಟದು, ಪ್ರತಿಕ್ರಿಯಾತ್ಮಕ ಪುನರಾರಂಭದ ಕುರಿತು ನಿಮ್ಮ ಅಭಿಪ್ರಾಯವನ್ನು ಕೇಳಲು ನಾನು ಇಷ್ಟಪಡುತ್ತೇನೆ ಮತ್ತು ಅನುಭವವು ನಿಮಗೆ ಹೇಗೆ ಆಗಿದೆ.<br/>ಪ್ರಪಂಚದಾದ್ಯಂತ ಬಳಕೆದಾರರು ಕಳುಹಿಸಿದ ಕೆಲವು ಸಂದೇಶಗಳು ಇಲ್ಲಿವೆ.",
|
||||
"contact": "<1>ನನ್ನ ಇಮೇಲ್ ಮೂಲಕ ನೀವು ನನ್ನನ್ನು ಸಂಪರ್ಕಿಸಬಹುದು</1> ಅಥವಾ <2>ನನ್ನ ವೆಬ್ಸೈಟ್ನಲ್ಲಿ ಸಂಪರ್ಕ ಫಾರ್ಮ್ ಮೂಲಕ</2>."
|
||||
"contact": "<1>ನನ್ನ ಇಮೇಲ್</1> ಮೂಲಕ ಅಥವಾ <3>ನನ್ನ ವೆಬ್ಸೈಟ್</3> ಮೂಲಕ ನೀವು ನನ್ನನ್ನು ಸಂಪರ್ಕಿಸಬಹುದು."
|
||||
},
|
||||
"summary": {
|
||||
"body": "ರಿಯಾಕ್ಟಿವ್ ರೇಸುಮೆವು ಉಚಿತ ಮತ್ತು ಮುಕ್ತ ಮೂಲ ರೆಸ್ಯೂಮ್ ಬಿಲ್ಡರ್ ಆಗಿದ್ದು, ನಿಮ್ಮ ರೆಸ್ಯೂಮ್ ಅನ್ನು 1, 2, 3 ರಂತೆ ಸುಲಭವಾಗಿ ರಚಿಸುವ, ನವೀಕರಿಸುವ ಮತ್ತು ಹಂಚಿಕೊಳ್ಳುವ ಪ್ರಾಪಂಚಿಕ ಕಾರ್ಯಗಳನ್ನು ಮಾಡಲು ನಿರ್ಮಿಸಲಾಗಿದೆ. ಈ ಅಪ್ಲಿಕೇಶನ್ನೊಂದಿಗೆ, ನೀವು ಬಹು ರೆಸ್ಯೂಮ್ಗಳನ್ನು ರಚಿಸಬಹುದು, ನೇಮಕಾತಿ ಮಾಡುವವರು ಅಥವಾ ಸ್ನೇಹಿತರೊಂದಿಗೆ ಹಂಚಿಕೊಳ್ಳಬಹುದು ಅನನ್ಯ ಲಿಂಕ್ ಮೂಲಕ ಮತ್ತು ಅದನ್ನು PDF ಆಗಿ ಮುದ್ರಿಸಿ, ಎಲ್ಲಾ ಉಚಿತವಾಗಿ, ಯಾವುದೇ ಜಾಹೀರಾತುಗಳಿಲ್ಲ, ಯಾವುದೇ ಟ್ರ್ಯಾಕಿಂಗ್ ಇಲ್ಲ, ನಿಮ್ಮ ಡೇಟಾದ ಸಮಗ್ರತೆ ಮತ್ತು ಗೌಪ್ಯತೆಯನ್ನು ಕಳೆದುಕೊಳ್ಳದೆ.",
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
.container {
|
||||
@apply m-6 grid gap-8 text-center md:m-8 md:text-left;
|
||||
|
||||
footer > div {
|
||||
@apply text-xs font-medium opacity-50 mt-2;
|
||||
footer {
|
||||
@apply flex items-end justify-between;
|
||||
|
||||
.version > div {
|
||||
@apply text-xs font-medium opacity-50 mt-3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue