amannn / next-intl

🌐 Internationalization (i18n) for Next.js
https://next-intl-docs.vercel.app
MIT License
2.58k stars 236 forks source link

feat: new hook(s) to retrieve dynamic defaultLocale and locales set in the middleware #1320

Closed rongsen-kaligo closed 2 months ago

rongsen-kaligo commented 2 months ago

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

I'm working on an internal project where the edge middleware will dynamically retrieve the defaultLocale and locales and pass the values to createNextIntlMiddleware(). There isn't a way for us to retrieve these values in both server and client components via hooks or async functions. It'd be great if we could get the values without writing our own providers to forward the values from server side to client side.

Describe the solution you'd like

I'd like to propose new hooks and async functions to retrieve current values of defaultLocale and locales which could be set dynamically in the edge middleware just like other existing hooks and async functions:

  1. async getDefautlLocale()
  2. useDefaultLocale()
  3. async getLocales()
  4. useLocales()

I think being explicit is preferrable instead of exposing 1 hook that returns multiple values but I'm opposing such approach.

Describe alternatives you've considered

Writing our own provider to pass the values from the edge middlewares via request.headers to the client components.

// pseudo-code

// middleware
const { defaultLocale, locales } = await getDynamicValues();

request.headers.set('x-default-locale', defaultLocale);
request.headers.set('x-locales', locales.toString());

createNextIntlMiddleware({ defaultLocale, locales, ... });

// server component
const defaultLocale = headers().get('x-default-locale') ?? fallbackDefaultLocale;
const locales = headers().get('x-locales') ?? fallbackLocales;

<LocaleConfigProvider locales={locales} defaultLocale={defaultLocale}>...</LocaleConfigProvider>

// client component
const { defaultLocale, locales } = useLocaleConfig();

await fetch('...', { headers: { 'x-accept-language': `${selectedLocale}, ${defaultLocale}` } });
amannn commented 2 months ago

Thanks for the question! As you've probably noticed, passing data from the middleware to the RSC render is unfortunately a bit cumbersome currently. next-intl currently limits this to the locale that is received by the [locale] segment in your app, but further additions are not planned currently.

I think your options currently are:

  1. The workaround with the header that you've shared
  2. Running the logic for fetching your default locale and locales in a Server Component again

That being said, it seems like the Next.js team is working on revamping the middleware: https://github.com/vercel/next.js/discussions/46722#discussioncomment-10262088. I found this particular sentence in the announcement interesting:

Then, you could pass data to the rendering phase.

As far as I'm aware, there's no clarification available currently on what this means, but maybe it could work for your use case in the future!

I'll close this as this particular feature is currently not planned.