Skip to content

Prepare for async await headers() in Next.js 15 #1375

Closed
@amannn

Description

@amannn

Is your feature request related to a problem? Please describe.

Ref.: vercel/next.js#68812

next-intl currently relies on reading a request header to detect the current locale when relevant APIs are called in a Server Component. Note that this by itself is a workaround, ideally the locale could be retrieved from a param (see vercel/next.js#58862).

The APIs next-intl offers can be put in three categories:

  1. Formatting APIs (useTranslations & useFormatter)
  2. APIs for retrieving global configuration (e.g. useLocale)
  3. Navigation APIs (e.g. Link—these are lightweight wrappers for navigation APIs from Next.js and automatically incorporate localization of pathnames like locale prefixes)

The first two categories use APIs that have signatures that are either hooks or awaitable async functions—so those should be fine to update.

In the third category, the APIs are a bit more diverse. However, most APIs can be adapted as necessary:

  1. The Link component can be turned async to use await getLocale() internally
  2. useRouter & usePathname can consume a promise via use
  3. getPathname requires an explicit locale anyway

Only one API stands out as problematic: redirect

This is a function that can be called in the following environments:

  1. During the RSC render in an async component
  2. During the RSC render in a non-async component
  3. During SSR in a Client Component
  4. During CSR in a Client Component
  5. (Calling outside of render, e.g. in an event handler, will not have any effect)

Since use(…) doesn't work in async components, we'd have to use an awaitable API for (1). However, for the other call sites, a non-awaitable API would be more ergonomic (otherwise the user would have to wrap in use)

Describe the solution you'd like

I can think of the following solutions to address this:

  1. Require a locale to be passed to redirect: redirect({locale: 'en', href: '/about'}). To retrieve the locale, it'd be the job of the user to either call async getLocale() or useLocale() depending on the calling component.
    • Pros: Flexible, also adding the capability to redirect to other locales
    • Cons: More verbose to what we had before (i.e. redirect('/about')
  2. Make redirect awaitable
    • Pros: Can keep the ergonomics and not require a locale (mostly)
    • Cons: Divergence from what the user knows from Next.js (prone to errors), can not be used in non-async components

Another implication is likely that the user can't read the locale that's passed to i18n/request.ts synchronously. We might have to replace this with something promise-based (await locale or await getLocale()).

Moving forward

As matters stand currently, it seems like (1) will be more future-proof. Also, in case use() becomes available in async Server Components in the future, we can put back a default for the current locale in a later release.

Note that the navigation APIs are currently being reworked in #1316, so now would be a good point to adjust for the future.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions