-
-
Notifications
You must be signed in to change notification settings - Fork 233
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
179 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
import VersionTabs from 'components/VersionTabs'; | ||
import Callout from 'components/Callout'; | ||
|
||
# Internationalization in Next.js error files | ||
|
||
The Next.js file convention provides two files that can be used for error handling: | ||
|
||
1. [`not-found.js`](https://nextjs.org/docs/app/api-reference/file-conventions/not-found) | ||
2. [`error.js`](https://nextjs.org/docs/app/api-reference/file-conventions/error) | ||
|
||
While `not-found.js` can either be a Server or Client Component, the latter two files require to be Client Components. Therefore depending on the file, you have to make sure that you're [providing configuration like messages](/docs/configuration#client-server-components) accordingly. | ||
|
||
This page provides practical guides for these cases. | ||
|
||
<Callout> | ||
Have a look at [the App Router example](/examples/app-router) to explore a | ||
working app with error handling. | ||
</Callout> | ||
|
||
## `not-found.js` | ||
|
||
Next.js renders the nearest `not-found` page when a route segment throws a [`notFound` function](https://nextjs.org/docs/app/api-reference/functions/not-found). Since we rely on the `[locale]` segment to localize our app, the `not-found` page needs to be located within this segment. | ||
|
||
```tsx filename="app/[locale]/not-found.tsx" | ||
import {useTranslations} from 'next-intl'; | ||
import PageLayout from 'components/PageLayout'; | ||
|
||
export default function NotFoundPage() { | ||
const t = useTranslations('NotFoundPage'); | ||
return <h1>{t('title')}</h1>; | ||
} | ||
``` | ||
|
||
Note however that Next.js will only render this page, when the `notFound` function is thrown from within a route, not for all unknown routes in general. | ||
|
||
### Catching unknown routes | ||
|
||
To catch unknown routes too, we can define a catch-all route that explicitly throws the `notFound` function. | ||
|
||
```tsx filename="app/[locale]/[...rest]/page.tsx" | ||
import {notFound} from 'next/navigation'; | ||
|
||
export default function CatchAllPage() { | ||
notFound(); | ||
} | ||
``` | ||
|
||
After this change, all routes that are matched within the `[locale]` segment will render the defined `not-found` page when an unknown route is encountered. | ||
|
||
### Catching non-localized requests | ||
|
||
When the user requests a route that is not matched by [the `next-intl` middleware](/docs/routing/middleware) (depending on your `matcher` config), there's no locale associated with the request. You can add a root `not-found` page to handle these cases too (e.g. `/unknown.txt`). | ||
|
||
```tsx filename="app/not-found.tsx" | ||
'use client'; | ||
|
||
import Error from 'next/error'; | ||
|
||
// Render the default Next.js 404 page when a route | ||
// is requested that doesn't match the middleware and | ||
// therefore doesn't have a locale associated with it. | ||
|
||
export default function NotFound() { | ||
return ( | ||
<html lang="en"> | ||
<body> | ||
<Error statusCode={404} /> | ||
</body> | ||
</html> | ||
); | ||
} | ||
``` | ||
|
||
## `error.js` | ||
|
||
When an unexpected runtime error is encountered within your components, Next.js will gracefully handle the error by [using the closest `error` file](https://nextjs.org/docs/app/building-your-application/routing/error-handling). When an `error` file is defined, Next.js will create [an error boundary within your layout that wraps pages accordingly](https://nextjs.org/docs/app/building-your-application/routing/error-handling#how-errorjs-works). | ||
|
||
Since the `error` file must be defined as a Client Component, you have to use [`NextIntlClientProvider`](/docs/configuration#client-server-components) to provide messages in case the `error` file renders. | ||
|
||
If you've [set up `next-intl` to be used in Client Components](http://localhost:3001/docs/getting-started/app-router-client-components), this is already the case and there's no additional setup needed. If you're using [the Server Components beta](/docs/getting-started/app-router-server-components), you have to provide the relevant messages in the wrapping layout. | ||
|
||
```tsx filename="app/[locale]/layout.tsx" | ||
import pick from 'lodash/pick'; | ||
|
||
// (only necessary when using the Server Components beta) | ||
|
||
export default async function LocaleLayout({children}) { | ||
// ... | ||
const messages = useMessages(); | ||
|
||
return ( | ||
<html lang={locale}> | ||
<body> | ||
<NextIntlClientProvider | ||
locale={locale} | ||
messages={pick(messages, 'Error')} | ||
> | ||
{children} | ||
</NextIntlClientProvider> | ||
</body> | ||
</html> | ||
); | ||
} | ||
``` | ||
|
||
Once `NextIntlClientProvider` is in place, you can use `next-intl` APIs in the `error` file: | ||
|
||
```tsx filename="app/[locale]/error.tsx" | ||
'use client'; | ||
|
||
import {useTranslations} from 'next-intl'; | ||
|
||
export default function Error({error, reset}) { | ||
const t = useTranslations('Error'); | ||
|
||
return ( | ||
<div> | ||
<h1>{t('title')}</h1> | ||
<button onClick={reset}>{t('retry')}</button> | ||
</div> | ||
); | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
'use client'; | ||
|
||
import {useTranslations} from 'next-intl'; | ||
import {useEffect} from 'react'; | ||
import PageLayout from 'components/PageLayout'; | ||
|
||
type Props = { | ||
error: Error; | ||
reset(): void; | ||
}; | ||
|
||
export default function Error({error, reset}: Props) { | ||
const t = useTranslations('Error'); | ||
|
||
useEffect(() => { | ||
console.error(error); | ||
}, [error]); | ||
|
||
return ( | ||
<PageLayout title={t('title')}> | ||
<div> | ||
{t.rich('description', { | ||
p: (chunks) => <p className="mt-4">{chunks}</p>, | ||
retry: (chunks) => ( | ||
<button | ||
className="text-white underline underline-offset-2" | ||
onClick={reset} | ||
type="button" | ||
> | ||
{chunks} | ||
</button> | ||
) | ||
})} | ||
</div> | ||
</PageLayout> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters