How to generate dynamic paths for non-default locales in Next.js?
I am building a Next.js app with internationalization using next-i18next. Pages are generated for all the pages of my site for both English and French, except for pages with dynamic routes: (i.e., blog/[id]/[blog-title]
). For pages with dynamic routes, pages are generated for English, but not for French.
I should note that the blog entries are the same in both languages. So if the user click on a blog entry in the list, they will get the same blog entry.
When a French language user goes to a page with a dynamic route they get a 404. I am new to React and Next so I could be doing something dumb here.
// next-i18next.config.js
module.exports = {
i18n: {
locales: ['en', 'fr'],
defaultLocale: 'en',
localeDetection: true,
},
}
//
// blog\[id]\[title]
//
export async function getStaticPaths() {
const response = await axios.get('https://api.myappi.com/blog')
const posts = response.data
const paths = posts.map((post: Props) => ({
params: { id: post.Id, title: post.Title },
}))
return { paths, fallback: false }
}
export async function getStaticProps(props: IStaticProps) {
const { id, locale } = props.params
const response = await axios.get(`https://api.myappi.com/blog/${id}`)
const post = await response.data
if (!post) {
return {
notFound: true,
}
}
return {
props: {
Id: post.Id,
Title: post.Title,
Blog: post.Blog,
DatePosted: post.DatePosted,
PostedBy: post.PostedBy,
...(await serverSideTranslations(props.locale, ['common', 'blog']))
}
}
}
Solution 1:
For dynamic routes, you have to explicitly return the locales you want to be pre-generated from the getStaticPaths
function. If you don't, Next.js will only generate pages for the default locale.
From Internationalized Routing documentation:
For pages using
getStaticProps
with Dynamic Routes, all locale variants of the page desired to be prerendered need to be returned fromgetStaticPaths
. Along with theparams
object returned forpaths
, you can also return alocale
field specifying which locale you want to render.
This can be achieved by modifying your getStaticPaths
function to generate a path for each slug/locale combination.
export async function getStaticPaths({ locales }) { // Get available locales from `context`
const response = await axios.get('https://api.myappi.com/blog')
const posts = response.data
const paths = posts
.map((post: Props) => locales.map((locale) => ({
params: { id: post.Id, title: post.Title },
locale // Pass locale here
})))
.flat() // Flatten array to avoid nested arrays
return { paths, fallback: false }
}