Usage in Server Components (preview)
Next.js 13 introduces support for React Server Components in the app
directory. next-intl
is adopting the new capabilities and is currently offering a preview to early adopters, who are already building apps with the app
directory.
The app
directory is currently in beta, patterns are still emerging and APIs
may change. Please use this at your own risk, knowing that you might have
to face a migration effort when the app
directory becomes stable.
next-intl
tries to stay up to date with the latest developments on the
Next.js side, but during this period there can be unexpected issues.
Current preview version
npm install next-intl@2.11.0-alpha.4
This preview version was tested with next@13.0.6
.
Getting started
If you haven't done so already, create a Next.js 13 app that uses the app
directory. The goal is to prefix all routes with the locale
, so we can retrieve it as a dynamic segment and use it to configure next-intl
.
Start by creating the following file structure:
├── i18n.tsx (1)
├── tsconfig.json (2)
├── middleware.tsx (3)
├── messages (4)
│ ├── en.json
│ └── ...
└── app
├── [locale]
│ ├── layout.tsx (5)
│ └── page.tsx (6)
└── ...
Now, set up these files as follows:
- Define your configuration in
i18n.tsx
:
import {NextIntlConfig} from 'next-intl';
const config: NextIntlConfig = {
locales: ['en', 'de'],
defaultLocale: 'en',
async getMessages({locale}) {
return (await import(`../messages/${locale}.json`)).default;
}
};
export default config;
- Link to your configuration in
tsconfig.json
:
{
"compilerOptions": {
"paths": {
"next-intl/config": ["./i18n"]
},
...
}
}
- Create a middleware that handles redirects in
middleware.tsx
:
import {createIntlMiddleware} from 'next-intl/server';
// This middleware intercepts requests to `/` and will redirect
// to one of the configured locales instead (e.g. `/en`). A cookie
// is set in the background, so if the user switches to a new
// language, this language will take precedence from now on.
export default createIntlMiddleware();
- Set up messages for a language, e.g. in
messages/en.json
:
{
"Index": {
"title": "Hello world!"
}
}
- Pass your received locale to
NextIntlServerProvider
inapp/[locale]/layout.tsx
:
import {NextIntlServerProvider} from 'next-intl/server';
export default async function LocaleLayout({children, params: {locale}}) {
return (
<NextIntlServerProvider locale={locale}>{children}</NextIntlServerProvider>
);
}
- Use translations in your page component in
app/[locale]/page.tsx
or anywhere else!
import {useTranslations} from 'next-intl';
export default function Index() {
const t = useTranslations('Index');
return <h1>{t('title')}</h1>;
}
That's all it takes! Now you can internationalize your apps without adding i18n features to your client bundle.
If you've encountered an issue, you can explore the code for a working example (demo).
If you're in a transitioning phase, either from the pages
directory to the app
directory, or from Client Components the the Server Components preview, you can apply NextIntlClientProvider
additionally.
Switching to Client Components
If you need to use translations in Client Components, the best approach is to pass the generated labels as props.
// app/[locale]/page.tsx
import {useTranslations} from 'next-intl';
import Counter from './Counter';
export default function Index() {
const t = useTranslations('Index');
return <Counter title={t('counterTitle')} />;
}
// app/[locale]/Counter.tsx
'use client';
import {useState} from 'react';
function Counter({title}) {
const [count, setCount] = useState(0);
function onIncrement() {
setCount(count + 1);
}
return (
<p>
{title}: {count} <button onClick={onIncrement}>+</button>
</p>
);
}
This way your messages never leave the server and the client only needs to load the code that is necessary for initializing your interactive components.
If you absolutely need to use functionality from next-intl
on the client side, you can wrap the respective components with NextIntlClientProvider
(example code). Note however that this will increase your client bundle size.
Providing feedback
If you have feedback about using next-intl
in the app
directory, feel free to leave feedback in the PR which implements the React Server Components support.