You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
3.2 KiB
106 lines
3.2 KiB
2 years ago
|
import { useEffect, useState, useRef } from "react"
|
||
|
import { useRouter } from "next/router"
|
||
|
import PropTypes from "prop-types"
|
||
|
import Link from "next/link"
|
||
|
|
||
|
import Cookies from "js-cookie"
|
||
|
import { MdExpandMore } from "react-icons/md"
|
||
|
import WorldIcon from "./icons/world"
|
||
|
|
||
|
import { useOnClickOutside } from "../utils/hooks"
|
||
|
import { getLocalizedPage } from "../utils/localize"
|
||
|
const LocaleSwitch = ({ pageContext }) => {
|
||
|
const isMounted = useRef(false)
|
||
|
const select = useRef()
|
||
|
const router = useRouter()
|
||
|
const [locale, setLocale] = useState()
|
||
|
const [showing, setShowing] = useState(false)
|
||
|
|
||
|
const handleLocaleChange = async (selectedLocale) => {
|
||
|
// Persist the user's language preference
|
||
|
// https://nextjs.org/docs/advanced-features/i18n-routing#leveraging-the-next_locale-cookie
|
||
|
Cookies.set("NEXT_LOCALE", selectedLocale)
|
||
|
setLocale(selectedLocale)
|
||
|
}
|
||
|
|
||
|
const handleLocaleChangeRef = useRef(handleLocaleChange)
|
||
|
useOnClickOutside(select, () => setShowing(false))
|
||
|
|
||
|
useEffect(() => {
|
||
|
const localeCookie = Cookies.get("NEXT_LOCALE")
|
||
|
if (!localeCookie) {
|
||
|
handleLocaleChangeRef.current(router.locale)
|
||
|
}
|
||
|
|
||
|
const checkLocaleMismatch = async () => {
|
||
|
if (
|
||
|
!isMounted.current &&
|
||
|
localeCookie &&
|
||
|
localeCookie !== pageContext.locale
|
||
|
) {
|
||
|
// Redirect to locale page if locale mismatch
|
||
|
const localePage = getLocalizedPage(localeCookie, pageContext)
|
||
|
|
||
|
router.push(
|
||
|
`${localizePath({ ...pageContext, ...localePage })}`,
|
||
|
`${localizePath({ ...pageContext, ...localePage })}`,
|
||
|
{ locale: localePage.locale }
|
||
|
)
|
||
|
}
|
||
|
setShowing(false)
|
||
|
}
|
||
|
|
||
|
setLocale(localeCookie || router.locale)
|
||
|
checkLocaleMismatch()
|
||
|
|
||
|
return () => {
|
||
|
isMounted.current = true
|
||
|
}
|
||
|
}, [locale, router, pageContext])
|
||
|
|
||
|
return (
|
||
|
<div ref={select} className="relative ml-4 ">
|
||
|
<button
|
||
|
type="button"
|
||
|
className="hover:bg-primary-50 hover:text-primary-600 focus:bg-primary-50 focus:text-primary-600 focus:outline-none flex items-center justify-between px-2 py-2 cursor-pointer h-full rounded-md w-20"
|
||
|
onClick={() => setShowing(!showing)}
|
||
|
>
|
||
|
<WorldIcon />
|
||
|
<span className="capitalize">{locale}</span>
|
||
|
<MdExpandMore className="ml-1 text-primary-600" />
|
||
|
</button>
|
||
|
<div
|
||
|
className={`w-full bg-white p-1 mt-1 shadow-lg rounded-md ${
|
||
|
showing ? "absolute" : "hidden"
|
||
|
}`}
|
||
|
>
|
||
|
{pageContext.localizedPaths &&
|
||
|
pageContext.localizedPaths.map(({ href, locale }) => {
|
||
|
return (
|
||
|
<Link
|
||
|
href={href}
|
||
|
key={locale}
|
||
|
locale={locale}
|
||
|
role="option"
|
||
|
passHref
|
||
|
>
|
||
|
<p
|
||
|
onClick={() => handleLocaleChange(locale)}
|
||
|
className="capitalize hover:bg-primary-50 hover:text-primary-600 cursor-pointer p-2 rounded-md text-center hover:text-primary-600"
|
||
|
>
|
||
|
{locale}
|
||
|
</p>
|
||
|
</Link>
|
||
|
)
|
||
|
})}
|
||
|
</div>
|
||
|
</div>
|
||
|
)
|
||
|
}
|
||
|
|
||
|
LocaleSwitch.propTypes = {
|
||
|
initialLocale: PropTypes.string,
|
||
|
}
|
||
|
|
||
|
export default LocaleSwitch
|