@intlayer/docs 6.1.4 → 6.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/blog/ar/next-i18next_vs_next-intl_vs_intlayer.md +1135 -75
  2. package/blog/ar/nextjs-multilingual-seo-comparison.md +364 -0
  3. package/blog/de/next-i18next_vs_next-intl_vs_intlayer.md +1139 -72
  4. package/blog/de/nextjs-multilingual-seo-comparison.md +362 -0
  5. package/blog/en/next-i18next_vs_next-intl_vs_intlayer.md +224 -240
  6. package/blog/en/nextjs-multilingual-seo-comparison.md +360 -0
  7. package/blog/en-GB/next-i18next_vs_next-intl_vs_intlayer.md +1134 -37
  8. package/blog/en-GB/nextjs-multilingual-seo-comparison.md +360 -0
  9. package/blog/es/next-i18next_vs_next-intl_vs_intlayer.md +1122 -64
  10. package/blog/es/nextjs-multilingual-seo-comparison.md +363 -0
  11. package/blog/fr/next-i18next_vs_next-intl_vs_intlayer.md +1132 -75
  12. package/blog/fr/nextjs-multilingual-seo-comparison.md +362 -0
  13. package/blog/hi/nextjs-multilingual-seo-comparison.md +363 -0
  14. package/blog/it/next-i18next_vs_next-intl_vs_intlayer.md +1120 -55
  15. package/blog/it/nextjs-multilingual-seo-comparison.md +363 -0
  16. package/blog/ja/next-i18next_vs_next-intl_vs_intlayer.md +1140 -76
  17. package/blog/ja/nextjs-multilingual-seo-comparison.md +362 -0
  18. package/blog/ko/next-i18next_vs_next-intl_vs_intlayer.md +1129 -73
  19. package/blog/ko/nextjs-multilingual-seo-comparison.md +362 -0
  20. package/blog/pt/next-i18next_vs_next-intl_vs_intlayer.md +1133 -76
  21. package/blog/pt/nextjs-multilingual-seo-comparison.md +362 -0
  22. package/blog/ru/next-i18next_vs_next-intl_vs_intlayer.md +1142 -74
  23. package/blog/ru/nextjs-multilingual-seo-comparison.md +370 -0
  24. package/blog/tr/nextjs-multilingual-seo-comparison.md +362 -0
  25. package/blog/zh/next-i18next_vs_next-intl_vs_intlayer.md +1142 -75
  26. package/blog/zh/nextjs-multilingual-seo-comparison.md +394 -0
  27. package/dist/cjs/generated/blog.entry.cjs +16 -0
  28. package/dist/cjs/generated/blog.entry.cjs.map +1 -1
  29. package/dist/esm/generated/blog.entry.mjs +16 -0
  30. package/dist/esm/generated/blog.entry.mjs.map +1 -1
  31. package/dist/types/generated/blog.entry.d.ts +1 -0
  32. package/dist/types/generated/blog.entry.d.ts.map +1 -1
  33. package/docs/en/interest_of_intlayer.md +2 -2
  34. package/package.json +10 -10
  35. package/src/generated/blog.entry.ts +16 -0
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  createdAt: 2025-08-23
3
- updatedAt: 2025-09-25
3
+ updatedAt: 2025-09-29
4
4
  title: next-i18next vs next-intl vs Intlayer
5
5
  description: Compare next-i18next with next-intl and Intlayer for the internationalization (i18n) of a Next.js app
6
6
  keywords:
@@ -47,12 +47,12 @@ We focus on **Next.js 13+ App Router** (with **React Server Components**) and ev
47
47
 
48
48
  ---
49
49
 
