Created
May 11, 2023 18:59
-
-
Save treckstar/c7be61248fd5b01a075f4e24c82fbc51 to your computer and use it in GitHub Desktop.
Next.js TypeScript Localization Proof of Concept for `output: 'export'` builds
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
import { GetStaticPaths, GetStaticProps } from 'next'; | |
type Locale = 'en-US' | 'es' | 'hm'; | |
type PageData = { | |
// Define the properties you need for your page data | |
title: string; | |
content: string; | |
}; | |
type PageParams = { | |
slug: string[]; | |
locale: Locale; | |
}; | |
const slugs: string[] = ['/about', '/products', '/contact']; | |
const locales: Locale[] = ['en-US', 'es', 'hm']; | |
export const getStaticPaths: GetStaticPaths<PageParams> = async () => { | |
const paths = []; | |
for (const slug of slugs) { | |
for (const locale of locales) { | |
paths.push({ params: { slug: [slug], locale } }); | |
} | |
} | |
return { | |
paths, | |
fallback: false, // or 'blocking' if you want to use fallback behavior | |
}; | |
}; | |
export const getStaticProps: GetStaticProps<PageData, PageParams> = async ({ params }) => { | |
const { slug, locale } = params; | |
// Fetch data based on the slug and locale | |
// Example implementation: | |
const title = `Page Title: ${slug}`; | |
const content = `Page Content for ${slug} in ${locale}`; | |
const pageData: PageData = { | |
title, | |
content, | |
}; | |
return { | |
props: pageData, | |
}; | |
}; |
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
type Locale = 'en-US' | 'es' | 'hm'; | |
function generateLocalizedUrls(slugs: string[], locales: Locale[]): string[] { | |
const defaultLocale = 'en'; | |
const localizedSlugs: string[] = []; | |
for (const slug of slugs) { | |
const trimmedSlug = slug.slice(1); // Remove leading slash | |
for (const locale of locales) { | |
const localeCode = locale === 'en-US' ? defaultLocale : locale; | |
const localizedSlug = `/${localeCode}/${trimmedSlug}`; | |
localizedSlugs.push(localizedSlug); | |
} | |
localizedSlugs.push(slug); // Add original relative slug | |
} | |
return localizedSlugs; | |
} | |
// Example usage | |
const slugs = ['/about', '/products', '/contact']; | |
const locales: Locale[] = ['en-US', 'es', 'hm']; | |
const localizedUrls = generateLocalizedUrls(slugs, locales); | |
console.log(localizedUrls); |
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
import { Component } from 'react'; | |
import Link from 'next/link'; | |
import { useRouter } from 'next/router'; | |
type Locale = 'en-US' | 'es' | 'hm'; | |
interface LocaleSelectorProps { | |
locales: Locale[]; | |
} | |
interface LocaleLinkProps { | |
href: string; | |
} | |
class LocaleSelector extends Component<LocaleSelectorProps> { | |
handleLocaleChange = (event: React.ChangeEvent<HTMLSelectElement>) => { | |
const selectedLocale = event.target.value; | |
localStorage.setItem('selectedLocale', selectedLocale); | |
}; | |
render() { | |
const { locales } = this.props; | |
return ( | |
<select onChange={this.handleLocaleChange}> | |
{locales.map((locale) => ( | |
<option key={locale} value={locale}> | |
{locale} | |
</option> | |
))} | |
</select> | |
); | |
} | |
} | |
const LocaleLink: React.FC<LocaleLinkProps> = ({ href, children }) => { | |
const router = useRouter(); | |
const selectedLocale = localStorage.getItem('selectedLocale') as Locale; | |
const localeHref = `/${selectedLocale}${href}`; | |
return ( | |
<Link href={localeHref} passHref> | |
<a className={router.asPath === localeHref ? 'active' : ''}>{children}</a> | |
</Link> | |
); | |
}; | |
export default function HomePage() { | |
const locales: Locale[] = ['en-US', 'es', 'hm']; | |
return ( | |
<div> | |
<h1>Home Page</h1> | |
<LocaleSelector locales={locales} /> | |
<p> | |
<LocaleLink href="/about">About</LocaleLink> | |
</p> | |
<p> | |
<LocaleLink href="/products">Products</LocaleLink> | |
</p> | |
<p> | |
<LocaleLink href="/contact">Contact</LocaleLink> | |
</p> | |
</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
type Locale = 'en' | 'es' | 'hm'; | |
function generateLocalizedUrls(slugs: string[], locales: Locale[]): string[] { | |
const defaultLocale = 'en'; | |
const localizedSlugs = []; | |
for (const slug of slugs) { | |
for (const locale of locales) { | |
const localeCode = locale === defaultLocale ? '' : `/${locale}`; | |
const localizedSlug = slug.startsWith('/') ? `${localeCode}${slug}` : `${localeCode}/${slug}`; | |
localizedSlugs.push(localizedSlug); | |
} | |
} | |
return localizedSlugs; | |
} | |
// Example usage | |
const slugs = ['about', 'products', 'contact']; | |
const locales: Locale[] = ['en', 'es', 'hm']; | |
const localizedUrls = generateLocalizedUrls(slugs, locales); | |
console.log(localizedUrls); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment