Locale switcher

This commit is contained in:
Henrik Larsson 2023-07-07 11:46:16 +02:00
parent da630eced6
commit 4327a10dc9
7 changed files with 96 additions and 168 deletions

View File

@ -1,18 +0,0 @@
export default function FlagEn ({ className = "w-6 h-auto" }: { className?: string }) {
return (
<svg
className={className}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 30.6 20.4"
>
<path className="fill-[#293476]" d="M.1.1h30.5v20.3H.1z"/>
<path className="fill-[#fff]" d="M30.5 7.2H18.3V.1h-6v7.1H.1v6.1h12.2v7.1h6v-7.1h12.2z"/>
<path className="fill-[#fff]" d="M30.5 18L3.6.1H.1v2.3l26.9 18h3.5z"/>
<path className="fill-[#fff]" d="M.1 18L27 .1h3.5v2.3l-26.9 18H.1z"/>
<path className="fill-[#ce202d]" d="M30.5 8.4H17.1V.1h-3.6v8.3H.1V12h13.4v8.4h3.6V12h13.4z"/>
<path className="fill-[#ce202d]" d="M30.5 20.3v-1.6l-8.2-5.4h-2.4zm0-20.2h-2.4l-9.8 6.5v.6h1.6L30.5.1zM10.7 13.3l-10.6 7v.1h2.3l9.9-6.6v-.5zM.1.1v1.6l8.2 5.5h2.4z"/>
<path className="fill-none" d="M0 20.4V0h30.6v20.5H0zm30.5 0zM.1 20.3h30.3V.1H.1v20.2z"/>
</svg>
)
}

View File

@ -1,25 +0,0 @@
export default function FlagSv ({ className = "w-6 h-auto" }: { className?: string }) {
return (
<svg
className={className}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 480"
>
<defs>
<clipPath id="a">
<path fillOpacity=".67" d="M-53.421 0h682.67v512h-682.67z"/>
</clipPath>
</defs>
<g clipPath="url(#a)" transform="translate(50.082) scale(.9375)">
<g fillRule="evenodd" strokeWidth="1pt">
<path fill="#006aa7" d="M-121.103.302h256V205.1h-256zm0 306.876h256v204.8h-256z"/>
<path fill="#fecc00" d="M-121.103 204.984h256v102.4h-256z"/>
<path fill="#fecc00" d="M133.843.01h102.4v511.997h-102.4z"/>
<path fill="#fecc00" d="M232.995 205.013h460.798v102.4H232.995z"/>
<path fill="#006aa7" d="M236.155 307.208h460.797v204.799H236.155zm0-306.906h460.797V205.1H236.155z"/>
</g>
</g>
</svg>
)
}

View File

@ -1,13 +0,0 @@
export default function GitHubIcon({ className }: { className?: string }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
shapeRendering="geometricPrecision"
className={className}
>
<path d="M12 0C5.37 0 0 5.50583 0 12.3035C0 17.7478 3.435 22.3463 8.205 23.9765C8.805 24.0842 9.03 23.715 9.03 23.3921C9.03 23.0999 9.015 22.131 9.015 21.1005C6 21.6696 5.22 20.347 4.98 19.6549C4.845 19.3012 4.26 18.2092 3.75 17.917C3.33 17.6863 2.73 17.1173 3.735 17.1019C4.68 17.0865 5.355 17.9939 5.58 18.363C6.66 20.2239 8.385 19.701 9.075 19.3781C9.18 18.5783 9.495 18.04 9.84 17.7325C7.17 17.4249 4.38 16.3637 4.38 11.6576C4.38 10.3196 4.845 9.21227 5.61 8.35102C5.49 8.04343 5.07 6.78232 5.73 5.09058C5.73 5.09058 6.735 4.76762 9.03 6.3517C9.99 6.07487 11.01 5.93645 12.03 5.93645C13.05 5.93645 14.07 6.07487 15.03 6.3517C17.325 4.75224 18.33 5.09058 18.33 5.09058C18.99 6.78232 18.57 8.04343 18.45 8.35102C19.215 9.21227 19.68 10.3042 19.68 11.6576C19.68 16.3791 16.875 17.4249 14.205 17.7325C14.64 18.1169 15.015 18.8552 15.015 20.0086C15.015 21.6542 15 22.9768 15 23.3921C15 23.715 15.225 24.0995 15.825 23.9765C18.2072 23.1519 20.2773 21.5822 21.7438 19.4882C23.2103 17.3942 23.9994 14.8814 24 12.3035C24 5.50583 18.63 0 12 0Z" />
</svg>
);
}

