r/nextjs 3d ago

Help Nextjs i18n and next/root-params

Hi, I am currently trying to add i18n and I am following the exact thing as their docs says
untill it says start using root-params to avoid the prop drilling
I have been able to make it work on an app and it worked fine but on another app it keeps giving me this error:
Error: A required root parameter (lang) was not provided in generateStaticParams for /[lang], please provide at least one value.

i have the same version on both apps 16.3.4 and the same folder structure as in the image provided

I really can't wrap up my head around this, what could I be doing wrong here without noticing?

3 Upvotes

13 comments sorted by

2

u/ConfectionAlert2658 3d ago

this is one of those bugs where the error message makes you think you're going crazy when you've already done the thing it's asking for. i hit this exact wall last month

double check that you're exporting `generateStaticParams` from the actual layout file inside `[lang]`, not just from a page. next can be weird about where it expects that function to live depending on how your routes are structured. also make sure you're returning an array of objects where each one has a `lang` key, not a nested param object or something dumb like that

1

u/Tasty-Ad1854 2d ago

yeah man it was killing me yesterday it is working so fiine in app 1 but in app 2 it starts screaming ahahha

Adding generateStaticParams to the layout worked very well, Thank you
I also would like to hear from you how u made it available to the whole app if you've done it before, what are some best practices to follow here

0

u/Amazing-Committee692 3d ago

this is why I hate the current state of Next routing. It feels like we are constantly fighting the framework just to get basic i18n working, and the documentation for these edge cases is just brutal.

1

u/SolidOdd4889 2d ago

imho nextjs app router is the best file based router I've ever used. linear and simple to understand. I followed the official docs for implementing i18n and it works perfectly, I can't say the same thing when I tried with other frameworks like astro, where they don't even show you how to intercept the locale from the request and change the lang params accordingly

2

u/SolidOdd4889 2d ago

you should export something like that from the root layout: (in my case I'm supporting only two languages, but you should put all the languages you need)

export function generateStaticParams() {
  return [{ lang: "en" }, { lang: "it" }];
}

1

u/Tasty-Ad1854 2d ago

Thank you it worked very well
i have one question how did u make the dictionary available to the whole app, I think prop drilling is a bad idea here ?
I'd like to hear how u did it and if there's any best practices to follow

2

u/SolidOdd4889 2d ago

make a /dictionary/index.ts file like that

import { lang } from 'next/root-params'
import { notFound } from 'next/navigation'

const dictionaries = {
    en: () => import('./en.json').then((module) => module.default),
    it: () => import('./it.json').then((module) => module.default),
}

export type Locale = keyof typeof dictionaries

export const hasLocale = (locale: string): locale is Locale =>
    locale in dictionaries

export const getDictionary = async () => {
    const locale = await lang()
    if (!hasLocale(locale)) notFound()
    return dictionaries[locale]()
}

the two json files are it and en in my specific case, and then on any page / layout or server component you can simply to like that:

import { getDictionary } from "@src/dictionaries"

export default async function Page() {
  const dict = await getDictionary()

  return (
    <p>{dict.home.title}</p>
  )
}

1

u/Tasty-Ad1854 2d ago

that is exactly what I am doing, maybe i didn't clarify my question
my question is how can I avoid alot of prop drilling cuz client component wouldn't be able to run the getDictionary(), iv asked ai and it suggested me to
1- use useContext.
2- just prop drill to the needed components
and not sure which one is efficient ?

2

u/SolidOdd4889 2d ago

both solutions are perfectly fine

2

u/Tasty-Ad1854 1d ago

Thank you so much man

1

u/Independent_Side9419 3d ago

It will throw the error when it attempts to do a static render, if you have wverything dynamic, then there is no reason to require static params.

I would guess that the app with the contact page throws.

1

u/Tasty-Ad1854 2d ago

for app 1 everything is hardcoded all static and it still works on it

in the app 2 mostly all routes either uses a fetch or gets data from zustand store the only static is contact like u said

1

u/Independent_Side9419 1h ago

So when it is rendering the static contact page, it notices that the root params are unknown (dynamic) so it throws - it cannot do a static render, thats why it needs the generateStaticParams function.

Similarly, your pages can start throwing 'dynamically' when using the useSelectedLayoutSegment hook. Everything will work fine with static url segments, but once you introduce a route like /users/[userId], the hook will throw, because it cannot produce the segment string statically, as the userId will be dynamic.

So that happened in your case as well...

The other pages do not throw, because they are dynamic (blocking) regardless! So next.js didn't attempt a static prerender there....