Implementing i18n with Dynamic Routing on NextJs

Viewed 539

I am implementing dynamic routing and i18n with Next.js. My app consists of 2 locales: en-US and es-MX. I am trying to generate the following routes:

  • /blog/posts/[id]
  • /es-MX/blog/posts/[id]

Using the default locale (en-US), my links point to /blog/posts/id and I am able to navigate to any id; for example: /blog/posts/1 without any issue. However, when I switch locale, my links now point to the route /es-MX/blog/posts/1, which in turn result in a 404 error - not found.

My slug directory consists of the structure pages/blog/posts/[id].js and in this file I use getStaticPaths to generate the paths for the above locales:

export const getStaticPaths({locales}) => {
   const res = await fetch(`${server}/api/posts`);
   const posts = await res.json();

   const ids = posts.map((post) => post.id);
   const paths = ids.map((id) => ({
      params: {id: id.toString(), locale: 'en-US' },
      params: {id: id.toString(), locale: 'es-MX' },
   }));

   return {
       paths,
       fallback: false,
   };
}

I intend to pull post translations from the api according to the current locale. Everything else including all the other routes in the app work as expected, except this route. What am I missing?

1 Answers

the problem you're having there is you're returning locale inside params which is wrong, locale should be outside of params because it can be accessed through context.locale and not context.params.locale, it worked for the defaultLocale because that's the default behavior of getStaticPaths with locales, read more on this here.

it's better if you rework your getStaticPaths like below to avoid problems with params:

export const getStaticPaths = async ({ locales }) => {
  const res = await fetch(`${server}/api/posts`);
  const posts = await res.json();

  const ids = posts.map((post) => post.id);
  const paths = ids
    .map((id) =>
      locales.map((locale) => ({
        params: { id: id.toString() },
        locale, //locale should not be inside `params`
      }))
    )
    .flat(); // to avoid nested arrays

  return {
    paths,
    fallback: false,
  };
};
Related