View File

@ -0,0 +1,18 @@
export default function LanguageIcon({ className }: { className?: string }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
className={className}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M10.5 21l5.25-11.25L21 21m-9-3h7.5M3 5.621a48.474 48.474 0 016-.371m0 0c1.12 0 2.233.038 3.334.114M9 5.25V3m3.334 2.364C11.176 10.658 7.69 15.08 3 17.502m9.334-12.138c.896.061 1.785.147 2.666.257m-4.589 8.495a18.023 18.023 0 01-3.827-5.802"
/>
</svg>
);
}

View File

@ -1,104 +1,68 @@
import FlagEn from 'components/icons/flag-en';
import FlagSv from 'components/icons/flag-sv';
import LanguageIcon from 'components/icons/language';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
DropdownMenuTrigger
} from 'components/ui/dropdown/dropdown';
import { useLocale } from 'next-intl';
import Link from 'next/link';
import { usePathname, useRouter } from 'next/navigation';
import { usePathname } from 'next/navigation';
import { useState } from 'react';
import { i18n } from '../../../i18n-config';
export default function LocaleSwitcher() {
const pathName = usePathname()
const locale = useLocale();
const [isOpen, setIsOpen] = useState(false)
const router = useRouter();
interface LocaleSwitcherProps {
current: string;
pageData: object;
}
export default function LocaleSwitcher({ current, pageData }: LocaleSwitcherProps) {
const pathName = usePathname();
console.log(pageData);
// Handle redirected pathname.
const redirectedPathName = (locale: string) => {
if (!pathName) return '/'
const segments = pathName.split('/')
segments[1] = locale
return segments.join('/')
}
if (!pathName) return '/';
const segments = pathName.split('/');
segments[1] = locale;
return segments.join('/');
};
// Handle click on dropdown menu item (<li>).
const handleClick = (e: any, locale: string) => {
e.preventDefault()
const parent = e.target
if (parent.nodeName !== 'LI') {
return
}
let href = '/'
const hasChildLink = parent.querySelector('a').href !== null
if (hasChildLink) {
href = parent.querySelector('a').href
}
router.push(`${redirectedPathName(locale)}`)
setIsOpen(false)
}
const [isOpen, setIsOpen] = useState(false);
return (
<div>
<DropdownMenu open={isOpen} onOpenChange={() => setIsOpen(!isOpen)}>
<DropdownMenuTrigger asChild>
<button
className={
'duration-200 bg-app shrink-0 uppercase space-x-2 text-sm flex items-center justify-center transition hover:scale-105'
}
aria-label="Language selector"
>
{locale === "sv" && (
<FlagSv />
)}
{locale === "en" && (
<FlagEn />
)}
<span className="sr-only">{locale}</span>
</button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="drop-shadow-xl">
<ul className="">
{i18n.locales.map((locale) => {
let FlagIcon: any
FlagIcon = i18n.flags[locale]
return (
<DropdownMenuItem
className='p-0'
key={locale}
asChild
onClick={(e) => handleClick(e, locale)}
>
<li className="flex" key={locale}>
<Link
className="flex w-full cursor-pointer uppercase space-x-2 text-sm p-2"
onClick={() => setIsOpen(false)}
href={redirectedPathName(locale)}
>
<FlagIcon />
<span>{locale}</span>
</Link>
</li>
</DropdownMenuItem>
)
})}
</ul>
</DropdownMenuContent>
</DropdownMenu>
</div>
)
<DropdownMenuTrigger asChild>
<button
className={
'flex shrink-0 items-center justify-center space-x-1 rounded bg-app p-2 text-sm font-bold uppercase outline-none ring-2 ring-transparent transition duration-200 hover:ring-ui-border focus:ring-ui-border'
}
aria-label="Language selector"
>
<LanguageIcon className="h-6 w-6" />
<span>{current}</span>
</button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="drop-shadow-xl">
<ul className="">
{i18n.locales.map((locale) => {
if (current === locale.id) {
return;
} else {
return (
<li className="" key={locale.id}>
<Link
className="flex w-full cursor-pointer px-4 py-2 text-sm"
href={redirectedPathName(locale.id)}
>
{locale.title}
</Link>
</li>
);
}
})}
</ul>
</DropdownMenuContent>
</DropdownMenu>
</div>
);
}

