You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/pages/docs/environments/server-client-components.mdx
+23-15Lines changed: 23 additions & 15 deletions
Original file line number
Diff line number
Diff line change
@@ -23,7 +23,7 @@ Moving internationalization to the server side unlocks new levels of performance
23
23
24
24
**Benefits of server-side internationalization:**
25
25
26
-
1. Your messages never leave the server and don't need to be serialized for the client side
26
+
1. Your messages never leave the server and don't need to be passed to the client side
27
27
2. Library code for internationalization doesn't need to be loaded on the client side
28
28
3. No need to split your messages, e.g. based on routes or components
29
29
4. No runtime cost on the client side
@@ -123,7 +123,22 @@ In regard to performance, async functions and hooks can be used very much interc
123
123
124
124
## Using internationalization in Client Components
125
125
126
-
Depending on your situation, you may need to handle internationalization in Client Components as well. There are several options for using translations or other functionality from `next-intl` in Client Components, listed here in order of recommendation.
126
+
Depending on your situation, you may need to handle internationalization in Client Components as well. While providing all messages to the client side is typically the easiest way to [get started](/docs/getting-started/app-router#layout) and a reasonable approach for many apps, you can be more selective about which messages are passed to the client side if you're interested in optimizing the performance of your app.
127
+
128
+
<Detailsid="client-messages-performance">
129
+
<summary>How does loading messages on the client side relate to performance?</summary>
130
+
131
+
Depending on the requirements for your app, you might want to monitor your [Core Web Vitals](https://web.dev/articles/vitals) to ensure your app meets your performance goals.
132
+
133
+
If you pass messages to `NextIntlClientProvider`, Next.js will emit them during the streaming render to the markup of the page so that they can be used by Client Components. This can contribute to the [total blocking time](https://web.dev/articles/tbt), which in turn can relate to the [interaction to next paint](https://web.dev/articles/inp) metric. If you're seeking to improve these metrics in your app, you can be more selective about which messages are passed to the client side.
134
+
135
+
However, as the general rule for optimization goes: Always measure before you optimize. If your app already performs well, there's no need for optimization.
136
+
137
+
Note that an automatic, compiler-driven approach for automatically splitting messages is being evaluated in [`next-intl#1`](https://github.com/amannn/next-intl/issues/1).
138
+
139
+
</Details>
140
+
141
+
There are several options for using translations from `next-intl` in Client Components, listed here in order of enabling the best performance:
127
142
128
143
### Option 1: Passing translations to Client Components
129
144
@@ -221,15 +236,15 @@ To keep internationalization on the server side, it can be helpful to structure
221
236
```tsx filename="app/register/page.tsx"
222
237
import {useTranslations} from'next-intl';
223
238
224
-
// A Client Component, so that it can use `useFormState` to
225
-
// potentially display errors received after submission.
239
+
// A Client Component, so that `useFormState` can be used
240
+
//to potentially display errors received after submission.
226
241
importRegisterFormfrom'./RegisterForm';
227
242
228
-
// A Client Component, so that it can use `useFormStatus`
243
+
// A Client Component, so that `useFormStatus` can be used
229
244
// to disable the input field during submission.
230
245
importFormFieldfrom'./FormField';
231
246
232
-
// A Client Component, so that it can use `useFormStatus`
247
+
// A Client Component, so that `useFormStatus` can be used
233
248
// to disable the submit button during submission.
234
249
importFormSubmitButtonfrom'./FormSubmitButton';
235
250
@@ -310,14 +325,12 @@ export default function Counter() {
310
325
}
311
326
```
312
327
313
-
In case you prefer to make all messages available to the client side, you can [configure `NextIntlClientProvider` in the root layout](#option-4-providing-all-messages) instead.
314
-
315
328
<Detailsid="messages-client-namespaces">
316
329
<summary>How can I know the messages I need to provide to the client side?</summary>
317
330
318
331
Currently, the messages you select for being passed to the client side need to be picked based on knowledge about the implementation of the wrapped components.
319
332
320
-
An automatic, compiler-driven approach is being evaluated in [`next-intl#2`](https://github.com/amannn/next-intl/issues/1).
333
+
An automatic, compiler-driven approach is being evaluated in [`next-intl#1`](https://github.com/amannn/next-intl/issues/1).
Note that this is a tradeoff in regard to performance (see the bullet points
352
-
at the top of this page).
353
-
</Callout>
354
-
355
363
## Troubleshooting
356
364
357
365
### "Failed to call `useTranslations` because the context from `NextIntlClientProvider` was not found." [#missing-context]
@@ -404,4 +412,4 @@ export default function MyCustomNextIntlClientProvider({
404
412
405
413
By doing this, your custom provider will already be part of the client-side bundle and can therefore define and pass functions as props.
406
414
407
-
**Important:** Be sure to pass explicit `locale`, `timeZone` and `now` props to `NextIntlClientProvider` in this case, since the props aren't automatically inherited from a Server Component when you import `NextIntlClientProvider` from a Client Component.
415
+
**Important:** Be sure to pass explicit `locale`, `formats`, `timeZone` and `now` props to `NextIntlClientProvider` in this case, since the props aren't automatically inherited from a Server Component when you import `NextIntlClientProvider` from a Client Component.
Copy file name to clipboardExpand all lines: docs/pages/docs/getting-started/app-router.mdx
+16-14Lines changed: 16 additions & 14 deletions
Original file line number
Diff line number
Diff line change
@@ -5,8 +5,6 @@ import Details from 'components/Details';
5
5
6
6
# Next.js App Router Internationalization (i18n)
7
7
8
-
The Next.js App Router introduces support for [React Server Components](https://nextjs.org/docs/app/building-your-application/rendering/server-components) and unlocks [many benefits](/docs/environments/server-client-components) when handling internationalization on the server side.
9
-
10
8
## Getting started
11
9
12
10
If you haven't done so already, [create a Next.js app](https://nextjs.org/docs/getting-started/installation) that uses the App Router.
@@ -56,8 +54,6 @@ Now, set up the plugin which creates an alias to provide your i18n configuration
`next-intl` creates a configuration once per request. Here you can provide messages and other options depending on the locale of the user.
87
+
`next-intl` creates a request-scoped configuration object that can be used to provide messages and other options depending on the locale of the user for usage in Server Components.
94
88
95
89
```tsx filename="src/i18n.ts"
96
90
import {notFound} from'next/navigation';
@@ -148,24 +142,36 @@ export const config = {
148
142
149
143
### `app/[locale]/layout.tsx`[#layout]
150
144
151
-
The `locale` that was matched by the middleware is available via the `locale` param and can be used to configure the document language.
145
+
The `locale` that was matched by the middleware is available via the `locale` param and can be used to configure the document language. Additionally, we can use this place to pass configuration from `i18n.ts` to Client Components via `NextIntlClientProvider`.
152
146
153
147
```tsx filename="app/[locale]/layout.tsx"
154
-
exportdefaultfunction LocaleLayout({
148
+
import {getMessages} from'next-intl/server';
149
+
150
+
exportdefaultasyncfunction LocaleLayout({
155
151
children,
156
152
params: {locale}
157
153
}: {
158
154
children:React.ReactNode;
159
155
params: {locale:string};
160
156
}) {
157
+
// Providing all messages to the client
158
+
// side is the easiest way to get started
159
+
const messages =awaitgetMessages();
160
+
161
161
return (
162
162
<htmllang={locale}>
163
-
<body>{children}</body>
163
+
<body>
164
+
<NextIntlClientProvidermessages={messages}>
165
+
{children}
166
+
</NextIntlClientProvider>
167
+
</body>
164
168
</html>
165
169
);
166
170
}
167
171
```
168
172
173
+
Note that `NextIntlClientProvider` automatically inherits most configuration from `i18n.ts` here.
174
+
169
175
### `app/[locale]/page.tsx`[#page]
170
176
171
177
Use translations in your page components or anywhere else!
@@ -191,10 +197,6 @@ In case you ran into an issue, have a look at [the App Router example](https://n
191
197
192
198
<ulclassName="ml-4 list-disc">
193
199
<li>[Usage guide](/docs/usage): Format messages, dates and times</li>
194
-
<li>
195
-
[Environments](/docs/environments): Explore usage in Server & Client
196
-
Components and the Metadata API
197
-
</li>
198
200
<li>
199
201
[Routing](/docs/routing): Integrate i18n routing with `<Link />` & friends
`NextIntlClientProvider` inherits the props `locale`, `now` and `timeZone` when the component is rendered from a Server Component. Other configuration like `messages` and `formats` can be provided as necessary.
60
+
These props are inherited if you're rendering `NextIntlClientProvider` from a Server Component:
61
+
62
+
1.`locale`
63
+
2.`now`
64
+
3.`timeZone`
65
+
66
+
In contrast, these props can be provided as necessary:
60
67
61
-
<Callout>
62
-
Before passing all messages to the client side, learn more about the options
1.`messages` (see [Internationalization in Client Components](/docs/environments/server-client-components#using-internationalization-in-client-components))
0 commit comments