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

feat: Invoke notFound() when no locale was attached to the request and update docs to suggest validating the locale in i18n.ts #742

Merged
merged 3 commits into from
Dec 21, 2023

Conversation

amannn
Copy link
Owner

@amannn amannn commented Dec 20, 2023

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)
  2. No locale is available during rendering (e.g. #716)

tldr:

  1. We now suggest to validate the incoming locale in i18n.ts. If you've previously validated the locale e.g. in the root layout, you can move this validation to i18n.ts now. This change is recommended to all users.
  2. next-intl will now 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. If you've previously been affected by this error, please make sure that your middleware matcher is set up correctly and that you're providing a not-found page 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, 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.

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 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 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

…and update docs to suggest validating the locale in `i18n.ts`
Copy link

vercel bot commented Dec 20, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
next-intl-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Dec 21, 2023 8:14am
next-intl-example-app-router ✅ Ready (Inspect) Visit Preview 💬 Add feedback Dec 21, 2023 8:14am

@amannn amannn marked this pull request as ready for review December 21, 2023 08:12
@amannn amannn merged commit e6d9878 into main Dec 21, 2023
5 checks passed
@amannn amannn deleted the docs/validate-locale-i18n branch December 21, 2023 08:39
juanforlizzi pushed a commit to juanforlizzi/next-intl that referenced this pull request Jan 16, 2025
…and update docs to suggest validating the locale in `i18n.ts` (amannn#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.
[amannn#736](amannn#736))
2. No locale is available during rendering (e.g.
[amannn#716](amannn#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`](amannn#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 amannn#736
Closes amannn#716
Closes amannn#446
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant