Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Geting rid of unstable_setRequestLocale #663

Open
amannn opened this issue Nov 24, 2023 · 6 comments
Open

Geting rid of unstable_setRequestLocale #663

amannn opened this issue Nov 24, 2023 · 6 comments
Labels
area: performance enhancement New feature or request

Comments

@amannn
Copy link
Owner

amannn commented Nov 24, 2023

As mentioned in the static rendering docs, unstable_setRequestLocale is intended as a stopgap solution to be removed at some point.

I've started a discussion for the relevant feature on the Next.js side here: vercel/next.js#58862

If you'd like to help simplify the usage of next-intl, please join the discussion there and upvote the comment!

@amannn amannn added enhancement New feature or request unconfirmed Needs triage. labels Nov 24, 2023
@amannn amannn pinned this issue Nov 24, 2023
@amannn amannn removed the unconfirmed Needs triage. label Nov 24, 2023
@xie392
Copy link

xie392 commented Dec 12, 2023

image
Some components need to use "use client", and I want to output static files. There is a conflict between the two. How should I solve it?

@amannn
Copy link
Owner Author

amannn commented Dec 12, 2023

You don’t need to call the function in client-only pages.

amannn added a commit that referenced this issue Dec 21, 2023
…and update docs to suggest validating the locale in `i18n.ts` (#742)

Users are currently struggling with errors that are caused by these two
scenarios:
1. An invalid locale was passed to `next-intl` APIs (e.g.
[#736](#736))
2. No locale is available during rendering (e.g.
[#716](#716))

**tldr:**
1. We now suggest to validate the incoming `locale` in
[`i18n.ts`](https://next-intl-docs.vercel.app/docs/usage/configuration#i18nts).
This change is recommended to all users.
2. `next-intl` will call the `notFound()` function when the middleware
didn't run on a localized request and `next-intl` APIs are used during
rendering. Previously this would throw an error, therefore this is only
relevant for you in case you've encountered [the corresponding
error](https://next-intl-docs.vercel.app/docs/routing/middleware#unable-to-find-locale).
Make sure you provide a relevant [`not-found`
page](https://next-intl-docs.vercel.app/docs/environments/error-files#not-foundjs)
that can be rendered in this case.

---

**Handling invalid locales**

Users run into this error because the locale wasn't sufficiently
validated. This is in practice quite hard because we currently educate
in the docs that this should happen in [the root
layout](https://next-intl-docs.vercel.app/docs/getting-started/app-router#applocalelayouttsx),
but due to the parallel rendering capabilities of Next.js, potentially a
page or `generateMetadata` runs first.

Therefore moving this validation to a more central place seems
necessary. Due to this, the docs will now suggest validating the locale
in `i18n.ts`. By doing this, we can catch erroneous locale arguments in
a single place before e.g. importing JSON files.

The only edge case is if an app uses no APIs of `next-intl` in Server
Components at all and therefore `i18n.ts` doesn't run. This should be a
very rare case though as even `NextIntlClientProvider` will call
`i18n.ts`. The only case to run into this is if you're using
`NextIntlClientProvider` in a Client Component and delegate all i18n
handling to Client Components too. If you have such an app, `i18n.ts`
will not be invoked and you should validate the `locale` before passing
it to `NextIntlClientProvider`.

**Handling missing locales**

This warning is probably one of the most annoying errors that users
currently run into:

```
Unable to find next-intl locale because the middleware didn't run on this request.
```

The various causes of this error are outlined in [the
docs](https://next-intl-docs.vercel.app/docs/routing/middleware#unable-to-find-locale).

Some of these cases should simply be 404s (e.g. when your middleware
matcher doesn't match `/unknown.txt`), while others require a fix in the
matcher (e.g. considering `/users/jane.doe` when using `localePrefix:
'as-necessary'`).

My assumption is that many of these errors are false positives that are
caused by the `[locale]` segment acting as a catch-all. As a result, a
500 error is encountered instead of 404s. Due to this, this PR will
downgrade the previous error to a dev-only warning and will invoke the
`notFound()` function. This should help in the majority of cases. Note
that you should define [a `not-found`
file](https://next-intl-docs.vercel.app/docs/environments/error-files#not-foundjs)
to handle this case.

I think this change is a good idea because if you're using
`unstable_setRequestLocale` and you have a misconfigured middleware
matcher, you can provide any kind of string to `next-intl` (also
`unknown.txt`) and not run into this error. Therefore it only affects
users with dynamic rendering. Validating the locale in `i18n.ts` is the
solution to either case (see above). Also in case something like
[`routeParams`](#663) gets
added to Next.js, the current warning will be gone entirely—therefore
tackling it from a different direction is likely a good idea.

The false negatives of this should hopefully be rather small as we
consistently point out that you need to adapt your middleware matcher
when switching the `localePrefix` to anything other than `always`.
Dev-only warnings should help to get further information for these
requests.

---

Closes #736
Closes #716
Closes #446
@AhmedBaset
Copy link
Contributor

I'm curious about whether calling setRequestLocale at the top level app/[locale]/layout.tsx will apply to the whole app or not?

When exporting generateStaticParams at the layout all sub routes are affected by it.

@amannn
Copy link
Owner Author

amannn commented Jan 9, 2024

Unfortunately not, please see the corresponding docs: Add unstable_setRequestLocale to all layouts and pages. It might work in some cases, but there's a race condition. To work reliably, you should add it to every layout and every page that you wish to enable static rendering for.

@amannn
Copy link
Owner Author

amannn commented May 1, 2024

We'll probably introduce support for providing a locale to next-intl as an alternative to having to use the middleware to negotiate this (see #1017). If your app only supports a single locale, this will enable static rendering without workarounds.

@amannn
Copy link
Owner Author

amannn commented May 13, 2024

A realization while working on #1017: We currently support a defaultLocale that is used as a fallback when matching locales in the middleware. However, the defaultLocale only applies to this particular case.

Developers have previously asked why the defaultLocale isn't used when using next-intl APIs outside of the [locale] folder (see e.g. #1067, but also others).

In case the developer could manage the reading of the locale from params manually in i18n.ts, this would also enable returning a fallback locale for cases like this.

Ideally, something like this would be possible:

import {notFound} from 'next/navigation';
import {getRequestConfig} from 'next-intl/server';
import {routeParams} from '???';
 
// Can be imported from a shared config
const locales = ['en', 'de'];
 
export default getRequestConfig(async () => {
  let {locale} = routeParams();
  if (!locale) locale = 'en';

  // Validate that the incoming `locale` parameter is valid
  if (!locales.includes(locale as any)) notFound();
 
  return {
    locale,
    messages: (await import(`../messages/${locale}.json`)).default
  };
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: performance enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants