-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #24 from strapi/feat/locale-switcher-logic
chore: create a locale switcher logic
- Loading branch information
Showing
13 changed files
with
346 additions
and
214 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
"use client"; | ||
|
||
import { useEffect } from "react"; | ||
import { useSlugContext } from "@/app/context/SlugContext"; | ||
|
||
export default function ClientSlugHandler({ | ||
localizedSlugs, | ||
}: { | ||
localizedSlugs: Record<string, string>; | ||
}) { | ||
const { dispatch } = useSlugContext(); | ||
|
||
useEffect(() => { | ||
if (localizedSlugs) { | ||
dispatch({ type: "SET_SLUGS", payload: localizedSlugs }); | ||
} | ||
}, [localizedSlugs, dispatch]); | ||
|
||
return null; // This component only handles the state and doesn't render anything. | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,38 @@ | ||
import { Metadata } from 'next'; | ||
import React from "react"; | ||
|
||
import { BlogLayout } from "@/components/blog-layout"; | ||
import fetchContentType from "@/lib/strapi/fetchContentType"; | ||
import { BlocksRenderer } from '@strapi/blocks-react-renderer'; | ||
import { BlocksRenderer } from "@strapi/blocks-react-renderer"; | ||
|
||
import { generateMetadataObject } from '@/lib/shared/metadata'; | ||
import ClientSlugHandler from "../../ClientSlugHandler"; | ||
|
||
export async function generateMetadata({ | ||
export default async function SingleArticlePage({ | ||
params, | ||
}: { | ||
params: { locale: string, slug: string }; | ||
}): Promise<Metadata> { | ||
const pageData = await fetchContentType("articles", `filters[slug]=${params?.slug}&filters[locale][$eq]=${params.locale}&populate=seo.metaImage`, true) | ||
|
||
const seo = pageData?.seo; | ||
const metadata = generateMetadataObject(seo); | ||
return metadata; | ||
} | ||
|
||
export default async function singleArticlePage({ params }: { params: { slug: string, locale: string } }) { | ||
const article = await fetchContentType("articles", `filters[slug]=${params?.slug}&filters[locale][$eq]=${params.locale}`, true) | ||
params: { slug: string; locale: string }; | ||
}) { | ||
const article = await fetchContentType( | ||
"articles", | ||
`filters[slug]=${params?.slug}&filters[locale][$eq]=${params.locale}`, | ||
true | ||
); | ||
|
||
if (!article) { | ||
return <div>Blog not found</div>; | ||
} | ||
|
||
const localizedSlugs = article.localizations?.reduce( | ||
(acc: Record<string, string>, localization: any) => { | ||
acc[localization.locale] = localization.slug; | ||
return acc; | ||
}, | ||
{ [params.locale]: params.slug } | ||
); | ||
|
||
return ( | ||
<BlogLayout article={article} locale={params.locale}> | ||
<ClientSlugHandler localizedSlugs={localizedSlugs} /> | ||
<BlocksRenderer content={article.content} /> | ||
</BlogLayout> | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
"use client"; | ||
|
||
import React, { createContext, useContext, useReducer } from "react"; | ||
|
||
type State = { | ||
localizedSlugs: Record<string, string>; | ||
}; | ||
|
||
type Action = { | ||
type: "SET_SLUGS"; | ||
payload: Record<string, string>; | ||
}; | ||
|
||
const SlugContext = createContext<{ | ||
state: State; | ||
dispatch: React.Dispatch<Action>; | ||
} | null>(null); | ||
|
||
const slugReducer = (state: State, action: Action): State => { | ||
switch (action.type) { | ||
case "SET_SLUGS": | ||
return { ...state, localizedSlugs: action.payload }; | ||
default: | ||
return state; | ||
} | ||
}; | ||
|
||
export const SlugProvider = ({ children }: { children: React.ReactNode }) => { | ||
const [state, dispatch] = useReducer(slugReducer, { localizedSlugs: {} }); | ||
|
||
return ( | ||
<SlugContext.Provider value={{ state, dispatch }}> | ||
{children} | ||
</SlugContext.Provider> | ||
); | ||
}; | ||
|
||
export const useSlugContext = () => { | ||
const context = useContext(SlugContext); | ||
if (!context) { | ||
throw new Error("useSlugContext must be used within a SlugProvider"); | ||
} | ||
return context; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,44 +1,55 @@ | ||
"use client"; | ||
|
||
import React from "react"; | ||
import Link from "next/link"; | ||
import { usePathname } from "next/navigation"; | ||
import { useSlugContext } from "@/app/context/SlugContext"; | ||
import { cn } from "@/lib/utils"; | ||
|
||
export function LocaleSwitcher({ currentLocale }: { currentLocale: string }) { | ||
const { state } = useSlugContext(); | ||
const { localizedSlugs } = state; | ||
|
||
import Link from 'next/link' | ||
import { usePathname } from 'next/navigation' | ||
import { i18n } from '@/i18n.config' | ||
const pathname = usePathname(); // Current path | ||
const segments = pathname.split("/"); // Split path into segments | ||
|
||
import { cn } from "@/lib/utils"; | ||
// Generate localized path for each locale | ||
const generateLocalizedPath = (locale: string): string => { | ||
if (!pathname) return `/${locale}`; // Default to root path for the locale | ||
|
||
// Handle homepage (e.g., "/en" -> "/fr") | ||
if (segments.length <= 2) { | ||
return `/${locale}`; | ||
} | ||
|
||
export function LocaleSwitcher() { | ||
const pathName = usePathname() | ||
const currentLocale = pathName.split('/')[1] | ||
// Handle dynamic paths (e.g., "/en/blog/[slug]") | ||
if (localizedSlugs[locale]) { | ||
segments[1] = locale; // Replace the locale | ||
segments[segments.length - 1] = localizedSlugs[locale]; // Replace slug if available | ||
return segments.join("/"); | ||
} | ||
|
||
const redirectedPathName = (locale: string) => { | ||
if (!pathName) return '/' | ||
const segments = pathName.split('/') | ||
segments[1] = locale | ||
return segments.join('/') | ||
} | ||
// Fallback to replace only the locale | ||
segments[1] = locale; | ||
return segments.join("/"); | ||
}; | ||
|
||
return ( | ||
<div className="flex gap-2 p-1 rounded-md"> | ||
{i18n.locales.map((locale) => ( | ||
<Link | ||
key={locale} | ||
href={redirectedPathName(locale)} | ||
> | ||
<React.Fragment > | ||
<div | ||
className={cn( | ||
"flex cursor-pointer items-center justify-center text-sm leading-[110%] w-8 py-1 rounded-md hover:bg-neutral-800 hover:text-white/80 text-white hover:shadow-[0px_1px_0px_0px_var(--neutral-600)_inset] transition duration-200", | ||
locale === currentLocale | ||
? "bg-neutral-800 text-white shadow-[0px_1px_0px_0px_var(--neutral-600)_inset]" | ||
: "" | ||
)} | ||
> | ||
{locale} | ||
</div> | ||
</React.Fragment> | ||
<div className="flex gap-2 p-1 rounded-md"> | ||
{!pathname.includes("/products/") && Object.keys(localizedSlugs).map((locale) => ( | ||
<Link key={locale} href={generateLocalizedPath(locale)}> | ||
<div | ||
className={cn( | ||
"flex cursor-pointer items-center justify-center text-sm leading-[110%] w-8 py-1 rounded-md hover:bg-neutral-800 hover:text-white/80 text-white hover:shadow-[0px_1px_0px_0px_var(--neutral-600)_inset] transition duration-200", | ||
locale === currentLocale | ||
? "bg-neutral-800 text-white shadow-[0px_1px_0px_0px_var(--neutral-600)_inset]" | ||
: "" | ||
)} | ||
> | ||
{locale} | ||
</div> | ||
</Link> | ||
))} | ||
</div> | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.