Статичний vs динамічний рендеринг з i18n у Next.js
Проблема з next-intl
Що відбувається? Коли ви використовуєте useTranslations, getTranslations, або будь-який хелпер next-intl всередині Server Component в застосунку з i18n-маршрутизацією (/en/…, /fr/…), Next.js позначає весь маршрут як dynamic. ([Next Intl][1])
Чому? next-intl визначає поточну локаль з заголовка, доступного лише в запиті (x-next-intl-locale) через headers(). Оскільки headers() — це динамічний API, будь-який компонент, який до нього звертається, втрачає статичну оптимізацію. ([Next Intl][1], [Next.js][2])
Офіційне рішення (boilerplate)
- Експортуйте generateStaticParams для кожної підтримуваної локалі.
- Викликайте setRequestLocale(locale) у кожному layout/page перед тим, як викликати useTranslations. ([Next Intl][1]) Це усуває залежність від заголовка, але додає додатковий код для підтримки та використовує нестабільний API у продакшені.
Як intlayer обходить проблему
Дизайн-рішення
- Тільки параметр маршруту (route-param only) – локаль береться з сегмента URL [locale], який Next.js вже передає кожній сторінці.
- Бандли на етапі компіляції – Переклади імпортуються як звичайні ES-модулі, тож вони піддаються tree-shaking і вбудовуються під час збірки.
- Без динамічних API – useT() читає з React context, а не з headers() або cookies().
- Жодної додаткової конфігурації – Як тільки ваші сторінки розміщені під app/[locale]/, Next.js автоматично генерує по одному HTML‑файлу на кожну локаль.