Receive notifications about upcoming Intlayer releases

    Static vs Dynamic Rendering with i18n in Next.js

    The issue with next-intl

    • What happens? When you use useTranslations, getTranslations, or any next-intl helper inside a Server Component on an i18n-routed app (/en/…, /fr/…), Next.js marks the whole route dynamic. ([Next Intl][1])

    • Why? next-intl looks up the current locale from a request-only header (x-next-intl-locale) via headers(). Because headers() is a dynamic API, any component that touches it loses static optimisation. ([Next Intl][1], [Next.js][2])

    • Official workaround (boilerplate)

      1. Export generateStaticParams with every supported locale.
      2. Call setRequestLocale(locale) in every layout/page before you call useTranslations. ([Next Intl][1]) This removes the header dependency, but you now have extra code to maintain and an unstable API in production.

    How intlayer sidesteps the problem

    Design choices

    1. Route-param only – The locale comes from the [locale] URL segment that Next.js already passes to every page.
    2. Compile-time bundles – Translations are imported as regular ES modules, so they’re tree-shaken and embedded at build-time.
    3. No dynamic APIsuseT() reads from React context, not from headers() or cookies().
    4. Zero extra config – Once your pages live under app/[locale]/, Next.js prerenders one HTML file per locale automatically.