View File

@ -1,13 +1,15 @@
import FlagEn from "components/icons/flag-en"
import FlagSv from "components/icons/flag-sv"
export const i18n = {
defaultLocale: 'sv',
locales: ['sv', 'en'],
flags: {
sv: FlagSv,
en: FlagEn
}
locales: [
{
id: 'sv',
title: 'Swedish'
},
{
id: 'en',
title: 'English'
}
],
} as const
export type Locale = typeof i18n['locales'][number]

View File

@ -2,7 +2,7 @@ export const docQuery = `*[_type in ["home", "page", "category", "product"] && d
_type,
"slug": slug.current,
"locale": language
}`
}`;
export const imageFields = `
alt,
@ -13,7 +13,7 @@ export const imageFields = `
_type,
_ref,
}
`
`;
export const seoFields = `
title,
@ -21,7 +21,7 @@ export const seoFields = `
image {
${imageFields}
}
`
`;
// Construct our "Modules" GROQ
export const modules = `
@ -141,7 +141,7 @@ export const modules = `
},
},
}
`
`;
export const reusableSection = `
_type == 'reusableSection' => {
disabled,
@ -157,7 +157,7 @@ export const reusableSection = `
}
}
}
`
`;
// Homepage query
export const homePageQuery = `*[_type == "home" && slug.current == "/" && language == $locale][0] {
@ -167,7 +167,7 @@ export const homePageQuery = `*[_type == "home" && slug.current == "/" && langua
"locale": language,
"translations": *[_type == "translation.metadata" && references(^._id)].translations[].value->{
title,
slug,
"slug": slug.current,
"locale": language
},
content[] {
@ -177,7 +177,7 @@ export const homePageQuery = `*[_type == "home" && slug.current == "/" && langua
seo {
${seoFields}
}
}`
}`;
// Page query
export const pageQuery = `*[_type == "page" && slug.current == $slug && language == $locale][0] {
@ -187,7 +187,7 @@ export const pageQuery = `*[_type == "page" && slug.current == $slug && language
"locale": language,
"translations": *[_type == "translation.metadata" && references(^._id)].translations[].value->{
title,
slug,
"slug": slug.current,
"locale": language
},
content[] {
@ -196,7 +196,7 @@ export const pageQuery = `*[_type == "page" && slug.current == $slug && language
seo {
${seoFields}
}
}`
}`;
// Product query
export const productQuery = `*[_type == "product" && slug.current == $slug && language == $locale][0] {
@ -206,7 +206,7 @@ export const productQuery = `*[_type == "product" && slug.current == $slug && la
"locale": language,
"translations": *[_type == "translation.metadata" && references(^._id)].translations[].value->{
title,
slug,
"slug": slug.current,
"locale": language
},
"product": {
@ -235,7 +235,7 @@ export const productQuery = `*[_type == "product" && slug.current == $slug && la
seo {
${seoFields}
}
}`
}`;
// Category query
export const categoryQuery = `*[_type == "category" && slug.current == $slug && language == $locale][0] {
@ -255,13 +255,13 @@ export const categoryQuery = `*[_type == "category" && slug.current == $slug &&
},
"translations": *[_type == "translation.metadata" && references(^._id)].translations[].value->{
title,
slug,
"slug": slug.current,
"locale": language
},
seo {
${seoFields}
}
}`
}`;
// Site settings query
export const siteSettingsQuery = `*[_type == "settings" && language == $locale][0] {
@ -301,4 +301,4 @@ export const siteSettingsQuery = `*[_type == "settings" && language == $locale][
reference->
}
}
}`
}`;