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

docs: Update docs and examples to Next.js 15 #1089

Draft
wants to merge 45 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
a8496ab
feat: Support Next.js 15 and React 19
amannn May 24, 2024
f900128
Revert "feat: Support Next.js 15 and React 19"
amannn May 24, 2024
5f3002f
Update `example-app-router`
amannn May 24, 2024
b746959
Upgrade `example-app-router-playground` and get rid of middleware war…
amannn May 24, 2024
a3a4ccf
Fix imports
amannn May 24, 2024
822e4d9
Merge remote-tracking branch 'origin/main' into chore/next-15
amannn Aug 23, 2024
d743797
Merge remote-tracking branch 'origin/main' into chore/next-15
amannn Oct 16, 2024
b9f7925
remove config
amannn Oct 16, 2024
ccc2c51
latest rc, run codemod
amannn Oct 16, 2024
beab339
fix some failing tests
amannn Oct 16, 2024
c20c78a
add next/font to the mix
amannn Oct 16, 2024
21eacb6
Merge remote-tracking branch 'origin/canary' into chore/next-15
amannn Oct 16, 2024
4e9af1e
Merge branch 'canary' into chore/next-15
amannn Oct 16, 2024
5789282
fix mdx rendering
amannn Oct 16, 2024
e1cfa7b
bump versions for all examples and docs, adapt types in next-intl
amannn Oct 16, 2024
07e8079
migrate example-app-router
amannn Oct 16, 2024
2737664
migrate examples
amannn Oct 16, 2024
96d5ecf
update docs
amannn Oct 16, 2024
443f16a
fix react-dom deps
amannn Oct 16, 2024
e409be2
Merge remote-tracking branch 'origin/canary' into chore/next-15
amannn Oct 17, 2024
76be200
Merge branch 'canary' into chore/next-15
amannn Oct 18, 2024
4e3de1f
use release
amannn Oct 22, 2024
66b3428
Merge remote-tracking branch 'origin/main' into chore/next-15
amannn Oct 22, 2024
57e4377
downgrade to next 14 for docs
amannn Oct 22, 2024
c7a8c79
try ts config, remove workaround, make global not found page not usin…
amannn Oct 22, 2024
5ff901e
update to next 15.0.3
amannn Dec 4, 2024
9f56e2e
Merge remote-tracking branch 'origin/main' into chore/next-15
amannn Jan 23, 2025
cb9dada
update assertion
amannn Jan 23, 2025
10cbf0d
canary
amannn Jan 23, 2025
08690b9
lockfile
amannn Jan 23, 2025
79221f8
lockfile
amannn Jan 23, 2025
d9018ec
adapt assertion
amannn Jan 23, 2025
7f13966
more tests
amannn Jan 23, 2025
2bd1a7a
enable nextjs eslint plugin and use standard config in examples
amannn Jan 23, 2025
9b4a79f
simplify
amannn Jan 23, 2025
2decc36
update build output
amannn Jan 23, 2025
d19a63b
cleanup
amannn Jan 23, 2025
c540471
lockfile
amannn Jan 23, 2025
748c3b7
fix lint
amannn Jan 23, 2025
92998e7
.ts configs
amannn Jan 23, 2025
8af13fc
fix
amannn Jan 23, 2025
4d4fe97
fix lint
amannn Jan 23, 2025
b7f456a
split out navigation apis in examples
amannn Jan 23, 2025
379d059
update docs to use separate navigation module
amannn Jan 23, 2025
2213185
cleanup
amannn Jan 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions docs/src/components/CodeSnippets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -293,23 +293,23 @@ function buildOutput() {
<span className="line">
<span data-token="text">┌ ● /</span>
<span data-token="text"> </span>
<span data-token="text">{' '}2.1 kB</span>
<span data-token="text">{' '}2.5 kB</span>
<span data-token="text">{' '}</span>
<span data-token="string">97.1 kB</span>
<span data-token="string">115 kB</span>
</span>
<span className="line">
<span data-token="text">├ ● /about</span>
<span data-token="text">{' '}</span>
<span data-token="text">2.5 kB</span>
<span data-token="text">2.6 kB</span>
<span data-token="text">{' '}</span>
<span data-token="string">97.6 kB</span>
<span data-token="string">116 kB</span>
</span>
<span className="line">
<span data-token="text">└ λ /[username]</span>
<span data-token="text">{' '}</span>
<span data-token="text">3.2 kB</span>
<span data-token="text">{' '}</span>
<span data-token="string">98.3 kB</span>
<span data-token="string">117 kB</span>
</span>
<span className="line"> </span>
<span className="line">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ To internationalize metadata like the page title, you can use functionality from
```tsx filename="layout.tsx"
import {getTranslations} from 'next-intl/server';

export async function generateMetadata({params: {locale}}) {
export async function generateMetadata({params}) {
const {locale} = await params;
const t = await getTranslations({locale, namespace: 'Metadata'});

return {
Expand Down Expand Up @@ -113,7 +114,8 @@ If you're programmatically generating [Open Graph images](https://nextjs.org/doc
import {ImageResponse} from 'next/og';
import {getTranslations} from 'next-intl/server';

export default async function OpenGraphImage({params: {locale}}) {
export default async function OpenGraphImage({params}) {
const {locale} = await params;
const t = await getTranslations({locale, namespace: 'OpenGraphImage'});
return new ImageResponse(<div style={{fontSize: 128}}>{t('title')}</div>);
}
Expand Down
4 changes: 3 additions & 1 deletion docs/src/pages/docs/environments/error-files.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ For the 404 page to render, we need to call the `notFound` function in the root
```tsx filename="app/[locale]/layout.tsx"
import {notFound} from 'next/navigation';

export default function LocaleLayout({children, params: {locale}}) {
export default async function LocaleLayout({children, params}) {
const {locale} = await params;

// Ensure that the incoming `locale` is valid
if (!routing.locales.includes(locale as any)) {
notFound();
Expand Down
4 changes: 3 additions & 1 deletion docs/src/pages/docs/environments/mdx.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ Now, in `page.tsx`, you can import the MDX content based on the user's locale:
import {notFound} from 'next/navigation';

export default async function HomePage({params}) {
const {locale} = await params;

try {
const Content = (await import(`./${params.locale}.mdx`)).default;
const Content = (await import(`./${locale}.mdx`)).default;
return <Content />;
} catch (error) {
notFound();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,19 @@ Now, we're going to create the following file structure:

```
├── messages
│ ├── en.json (1)
│ ├── en.json
│ └── ...
├── next.config.mjs (2)
├── next.config.ts
└── src
├── i18n
│ ├── routing.ts (3)
│ └── request.ts (5)
├── middleware.ts (4)
│ ├── routing.ts
│ ├── navigation.ts
│ └── request.ts
├── middleware.ts
└── app
└── [locale]
├── layout.tsx (6)
└── page.tsx (7)
├── layout.tsx
└── page.tsx
```

In case you're migrating an existing app to `next-intl`, you'll typically move your existing pages into the `[locale]` folder as part of the setup.
Expand All @@ -59,21 +60,20 @@ The simplest option is to add JSON files in your local project folder:
}
```

### `next.config.mjs` [#next-config]
### `next.config.ts` [#next-config]

Now, set up the plugin which creates an alias to provide a request-specific i18n configuration to Server Components—more on this in the following steps.

<Tabs items={['next.config.mjs', 'next.config.js']}>
<Tabs items={['next.config.ts', 'next.config.js']}>
<Tabs.Tab>

```js filename="next.config.mjs"
```js filename="next.config.ts"
import {NextConfig} from 'next';
import createNextIntlPlugin from 'next-intl/plugin';

const withNextIntl = createNextIntlPlugin();

/** @type {import('next').NextConfig} */
const nextConfig = {};
const nextConfig: NextConfig = {};

const withNextIntl = createNextIntlPlugin();
export default withNextIntl(nextConfig);
```

Expand Down Expand Up @@ -116,18 +116,25 @@ export const routing = defineRouting({
// Used when no locale matches
defaultLocale: 'en'
});
```

Depending on your requirements, you may wish to customize your routing configuration later—but let's finish with the setup first.

### `src/i18n/navigation.ts` [#i18n-navigation]

Once we have our routing configuration in place, we can use it to set up the navigation APIs.

```ts filename="src/i18n/navigation.ts"
import {createNavigation} from 'next-intl/navigation';
import {routing} from './routing';

// Lightweight wrappers around Next.js' navigation APIs
// that will consider the routing configuration
export const {Link, redirect, usePathname, useRouter, getPathname} =
createNavigation(routing);
```

Depending on your requirements, you may wish to customize your routing configuration later—but let's finish with the setup first.

### `src/middleware.ts` [#middleware]

Once we have our routing configuration in place, we can use it to set up the middleware.
Additionally, we can use our routing configuration to set up the middleware.

```tsx filename="src/middleware.ts"
import createMiddleware from 'next-intl/middleware';
Expand Down Expand Up @@ -172,7 +179,7 @@ This file is supported out-of-the-box as `./i18n/request.ts` both in the `src` f

If you prefer to move this file somewhere else, you can optionally provide a path to the plugin:

```js filename="next.config.mjs"
```js filename="next.config.ts"
const withNextIntl = createNextIntlPlugin(
// Specify a custom path here
'./somewhere/else/request.ts'
Expand All @@ -193,12 +200,13 @@ import {routing} from '@/i18n/routing';

export default async function LocaleLayout({
children,
params: {locale}
params
}: {
children: React.ReactNode;
params: {locale: string};
params: Promise<{locale: string}>;
}) {
// Ensure that the incoming `locale` is valid
const {locale} = await params;
if (!routing.locales.includes(locale as any)) {
notFound();
}
Expand Down Expand Up @@ -300,7 +308,9 @@ import {setRequestLocale} from 'next-intl/server';
import {notFound} from 'next/navigation';
import {routing} from '@/i18n/routing';

export default async function LocaleLayout({children, params: {locale}}) {
export default async function LocaleLayout({children, params}) {
const {locale} = await params;

// Ensure that the incoming `locale` is valid
if (!routing.locales.includes(locale as any)) {
notFound();
Expand All @@ -318,7 +328,9 @@ export default async function LocaleLayout({children, params: {locale}}) {
```tsx filename="app/[locale]/page.tsx"
import {setRequestLocale} from 'next-intl/server';

export default function IndexPage({params: {locale}}) {
export default function IndexPage({params}) {
const {locale} = use(params);

// Enable static rendering
setRequestLocale(locale);

Expand Down Expand Up @@ -369,7 +381,8 @@ To achieve this, you can forward the `locale` that you receive from Next.js via
```tsx filename="page.tsx"
import {getTranslations} from 'next-intl/server';

export async function generateMetadata({params: {locale}}) {
export async function generateMetadata({params}) {
const {locale} = await params;
const t = await getTranslations({locale, namespace: 'Metadata'});

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ Now, we're going to create the following file structure:

```
├── messages
│ ├── en.json (1)
│ ├── en.json
│ └── ...
├── next.config.mjs (2)
├── next.config.ts
└── src
├── i18n
│ └── request.ts (3)
│ └── request.ts
└── app
├── layout.tsx (4)
└── page.tsx (5)
├── layout.tsx
└── page.tsx
```

**Let's set up the files:**
Expand All @@ -53,21 +53,20 @@ The simplest option is to add JSON files in your local project folder:
}
```

### `next.config.mjs` [#next-config]
### `next.config.ts` [#next-config]

Now, set up the plugin which creates an alias to provide a request-specific i18n configuration to Server Components (specified in the next step).

<Tabs items={['next.config.mjs', 'next.config.js']}>
<Tabs items={['next.config.ts', 'next.config.js']}>
<Tabs.Tab>

```js filename="next.config.mjs"
```js filename="next.config.ts"
import {NextConfig} from 'next';
import createNextIntlPlugin from 'next-intl/plugin';

const withNextIntl = createNextIntlPlugin();

/** @type {import('next').NextConfig} */
const nextConfig = {};
const nextConfig: NextConfig = {};

const withNextIntl = createNextIntlPlugin();
export default withNextIntl(nextConfig);
```

Expand Down Expand Up @@ -114,7 +113,7 @@ This file is supported out-of-the-box as `./i18n/request.ts` both in the `src` f

If you prefer to move this file somewhere else, you can optionally provide a path to the plugin:

```js filename="next.config.mjs"
```js filename="next.config.ts"
const withNextIntl = createNextIntlPlugin(
// Specify a custom path here
'./somewhere/else/request.ts'
Expand Down
7 changes: 4 additions & 3 deletions docs/src/pages/docs/routing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -300,14 +300,15 @@ import {notFound} from 'next';
import {fetchContent} from './cms';

type Props = {
params: {
params: Promise<{
locale: string;
slug: Array<string>;
};
}>;
};

export default async function CatchAllPage({params}: Props) {
const content = await fetchContent(params.locale, params.slug);
const {locale, slug} = await params;
const content = await fetchContent(locale, slug);
if (!content) notFound();

// ...
Expand Down
Loading
Loading