50
- | Library | GitHub Stars | Total Commits | Last Commit | First Version | NPM Version | NPM Downloads |
51
- | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | ---------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
52
- | `aymericzip/intlayer` | [![GitHub Repo stars](https://img.shields.io/github/stars/aymericzip/intlayer?style=flat&label=%E2%AD%90%20stars)](https://github.com/aymericzip/intlayer/stargazers) | [![GitHub commit activity](https://img.shields.io/github/commit-activity/t/aymericzip/intlayer?style=flat&label=commits)](https://github.com/aymericzip/intlayer/commits) | [![Last Commit](https://img.shields.io/github/last-commit/aymericzip/intlayer?style=flat)](https://github.com/aymericzip/intlayer/commits) | April 2024 | [![npm](https://img.shields.io/npm/v/intlayer?style=flat)](https://www.npmjs.com/package/intlayer) | [![npm downloads](https://img.shields.io/npm/dm/intlayer?style=flat)](https://www.npmjs.com/package/intlayer) |
53
- | `amannn/next-intl` | [![GitHub Repo stars](https://img.shields.io/github/stars/amannn/next-intl?style=flat&label=%E2%AD%90%20stars)](https://github.com/amannn/next-intl/stargazers) | [![GitHub commit activity](https://img.shields.io/github/commit-activity/t/amannn/next-intl?style=flat&label=commits)](https://github.com/amannn/next-intl/commits) | [![Last Commit](https://img.shields.io/github/last-commit/amannn/next-intl?style=flat)](https://github.com/amannn/next-intl/commits) | Nov 2020 | [![npm](https://img.shields.io/npm/v/next-intl?style=flat)](https://www.npmjs.com/package/next-intl) | [![npm downloads](https://img.shields.io/npm/dm/next-intl?style=flat)](https://www.npmjs.com/package/next-intl) |
54
- | `i18next/i18next` | [![GitHub Repo stars](https://img.shields.io/github/stars/i18next/i18next?style=flat&label=%E2%AD%90%20stars)](https://github.com/i18next/i18next/stargazers) | [![GitHub commit activity](https://img.shields.io/github/commit-activity/t/i18next/i18next?style=flat&label=commits)](https://github.com/i18next/i18next/commits) | [![Last Commit](https://img.shields.io/github/last-commit/i18next/i18next?style=flat)](https://github.com/i18next/i18next/commits) | Jan 2012 | [![npm](https://img.shields.io/npm/v/i18next?style=flat)](https://www.npmjs.com/package/i18next) | [![npm downloads](https://img.shields.io/npm/dm/i18next?style=flat)](https://www.npmjs.com/package/i18next) |
55
- | `i18next/next-i18next` | [![GitHub Repo stars](https://img.shields.io/github/stars/i18next/next-i18next?style=flat&label=%E2%AD%90%20stars)](https://github.com/i18next/next-i18next/stargazers) | [![GitHub commit activity](https://img.shields.io/github/commit-activity/t/i18next/next-i18next?style=flat&label=commits)](https://github.com/i18next/next-i18next/commits) | [![Last Commit](https://img.shields.io/github/last-commit/i18next/next-i18next?style=flat)](https://github.com/i18next/next-i18next/commits) | Nov 2018 | [![npm](https://img.shields.io/npm/v/next-i18next?style=flat)](https://www.npmjs.com/package/next-i18next) | [![npm downloads](https://img.shields.io/npm/dm/next-i18next?style=flat)](https://www.npmjs.com/package/next-i18next) |
50
+ | Library | GitHub Stars | Total Commits | Last Commit | First Version | NPM Version | NPM Downloads |
51
+ | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
52
+ | `aymericzip/intlayer` | [![GitHub Repo stars](https://img.shields.io/github/stars/aymericzip/intlayer?style=for-the-badge&label=%E2%AD%90%20stars)](https://github.com/aymericzip/intlayer/stargazers) | [![GitHub commit activity](https://img.shields.io/github/commit-activity/t/aymericzip/intlayer?style=for-the-badge&label=commits)](https://github.com/aymericzip/intlayer/commits) | [![Last Commit](https://img.shields.io/github/last-commit/aymericzip/intlayer?style=for-the-badge)](https://github.com/aymericzip/intlayer/commits) | April 2024 | [![npm](https://img.shields.io/npm/v/intlayer?style=for-the-badge)](https://www.npmjs.com/package/intlayer) | [![npm downloads](https://img.shields.io/npm/dm/intlayer?style=for-the-badge)](https://www.npmjs.com/package/intlayer) |
53
+ | `amannn/next-intl` | [![GitHub Repo stars](https://img.shields.io/github/stars/amannn/next-intl?style=for-the-badge&label=%E2%AD%90%20stars)](https://github.com/amannn/next-intl/stargazers) | [![GitHub commit activity](https://img.shields.io/github/commit-activity/t/amannn/next-intl?style=for-the-badge&label=commits)](https://github.com/amannn/next-intl/commits) | [![Last Commit](https://img.shields.io/github/last-commit/amannn/next-intl?style=for-the-badge)](https://github.com/amannn/next-intl/commits) | Nov 2020 | [![npm](https://img.shields.io/npm/v/next-intl?style=for-the-badge)](https://www.npmjs.com/package/next-intl) | [![npm downloads](https://img.shields.io/npm/dm/next-intl?style=for-the-badge)](https://www.npmjs.com/package/next-intl) |
54
+ | `i18next/i18next` | [![GitHub Repo stars](https://img.shields.io/github/stars/i18next/i18next?style=for-the-badge&label=%E2%AD%90%20stars)](https://github.com/i18next/i18next/stargazers) | [![GitHub commit activity](https://img.shields.io/github/commit-activity/t/i18next/i18next?style=for-the-badge&label=commits)](https://github.com/i18next/i18next/commits) | [![Last Commit](https://img.shields.io/github/last-commit/i18next/i18next?style=for-the-badge)](https://github.com/i18next/i18next/commits) | Jan 2012 | [![npm](https://img.shields.io/npm/v/i18next?style=for-the-badge)](https://www.npmjs.com/package/i18next) | [![npm downloads](https://img.shields.io/npm/dm/i18next?style=for-the-badge)](https://www.npmjs.com/package/i18next) |
55
+ | `i18next/next-i18next` | [![GitHub Repo stars](https://img.shields.io/github/stars/i18next/next-i18next?style=for-the-badge&label=%E2%AD%90%20stars)](https://github.com/i18next/next-i18next/stargazers) | [![GitHub commit activity](https://img.shields.io/github/commit-activity/t/i18next/next-i18next?style=for-the-badge&label=commits)](https://github.com/i18next/next-i18next/commits) | [![Last Commit](https://img.shields.io/github/last-commit/i18next/next-i18next?style=for-the-badge)](https://github.com/i18next/next-i18next/commits) | Nov 2018 | [![npm](https://img.shields.io/npm/v/next-i18next?style=for-the-badge)](https://www.npmjs.com/package/next-i18next) | [![npm downloads](https://img.shields.io/npm/dm/next-i18next?style=for-the-badge)](https://www.npmjs.com/package/next-i18next) |
56
56
 
57
57
  > Badges update automatically. Snapshots will vary over time.
58
58
 
@@ -140,6 +140,7 @@ Two important issues:
140
140
  > If I'm on the `/about` page, I don't want to load the content of the `/home` page
141
141
 
142
142
  - **Splitting by locale:**
143
+
143
144
  > If I'm on the `/fr/about` page, I don't want to load the content of the `/en/about` page
144
145
 
145
146
  Again, all three solutions are aware of these issues and allow managing these optimizations. The difference between the three solutions is the DX (Developer Experience).
@@ -170,6 +171,173 @@ Here an example of the impact of bundle size optimization using `intlayer` in a
170
171
 
171
172
  ---
172
173
 
174
+ ## TypeScript & safety
175
+
176
+ <Columns>
177
+ <Column>
178
+
179
+ **next-intl**
180
+
181
+ - Solid TypeScript support, but **keys aren’t strictly typed by default**; you’ll maintain safety patterns manually.
182
+
183
+ </Column>
184
+ <Column>
185
+
186
+ **next-i18next**
187
+
188
+ - Base typings for hooks; **strict key typing requires extra tooling/config**.
189
+
190
+ </Column>
191
+ <Column>
192
+
193
+ **intlayer**
194
+
195
+ - **Generates strict types** from your content. **IDE autocompletion** and **compile-time errors** catch typos and missing keys before deploy.
196
+
197
+ </Column>
198
+ </Columns>
199
+
200
+ **Why it matters:** Strong typing shifts failures **left** (CI/build) instead of **right** (runtime).
201
+
202
+ ---
203
+
204
+ ## Missing translation handling
205
+
206
+ <Columns>
207
+ <Column>
208
+
209
+ **next-intl**
210
+
211
+ - Relies on **runtime fallbacks** (e.g., show the key or default locale). Build doesn’t fail.
212
+
213
+ </Column>
214
+ <Column>
215
+
216
+ **next-i18next**
217
+
218
+ - Relies on **runtime fallbacks** (e.g., show the key or default locale). Build doesn’t fail.
219
+
220
+ </Column>
221
+ <Column>
222
+
223
+ **intlayer**
224
+
225
+ - **Build-time detection** with **warnings/errors** for missing locales or keys.
226
+
227
+ </Column>
228
+ </Columns>
229
+
230
+ **Why it matters:** Catching gaps during build prevents “mystery strings” in production and aligns with strict release gates.
231
+
232
+ ---
233
+
234
+ ## Routing, middleware & URL strategy
235
+
236
+ <Columns>
237
+ <Column>
238
+
239
+ **next-intl**
240
+
241
+ - Works with **Next.js localized routing** on the App Router.
242
+
243
+ </Column>
244
+ <Column>
245
+
246
+ **next-i18next**
247
+
248
+ - Works with **Next.js localized routing** on the App Router.
249
+
250
+ </Column>
251
+ <Column>
252
+
253
+ **intlayer**
254
+
255
+ - All of the above, plus **i18n middleware** (locale detection via headers/cookies) and **helpers** to generate localized URLs and `<link rel="alternate" hreflang="…">` tags.
256
+
257
+ </Column>
258
+ </Columns>
259
+
260
+ **Why it matters:** Fewer custom glue layers; **consistent UX** and **clean SEO** across locales.
261
+
262
+ ---
263
+
264
+ ## Server Components (RSC) alignment
265
+
266
+ <Columns>
267
+ <Column>
268
+
269
+ **next-intl**
270
+
271
+ - Supports Next.js 13+. Often requires passing t-functions/formatters through component trees in hybrid setups.
272
+
273
+ </Column>
274
+ <Column>
275
+
276
+ **next-i18next**
277
+
278
+ - Supports Next.js 13+. Similar constraints with passing translation utilities across boundaries.
279
+
280
+ </Column>
281
+ <Column>
282
+
283
+ **intlayer**
284
+
285
+ - Supports Next.js 13+ and smooths the **server/client boundary** with a consistent API and RSC-oriented providers, avoiding shuttling formatters or t-functions.
286
+
287
+ </Column>
288
+ </Columns>
289
+
290
+ **Why it matters:** Cleaner mental model and fewer edge cases in hybrid trees.
291
+
292
+ ---
293
+
294
+ ## DX, tooling & maintenance
295
+
296
+ <Columns>
297
+ <Column>
298
+
299
+ **next-intl**
300
+
301
+ - Commonly paired with external localization platforms and editorial workflows.
302
+
303
+ </Column>
304
+ <Column>
305
+
306
+ **next-i18next**
307
+
308
+ - Commonly paired with external localization platforms and editorial workflows.
309
+
310
+ </Column>
311
+ <Column>
312
+
313
+ **intlayer**
314
+
315
+ - Ships a **free Visual Editor** and **optional CMS** (Git-friendly or externalized), plus a **VSCode extension** and **AI-assisted translations** using your own provider keys.
316
+
317
+ </Column>
318
+ </Columns>
319
+
320
+ **Why it matters:** Lowers ops cost and shortens the loop between developers and content authors.
321
+
322
+ ## Integration with localization platforms (TMS)
323
+
324
+ Large organizations often rely on Translation Management Systems (TMS) like **Crowdin**, **Phrase**, **Lokalise**, **Localizely**, or **Localazy**.
325
+
326
+ - **Why companies care**
327
+ - **Collaboration & roles**: Multiple actors are involved: developers, product managers, translators, reviewers, marketing teams.
328
+ - **Scale & efficiency**: continuous localization, in‑context review.
329
+
330
+ - **next-intl / next-i18next**
331
+ - Typically use **centralized JSON catalogs**, so export/import with TMS is straightforward.
332
+ - Mature ecosystems and examples/integrations for the platforms above.
333
+
334
+ - **Intlayer**
335
+ - Encourages **decentralized, per-component dictionaries** and supports **TypeScript/TSX/JS/JSON/MD** content.
336
+ - This improves modularity in code, but can make plug‑and‑play TMS integration harder when a tool expects centralized, flat JSON files.
337
+ - Intlayer provides alternatives: **AI‑assisted translations** (using your own provider keys), a **Visual Editor/CMS**, and **CLI/CI** workflows to catch and prefill gaps.
338
+
339
+ > Note: `next-intl` and `i18next` also accepts TypeScript catalogs. If your team stores messages in `.ts` files or decentralizes them by feature, you can face similar TMS friction. However, many `next-intl` setups remain centralized in a `locales/` folder, which is a bit easier to refactor to JSON for TMS.
340
+
173
341
  ## Developer Experience
174
342
 
175
343
  This part makes a deep comparison between the three solutions. Rather than considering simple cases, as described in the 'getting started' documentation for each solution, we will consider a real use case, more similar to a real project.
@@ -206,7 +374,7 @@ The app structure is important to ensure good maintainability for your codebase.
206
374
  ```
207
375
 
208
376
  </TabItem>
209
- <TabItem label="next-intl" value="next-intl">
377
+ <TabItem label="next-intl" value="next-intl">
210
378
 
211
379
  ```bash
212
380
  .
@@ -253,54 +421,8 @@ The app structure is important to ensure good maintainability for your codebase.
253
421
 
254
422
  #### Comparison
255
423
 
256
- ##### Configuration
257
-
258
- Intlayer uses a centralized configuration file to set up your locale, middleware, build, etc.
259
-
260
- ##### Content declaration
261
-
262
- The centralized type of architecture slows down the development process and makes the codebase more complex to maintain for several reasons:
263
-
264
- 1. **For any new component created, you should:**
265
- - Create the new resource/namespace in the `locales` folder
266
- - Remember to import the new namespace in your page
267
- - Translate your content (often done manually by copy/paste from AI providers)
268
-
269
- 2. **For any change made on your components, you should:**
270
- - Search for the related resource/namespace (far from the component)
271
- - Translate your content
272
- - Ensure your content is up to date for any locale
273
- - Verify your namespace doesn't include unused keys/values
274
- - Ensure the structure of your JSON files is the same for all locales
275
-
276
- On professional projects using these solutions, localization platforms are often used to help manage the translation of your content. However, this can quickly become costly for large projects.
277
-
278
- To solve this problem, Intlayer adopts an approach that scopes your content per-component and keeps your content close to your component, as we often do with CSS (`styled-components`), types, documentation (`storybook`), or unit tests (`jest`).
279
-
280
- This approach allows you to:
281
-
282
- 1. **Increase the speed of development**
283
- - `.content.{{ts|js|json}}` files can be created using a VSCode extension
284
- - Autocompletion AI tools in your IDE (such as GitHub Copilot) can help you declare your content, reducing copy/paste
285
-
286
- 2. **Clean your codebase**
287
- - Reduce the complexity
288
- - Increase the maintainability
289
-
290
- 3. **Duplicate your components and their related content more easily (Example: login/register components, etc.)**
291
- - By limiting the risk of impacting other components' content
292
- - By copy/pasting your content from one application to another without external dependencies
293
-
294
- 4. **Avoid polluting your codebase with unused keys/values for unused components**
295
- - If you don't use a component, Intlayer will not import its related content
296
- - If you delete a component, you'll more easily remember to remove its related content as it will be present in the same folder
297
-
298
- 5. **Reduce reasoning cost for AI agents to declare your multilingual content**
299
- - The AI agent won't have to scan your entire codebase to know where to implement your content
300
- - Translations can easily be done by autocompletion AI tools in your IDE (such as GitHub Copilot)
301
-
302
- 6. **Optimize loading performance**
303
- - If a component is lazy-loaded, its related content will be loaded at the same time
424
+ - **next-intl / next-i18next**: Centralized catalogs (JSON; namespaces/messages). Clear structure, integrates well with translation platforms, but can lead to more cross-file edits as apps grow.
425
+ - **Intlayer**: Per-component `.content.{ts|js|json}` dictionaries co-located with components. Easier component reuse and local reasoning; adds files and relies on build-time tooling.
304
426
 
305
427
  #### Setup and Loading Content
306
428
 
@@ -335,7 +457,7 @@ import { I18nextProvider, initReactI18next } from "react-i18next";
335
457
  import { createInstance } from "i18next";
336
458
  import { ClientComponent, ServerComponent } from "@components";
337
459
 
338
- export default function HomePage() {
460
+ export default function HomePage({ locale }: { locale: string }) {
339
461
  // Déclarez explicitement le namespace utilisé par ce composant
340
462
  const resources = await loadMessagesFor(locale); // your loader (JSON, etc.)
341
463
 
@@ -394,7 +516,7 @@ export default getRequestConfig(async ({ locale }) => {
394
516
 
395
517
  ```tsx fileName="src/app/[locale]/about/layout.tsx"
396
518
  import { NextIntlClientProvider } from "next-intl";
397
- import { getMessages } from "next-intl/server";
519
+ import { getMessages, unstable_setRequestLocale } from "next-intl/server";
398
520
  import pick from "lodash/pick";
399
521
 
400
522
  export default async function LocaleLayout({
@@ -405,9 +527,13 @@ export default async function LocaleLayout({
405
527
  params: { locale: string };
406
528
  }) {
407
529
  const { locale } = params;
408
- // Les messages sont chargés côté serveur via src/i18n/request.ts
409
- // (voir docs next-intl). Ici on ne pousse au client qu'un sous-ensemble
410
- // utile aux composants client (optimisation du payload).
530
+
531
+ // Set the active request locale for this server render (RSC)
532
+ unstable_setRequestLocale(locale);
533
+
534
+ // Messages are loaded server-side via src/i18n/request.ts
535
+ // (see next-intl docs). Here we only push a subset to the client
536
+ // that's needed for client components (payload optimization).
411
537
  const messages = await getMessages();
412
538
  const clientMessages = pick(messages, ["common", "about"]);
413
539
 
@@ -511,13 +637,13 @@ export default LandingPage;
511
637
 
512
638
  #### Comparison
513
639
 
514
- In comparison to other solutions, Intlayer uses plugins to optimize the import of content at build time.
640
+ All three support per-locale content loading and providers.
515
641
 
516
- This means that the client context can be stored in the root layout, to reuse only one instance of the provider for all pages.
642
+ - With **next-intl/next-i18next**, you typically load selected messages/namespaces per route and place providers where needed.
517
643
 
518
- In comparison, the other solutions require rebuilding a custom provider for each page.
644
+ - With **Intlayer**, adds build-time analysis to infer usage, which can reduce manual wiring and may allow a single root provider.
519
645
 
520
- Intlayer also provides a Provider for your server components. We'll see why later.
646
+ Choose between explicit control and automation based on team preference.
521
647
 
522
648
  ### Usage in a client component
523
649
 
@@ -554,7 +680,7 @@ Let's take an example of a client component rendering a counter.
554
680
  import React, { useMemo, useState } from "react";
555
681
  import { useTranslation } from "next-i18next";
556
682
 
557
- export default function ClientComponentExample() {
683
+ const ClientComponentExample = () => {
558
684
  const { t, i18n } = useTranslation("about");
559
685
  const [count, setCount] = useState(0);
560
686
 
@@ -572,7 +698,7 @@ export default function ClientComponentExample() {
572
698
  </button>
573
699
  </div>
574
700
  );
575
- }
701
+ };
576
702
  ```
577
703
 
578
704
  > Don't forget to add "about" namespace on the page serverSideTranslations
@@ -609,7 +735,7 @@ export default function ClientComponentExample() {
609
735
  import React, { useState } from "react";
610
736
  import { useTranslations, useFormatter } from "next-intl";
611
737
 
612
- export default function ClientComponentExample() {
738
+ const ClientComponentExample = () => {
613
739
  // Scope directly to the nested object
614
740
  const t = useTranslations("about.counter");
615
741
  const format = useFormatter();
@@ -626,7 +752,7 @@ export default function ClientComponentExample() {
626
752
  </button>
627
753
  </div>
628
754
  );
629
- }
755
+ };
630
756
  ```
631
757
 
632
758
  > Don't forget to add "about" message on the page client message
@@ -658,7 +784,7 @@ export default counterContent;
658
784
  import React, { useState } from "react";
659
785
  import { useNumber, useIntlayer } from "next-intlayer";
660
786
 
661
- export default function ClientComponentExample() {
787
+ const ClientComponentExample = () => {
662
788
  const [count, setCount] = useState(0);
663
789
  const { label, increment } = useIntlayer("counter"); // returns strings
664
790
  const { number } = useNumber();
@@ -671,7 +797,7 @@ export default function ClientComponentExample() {
671
797
  </button>
672
798
  </div>
673
799
  );
674
- }
800
+ };
675
801
  ```
676
802
 
677
803
  </TabItem>
@@ -702,62 +828,52 @@ We will take the case of a UI component. This component is a server component, a
702
828
  <TabItem label="next-i18next" value="next-i18next">
703
829
 
704
830
  ```tsx fileName="src/pages/about.tsx"
705
- import React from "react";
706
831
  import type { GetStaticProps } from "next";
707
832
  import { useTranslation } from "next-i18next";
708
- import { serverSideTranslations } from "next-i18next/serverSideTranslations";
709
833
 
710
834
  type ServerComponentProps = {
711
835
  count: number;
712
- t: (key: string) => string;
713
- format: (value: number) => string;
714
836
  };
715
837
 
716
- export default function ServerComponent({
717
- t,
718
- format,
719
- count,
720
- }: ServerComponentProps) {
838
+ const ServerComponent = ({ count }: ServerComponentProps) => {
839
+ const { t, i18n } = useTranslation("about");
840
+ const formatted = new Intl.NumberFormat(i18n.language).format(count);
841
+
721
842
  return (
722
843
  <div>
723
- <p>{format(count)}</p>
844
+ <p>{formatted}</p>
724
845
  <button aria-label={t("counter.label")}>{t("counter.increment")}</button>
725
846
  </div>
726
847
  );
727
- }
848
+ };
728
849
  ```
729
850
 
730
- > As the server component cannot be async, you need to pass the translations and formatter function as props.
731
- >
732
- > - `const { t, i18n } = useTranslation("about");`
733
- > - `const formatted = new Intl.NumberFormat(i18n.language).format(initialCount);`
734
-
735
851
  </TabItem>
736
852
  <TabItem label="next-intl" value="next-intl">
737
853
 
738
854
  ```tsx fileName="src/components/ServerComponent.tsx"
739
- import { getTranslations, getFormatter } from "next-intl/server";
740
-
741
- export default async function ServerComponent({
742
- t,
743
- format,
744
- count,
745
- }: {
746
- t: (key: string) => string;
747
- format: (value: number) => string;
855
+ type ServerComponentProps = {
748
856
  count: number;
749
- }) {
857
+ t: (key: string) => string;
858
+ };
859
+
860
+ const ServerComponent = ({ t, count }: ServerComponentProps) => {
861
+ const formatted = new Intl.NumberFormat(i18n.language).format(count);
862
+
750
863
  return (
751
864
  <div>
752
- <p>{format.number(count)}</p>
865
+ <p>{formatted}</p>
753
866
  <button aria-label={t("label")}>{t("increment")}</button>
754
867
  </div>
755
868
  );
756
- }
869
+ };
757
870
  ```
758
871
 
759
872
  > As the server component cannot be async, you need to pass the translations and formatter function as props.
760
873
  >
874
+ > In your page / layout:
875
+ >
876
+ > - `import { getTranslations, getFormatter } from "next-intl/server";`
761
877
  > - `const t = await getTranslations("about.counter");`
762
878
  > - `const format = await getFormatter();`
763
879
 
@@ -767,7 +883,11 @@ export default async function ServerComponent({
767
883
  ```tsx fileName="src/components/ServerComponent.tsx"
768
884
  import { useIntlayer, useNumber } from "next-intlayer/server";
769
885
 
770
- const ServerComponent = ({ count }: { count: number }) => {
886
+ type ServerComponentProps = {
887
+ count: number;
888
+ };
889
+
890
+ const ServerComponent = ({ count }: ServerComponentProps) => {
771
891
  const { label, increment } = useIntlayer("counter");
772
892
  const { number } = useNumber();
773
893
 
@@ -909,7 +1029,7 @@ export default function robots(): MetadataRoute.Robots {
909
1029
  ```tsx fileName="src/app/[locale]/about/layout.tsx"
910
1030
  import type { Metadata } from "next";
911
1031
  import { locales, defaultLocale } from "@/i18n";
912
- import { getTranslations, unstable_setRequestLocale } from "next-intl/server";
1032
+ import { getTranslations } from "next-intl/server";
913
1033
 
914
1034
  function localizedPath(locale: string, path: string) {
915
1035
  return locale === defaultLocale ? path : "/" + locale + path;
@@ -1063,147 +1183,20 @@ export default robots;
1063
1183
 
1064
1184
  ---
1065
1185
 
1066
- ## TypeScript & safety
1067
-
1068
- <Columns>
1069
- <Column>
1070
-
1071
- **next-intl**
1072
-
1073
- - Solid TypeScript support, but **keys aren’t strictly typed by default**; you’ll maintain safety patterns manually.
1074
-
1075
- </Column>
1076
- <Column>
1077
-
1078
- **next-i18next**
1079
-
1080
- - Base typings for hooks; **strict key typing requires extra tooling/config**.
1081
-
1082
- </Column>
1083
- <Column>
1084
-
1085
- **intlayer**
1086
-
1087
- - **Generates strict types** from your content. **IDE autocompletion** and **compile-time errors** catch typos and missing keys before deploy.
1088
-
1089
- </Column>
1090
- <Columns>
1091
-
1092
- **Why it matters:** Strong typing shifts failures **left** (CI/build) instead of **right** (runtime).
1093
-
1094
1186
  ---
1095
1187
 
1096
- ## Missing translation handling
1097
-
1098
- **next-intl**
1099
-
1100
- - Relies on **runtime fallbacks** (e.g., show the key or default locale). Build doesn’t fail.
1101
-
1102
- **next-i18next**
1103
-
1104
- - Relies on **runtime fallbacks** (e.g., show the key or default locale). Build doesn’t fail.
1105
-
1106
- **intlayer**
1107
-
1108
- - **Build-time detection** with **warnings/errors** for missing locales or keys.
1109
-
1110
- **Why it matters:** Catching gaps during build prevents “mystery strings” in production and aligns with strict release gates.
1111
-
1112
- ---
1113
-
1114
- ## Routing, middleware & URL strategy
1115
-
1116
- <Columns>
1117
- <Column>
1118
-
1119
- **next-intl**
1120
-
1121
- - Works with **Next.js localized routing** on the App Router.
1122
-
1123
- </Column>
1124
- <Column>
1125
-
1126
- **next-i18next**
1127
-
1128
- - Works with **Next.js localized routing** on the App Router.
1129
-
1130
- </Column>
1131
- <Column>
1132
-
1133
- **intlayer**
1134
-
1135
- - All of the above, plus **i18n middleware** (locale detection via headers/cookies) and **helpers** to generate localized URLs and `<link rel="alternate" hreflang="…">` tags.
1136
-
1137
- </Column>
1138
- </Columns>
1139
-
1140
- **Why it matters:** Fewer custom glue layers; **consistent UX** and **clean SEO** across locales.
1141
-
1142
- ---
1143
-
1144
- ## Server Components (RSC) alignment
1145
-
1146
- <Columns>
1147
- <Column>
1148
-
1149
- **next-intl**
1150
-
1151
- - Supports Next.js 13+. Often requires passing t-functions/formatters through component trees in hybrid setups.
1152
-
1153
- </Column>
1154
- <Column>
1155
-
1156
- **next-i18next**
1157
-
1158
- - Supports Next.js 13+. Similar constraints with passing translation utilities across boundaries.
1159
-
1160
- </Column>
1161
- <Column>
1162
-
1163
- **intlayer**
1164
-
1165
- - Supports Next.js 13+ and smooths the **server/client boundary** with a consistent API and RSC-oriented providers, avoiding shuttling formatters or t-functions.
1166
-
1167
- </Column>
1168
- </Columns>
1169
-
1170
- **Why it matters:** Cleaner mental model and fewer edge cases in hybrid trees.
1171
-
1172
- ---
1188
+ ## And the winner is…
1173
1189
 
1174
- ## DX, tooling & maintenance
1190
+ It’s not simple. Each option has trade-offs. Here’s how I see it:
1175
1191
 
1176
1192
  <Columns>
1177
1193
  <Column>
1178
1194
 
1179
- **next-intl**
1180
-
1181
- - Commonly paired with external localization platforms and editorial workflows.
1182
-
1183
- </Column>
1184
- <Column>
1185
-
1186
1195
  **next-i18next**
1187
1196
 
1188
- - Commonly paired with external localization platforms and editorial workflows.
1189
-
1190
- </Column>
1191
- <Column>
1192
-
1193
- **intlayer**
1194
-
1195
- - Ships a **free Visual Editor** and **optional CMS** (Git-friendly or externalized), plus a **VSCode extension** and **AI-assisted translations** using your own provider keys.
1197
+ - mature, full of features, lots of community plugins, but higher setup cost. If you need **i18next’s plugin ecosystem** (e.g., advanced ICU rules via plugins) and your team already knows i18next, accepting **more configuration** for flexibility.
1196
1198
 
1197
1199
  </Column>
1198
- </Columns>
1199
-
1200
- **Why it matters:** Lowers ops cost and shortens the loop between developers and content authors.
1201
-
1202
- ## And the winner is…
1203
-
1204
- It’s not simple. Each option has trade-offs. Here’s how I see it:
1205
-
1206
- <Columns>
1207
1200
  <Column>
1208
1201
 
1209
1202
  **next-intl**
@@ -1213,13 +1206,6 @@ It’s not simple. Each option has trade-offs. Here’s how I see it:
1213
1206
  </Column>
1214
1207
  <Column>
1215
1208
 
1216
- **next-i18next**
1217
-
1218
- - mature, full of features, lots of community plugins, but higher setup cost. If you need **i18next’s plugin ecosystem** (e.g., advanced ICU rules via plugins) and your team already knows i18next, accepting **more configuration** for flexibility.
1219
-
1220
- </Column>
1221
- <Column>
1222
-
1223
1209
  **Intlayer**
1224
1210
 
1225
1211
  - built for modern Next.js, with modular content, type safety, tooling, and less boilerplate. If you value **component-scoped content**, **strict TypeScript**, **build-time guarantees**, **tree-shaking**, and **batteries-included** routing/SEO/editor tooling - especially for **Next.js App Router**, design-systems and **large, modular codebases**.
@@ -1233,8 +1219,6 @@ If you prefer minimal setup and accept some manual wiring, next-intl is a good p
1233
1219
 
1234
1220
  > **Future roadmap**: Intlayer also plans to develop plugins that work on top of **i18next** and **next-intl** solutions. This will give you the advantages of Intlayer for automation, syntax, and content management while keeping the security and stability provided by these established solutions in your application code.
1235
1221
 
1236
- ---
1237
-
1238
1222
  ## GitHub STARs
1239
1223
 
1240
1224
  GitHub stars are a strong indicator of a project's popularity, community trust, and long-term relevance. While not a direct measure of technical quality, they reflect how many developers find the project useful, follow its progress, and are likely to adopt it. For estimating the value of a project, stars help compare traction across alternatives and provide insights into ecosystem growth.