@intlayer/docs 7.0.3 → 7.0.4-canary.0

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 (62) hide show
  1. package/blog/en/intlayer_with_i18next.md +1620 -54
  2. package/blog/en/intlayer_with_next-i18next.md +763 -163
  3. package/blog/en/intlayer_with_next-intl.md +986 -217
  4. package/blog/en/intlayer_with_react-i18next.md +645 -147
  5. package/blog/en/intlayer_with_react-intl.md +900 -147
  6. package/blog/en/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  7. package/dist/cjs/generated/blog.entry.cjs +13 -1
  8. package/dist/cjs/generated/blog.entry.cjs.map +1 -1
  9. package/dist/cjs/generated/docs.entry.cjs +13 -1
  10. package/dist/cjs/generated/docs.entry.cjs.map +1 -1
  11. package/dist/cjs/generated/frequentQuestions.entry.cjs +13 -1
  12. package/dist/cjs/generated/frequentQuestions.entry.cjs.map +1 -1
  13. package/dist/cjs/generated/legal.entry.cjs +13 -1
  14. package/dist/cjs/generated/legal.entry.cjs.map +1 -1
  15. package/dist/esm/generated/blog.entry.mjs +13 -2
  16. package/dist/esm/generated/blog.entry.mjs.map +1 -1
  17. package/dist/esm/generated/docs.entry.mjs +13 -2
  18. package/dist/esm/generated/docs.entry.mjs.map +1 -1
  19. package/dist/esm/generated/frequentQuestions.entry.mjs +13 -2
  20. package/dist/esm/generated/frequentQuestions.entry.mjs.map +1 -1
  21. package/dist/esm/generated/legal.entry.mjs +13 -2
  22. package/dist/esm/generated/legal.entry.mjs.map +1 -1
  23. package/dist/types/generated/blog.entry.d.ts.map +1 -1
  24. package/dist/types/generated/docs.entry.d.ts.map +1 -1
  25. package/dist/types/generated/frequentQuestions.entry.d.ts.map +1 -1
  26. package/dist/types/generated/legal.entry.d.ts.map +1 -1
  27. package/docs/de/releases/v7.md +1 -18
  28. package/docs/en/CI_CD.md +1 -1
  29. package/docs/en/configuration.md +1 -1
  30. package/docs/en/formatters.md +1 -1
  31. package/docs/en/how_works_intlayer.md +1 -1
  32. package/docs/en/intlayer_CMS.md +1 -1
  33. package/docs/en/intlayer_cli.md +1 -1
  34. package/docs/en/intlayer_with_nextjs_14.md +1 -1
  35. package/docs/en/intlayer_with_nextjs_15.md +1 -1
  36. package/docs/en/intlayer_with_nextjs_16.md +1 -1
  37. package/docs/en/intlayer_with_nextjs_page_router.md +1 -1
  38. package/docs/en/intlayer_with_nuxt.md +1 -1
  39. package/docs/en/intlayer_with_react_native+expo.md +1 -1
  40. package/docs/en/intlayer_with_react_router_v7.md +1 -1
  41. package/docs/en/intlayer_with_tanstack.md +1 -1
  42. package/docs/en/intlayer_with_vite+preact.md +1 -1
  43. package/docs/en/intlayer_with_vite+react.md +1 -1
  44. package/docs/en/intlayer_with_vite+solid.md +1 -1
  45. package/docs/en/intlayer_with_vite+svelte.md +1 -1
  46. package/docs/en/intlayer_with_vite+vue.md +1 -1
  47. package/docs/en/roadmap.md +1 -1
  48. package/docs/es/releases/v7.md +1 -18
  49. package/docs/fr/intlayer_with_nextjs_16.md +2 -51
  50. package/docs/fr/releases/v7.md +1 -18
  51. package/docs/hi/intlayer_with_nextjs_16.md +3 -2
  52. package/docs/id/releases/v7.md +1 -18
  53. package/docs/it/releases/v7.md +1 -18
  54. package/docs/ja/intlayer_with_nextjs_16.md +44 -205
  55. package/docs/ja/releases/v7.md +1 -18
  56. package/docs/ko/releases/v7.md +1 -18
  57. package/docs/pt/intlayer_with_nextjs_16.md +1 -52
  58. package/package.json +14 -14
  59. package/src/generated/blog.entry.ts +26 -3
  60. package/src/generated/docs.entry.ts +26 -3
  61. package/src/generated/frequentQuestions.entry.ts +26 -3
  62. package/src/generated/legal.entry.ts +26 -3
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  createdAt: 2025-08-23
3
- updatedAt: 2025-08-23
3
+ updatedAt: 2025-10-29
4
4
  title: Intlayer and next-i18next
5
- description: Integrate Intlayer with next-i18next for a Next.js app
5
+ description: Integrate Intlayer with next-i18next for a comprehensive Next.js internationalization solution
6
6
  keywords:
7
7
  - i18next
8
8
  - next-i18next
@@ -15,106 +15,118 @@ keywords:
15
15
  slugs:
16
16
  - blog
17
17
  - intlayer-with-next-i18next
18
+ history:
19
+ - version: 7.0.0
20
+ date: 2025-10-29
21
+ changes: Change to syncJSON plugin and comprehensive rewrite
18
22
  ---
19
23
 
20
24
  # Next.js Internationalization (i18n) with next-i18next and Intlayer
21
25
 
22
- Both next-i18next and Intlayer are open-source internationalization (i18n) frameworks designed for Next.js applications. They are widely used for managing translations, localization, and language switching in software projects.
26
+ ## Table of Contents
23
27
 
24
- Both solutions include three principal notions:
28
+ <TOC/>
25
29
 
26
- 1. **Dictionary**: The method for defining the translatable content of your application.
27
- - Named `resource` in the case of `i18next`, the content declaration is a structured JSON object containing key-value pairs for translations in one or more languages. See [i18next documentation](https://www.i18next.com/translation-function/essentials) for more information.
28
- - Named `content declaration file` in the case of `Intlayer`, the content declaration can be a JSON, JS, or TS file exporting the structured data. See [Intlayer documentation](https://intlayer.org/fr/doc/concept/content) for more information.
30
+ ## What is next-i18next?
29
31
 
30
- 2. **Utilities**: Tools to build and interpret content declarations in the application, such as `getI18n()`, `useCurrentLocale()`, or `useChangeLocale()` for next-i18next, and `useIntlayer()` or `useLocale()` for Intlayer.
32
+ **next-i18next** is one of the most popular internationalization (i18n) frameworks for Next.js applications. Built on top of the powerful **i18next** ecosystem, it provides a comprehensive solution for managing translations, localization, and language switching in Next.js projects.
31
33
 
32
- 3. **Plugins and Middlewares**: Features for managing URL redirection, bundling optimization, and more, such as `next-i18next/middleware` for next-i18next or `intlayerMiddleware` for Intlayer.
34
+ However, next-i18next comes with some challenges:
33
35
 
34
- ## Intlayer vs. i18next: Key Differences
36
+ - **Complex configuration**: Setting up next-i18next requires multiple configuration files and careful setup of server-side and client-side i18n instances.
37
+ - **Scattered translations**: Translation files are typically stored in separate directories from components, making it harder to maintain consistency.
38
+ - **Manual namespace management**: Developers need to manually manage namespaces and ensure proper loading of translation resources.
39
+ - **Limited type safety**: TypeScript support requires additional configuration and doesn't provide automatic type generation for translations.
35
40
 
36
- To explore the differences between i18next and Intlayer, check out our [next-i18next vs. next-intl vs. Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/blog/en/i18next_vs_next-intl_vs_intlayer.md) blog post.
41
+ ## What is Intlayer?
37
42
 
38
- ## How to Generate next-i18next Dictionaries with Intlayer
43
+ **Intlayer** is an innovative, open-source internationalization library designed to address the shortcomings of traditional i18n solutions. It offers a modern approach to content management in Next.js applications.
39
44
 
40
- ### Why Use Intlayer with next-i18next?
45
+ Key advantages of Intlayer:
41
46
 
42
- Intlayer content declaration files generally offer a better developer experience. They are more flexible and maintainable due to two main advantages:
47
+ - **Declarative content management**: Translations are defined alongside components, improving maintainability.
48
+ - **Type-safe by design**: Auto-generated TypeScript types ensure type safety and autocompletion.
49
+ - **Flexible content structure**: Supports complex content structures beyond simple key-value pairs.
50
+ - **Built-in Visual Editor**: Optional visual editing capabilities for non-technical team members.
51
+ - **Framework optimization**: Deep integration with Next.js for optimal performance.
43
52
 
44
- 1. **Flexible Placement**: An Intlayer content declaration file can be placed anywhere in the application's file tree, simplifying the management of duplicated or deleted components without leaving unused content declarations.
53
+ ## Why Combine Intlayer with next-i18next?
45
54
 
46
- Example file structures:
55
+ While Intlayer provides an excellent standalone i18n solution (see our [Next.js integration guide](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_with_nextjs_16.md)), you might want to combine it with next-i18next for several reasons:
47
56
 
48
- ```bash codeFormat="typescript"
49
- .
50
- └── src
51
- └── components
52
- └── MyComponent
53
- ├── index.content.ts # Content declaration file
54
- └── index.tsx
55
- ```
57
+ 1. **Existing codebase**: You have an established next-i18next implementation and want to gradually migrate to Intlayer's improved developer experience.
58
+ 2. **Legacy requirements**: Your project requires compatibility with existing i18next plugins or workflows.
59
+ 3. **Team familiarity**: Your team is comfortable with next-i18next but wants better content management.
56
60
 
57
- ```bash codeFormat="esm"
58
- .
59
- └── src
60
- └── components
61
- └── MyComponent
62
- ├── index.content.mjs # Content declaration file
63
- └── index.mjx
64
- ```
61
+ This guide shows you how to leverage Intlayer's superior content declaration system while maintaining compatibility with next-i18next.
65
62
 
66
- ```bash codeFormat="cjs"
67
- .
68
- └── src
69
- └── components
70
- └── MyComponent
71
- ├── index.content.cjs # Content declaration file
72
- └── index.cjx
73
- ```
63
+ ## Intlayer vs. next-i18next: Key Differences
74
64
 
75
- ```bash codeFormat="json"
76
- .
77
- └── src
78
- └── components
79
- └── MyComponent
80
- ├── index.content.json # Content declaration file
81
- └── index.jsx
82
- ```
65
+ For a detailed comparison of different i18n solutions including next-i18next and Intlayer, check out our [next-i18next vs. next-intl vs. Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/blog/en/next-i18next_vs_next-intl_vs_intlayer.md) blog post.
83
66
 
84
- 2. **Centralized Translations**: Intlayer stores all translations in a single file, ensuring no translation is missing. When using TypeScript, missing translations are automatically detected and reported as errors.
67
+ Key differences:
85
68
 
86
- ### Installation
69
+ | Feature | next-i18next | Intlayer with next-i18next |
70
+ | ----------------- | ---------------------------- | -------------------------- |
71
+ | Content Location | Separate translation folders | Co-located with components |
72
+ | Type Safety | Manual setup required | Auto-generated types |
73
+ | Content Structure | Flat key-value pairs | Nested, structured objects |
74
+ | Visual Editor | Not included | Built-in optional editor |
75
+ | Setup Complexity | Multiple config files | Minimal configuration |
76
+
77
+ ---
78
+
79
+ ## Step-by-Step Guide to Set Up Intlayer with next-i18next
80
+
81
+ ### Step 1: Install Dependencies
82
+
83
+ Install the necessary packages using your preferred package manager:
87
84
 
88
85
  ```bash packageManager="npm"
89
- npm install intlayer i18next next-i18next i18next-resources-to-backend
86
+ npm install intlayer next-intlayer i18next next-i18next i18next-resources-to-backend @intlayer/sync-json-plugin
90
87
  ```
91
88
 
92
- ```bash packageManager="yarn"
93
- yarn add intlayer i18next next-i18next i18next-resources-to-backend
89
+ ```bash packageManager="pnpm"
90
+ pnpm add intlayer next-intlayer i18next next-i18next i18next-resources-to-backend @intlayer/sync-json-plugin
94
91
  ```
95
92
 
96
- ```bash packageManager="pnpm"
97
- pnpm add intlayer i18next next-i18next i18next-resources-to-backend
93
+ ```bash packageManager="yarn"
94
+ yarn add intlayer next-intlayer i18next next-i18next i18next-resources-to-backend @intlayer/sync-json-plugin
98
95
  ```
99
96
 
100
- ### Configuring Intlayer to Export i18next Dictionaries
97
+ **Package explanations:**
101
98
 
102
- > Exporting i18next resources does not ensure 1:1 compatibility with other frameworks. It's recommended to stick to an Intlayer-based configuration to minimize issues.
99
+ - **intlayer**: Core library for content declaration and management
100
+ - **next-intlayer**: Next.js integration layer with build plugins
101
+ - **i18next**: Core i18n framework
102
+ - **next-i18next**: Next.js wrapper for i18next
103
+ - **i18next-resources-to-backend**: Dynamic resource loading for i18next
104
+ - **@intlayer/sync-json-plugin**: Plugin to sync Intlayer content declarations to i18next JSON format
103
105
 
104
- To export i18next resources, configure Intlayer in a `intlayer.config.ts` file. Example configurations:
106
+ ### Step 2: Configure Your Project
107
+
108
+ Create an Intlayer configuration file to define your locales and set up the sync plugin:
105
109
 
106
110
  ```typescript fileName="intlayer.config.ts" codeFormat="typescript"
107
111
  import { Locales, type IntlayerConfig } from "intlayer";
112
+ import { syncJSON } from "@intlayer/sync-json-plugin";
108
113
 
109
114
  const config: IntlayerConfig = {
110
115
  internationalization: {
111
- locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
116
+ locales: [
117
+ Locales.ENGLISH,
118
+ Locales.FRENCH,
119
+ Locales.SPANISH,
120
+ // Add your other locales
121
+ ],
112
122
  defaultLocale: Locales.ENGLISH,
113
123
  },
114
- content: {
115
- dictionaryOutput: ["i18next"],
116
- i18nextResourcesDir: "./i18next/resources",
117
- },
124
+ plugins: [
125
+ syncJSON({
126
+ // Specify where i18next JSON files should be generated
127
+ source: ({ key, locale }) => `./intl/messages/${locale}/${key}.json`,
128
+ }),
129
+ ],
118
130
  };
119
131
 
120
132
  export default config;
@@ -122,17 +134,24 @@ export default config;
122
134
 
123
135
  ```javascript fileName="intlayer.config.mjs" codeFormat="esm"
124
136
  import { Locales } from "intlayer";
137
+ import { syncJSON } from "@intlayer/sync-json-plugin";
125
138
 
126
139
  /** @type {import('intlayer').IntlayerConfig} */
127
140
  const config = {
128
141
  internationalization: {
129
- locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
142
+ locales: [
143
+ Locales.ENGLISH,
144
+ Locales.FRENCH,
145
+ Locales.SPANISH,
146
+ // Add your other locales
147
+ ],
130
148
  defaultLocale: Locales.ENGLISH,
131
149
  },
132
- content: {
133
- dictionaryOutput: ["i18next"],
134
- i18nextResourcesDir: "./i18next/resources",
135
- },
150
+ plugins: [
151
+ syncJSON({
152
+ source: ({ key, locale }) => `./intl/messages/${locale}/${key}.json`,
153
+ }),
154
+ ],
136
155
  };
137
156
 
138
157
  export default config;
@@ -140,141 +159,354 @@ export default config;
140
159
 
141
160
  ```javascript fileName="intlayer.config.cjs" codeFormat="commonjs"
142
161
  const { Locales } = require("intlayer");
162
+ const { syncJSON } = require("@intlayer/sync-json-plugin");
143
163
 
144
164
  /** @type {import('intlayer').IntlayerConfig} */
145
165
  const config = {
146
166
  internationalization: {
147
- locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
167
+ locales: [
168
+ Locales.ENGLISH,
169
+ Locales.FRENCH,
170
+ Locales.SPANISH,
171
+ // Add your other locales
172
+ ],
148
173
  defaultLocale: Locales.ENGLISH,
149
174
  },
150
- content: {
151
- dictionaryOutput: ["i18next"],
152
- i18nextResourcesDir: "./i18next/resources",
153
- },
175
+ plugins: [
176
+ syncJSON({
177
+ source: ({ key, locale }) => `./intl/messages/${locale}/${key}.json`,
178
+ }),
179
+ ],
154
180
  };
155
181
 
156
182
  module.exports = config;
157
183
  ```
158
184
 
159
- Here’s the continuation and correction of the remaining parts of your document:
185
+ > The `syncJSON` plugin automatically converts Intlayer content declarations to i18next-compatible JSON files. For more configuration options, refer to the [configuration documentation](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/configuration.md).
160
186
 
161
- ---
187
+ ### Step 3: Integrate Intlayer in Your Next.js Configuration
188
+
189
+ Configure your Next.js setup to use Intlayer's build plugin:
190
+
191
+ ```typescript fileName="next.config.ts" codeFormat="typescript"
192
+ import type { NextConfig } from "next";
193
+ import { withIntlayer } from "next-intlayer/server";
194
+
195
+ const nextConfig: NextConfig = {
196
+ /* your Next.js config options */
197
+ };
198
+
199
+ export default withIntlayer(nextConfig);
200
+ ```
201
+
202
+ ```javascript fileName="next.config.mjs" codeFormat="esm"
203
+ import { withIntlayer } from "next-intlayer/server";
204
+
205
+ /** @type {import('next').NextConfig} */
206
+ const nextConfig = {
207
+ /* your Next.js config options */
208
+ };
209
+
210
+ export default withIntlayer(nextConfig);
211
+ ```
162
212
 
163
- ### Importing Dictionaries into Your i18next Configuration
213
+ ```javascript fileName="next.config.cjs" codeFormat="commonjs"
214
+ const { withIntlayer } = require("next-intlayer/server");
215
+
216
+ /** @type {import('next').NextConfig} */
217
+ const nextConfig = {
218
+ /* your Next.js config options */
219
+ };
220
+
221
+ module.exports = withIntlayer(nextConfig);
222
+ ```
164
223
 
165
- To import the generated resources into your i18next configuration, use `i18next-resources-to-backend`. Below are examples:
224
+ > The `withIntlayer()` plugin ensures that Intlayer content declarations are built and monitored during development. It automatically regenerates i18next JSON files when you modify content declarations.
225
+
226
+ ### Step 4: Set Up next-i18next Configuration
227
+
228
+ Create the standard next-i18next configuration file:
229
+
230
+ ```javascript fileName="next-i18next.config.js"
231
+ module.exports = {
232
+ i18n: {
233
+ defaultLocale: "en",
234
+ locales: ["en", "fr", "es"],
235
+ },
236
+ };
237
+ ```
238
+
239
+ Update your Next.js config to use next-i18next:
240
+
241
+ ```typescript fileName="next.config.ts" codeFormat="typescript"
242
+ import type { NextConfig } from "next";
243
+ import { withIntlayer } from "next-intlayer/server";
244
+
245
+ const nextConfig: NextConfig = {
246
+ /* your Next.js config options */
247
+ i18n: {
248
+ defaultLocale: "en",
249
+ locales: ["en", "fr", "es"],
250
+ },
251
+ };
252
+
253
+ export default withIntlayer(nextConfig);
254
+ ```
255
+
256
+ ```javascript fileName="next.config.mjs" codeFormat="esm"
257
+ import { withIntlayer } from "next-intlayer/server";
258
+
259
+ /** @type {import('next').NextConfig} */
260
+ const nextConfig = {
261
+ /* your Next.js config options */
262
+ i18n: {
263
+ defaultLocale: "en",
264
+ locales: ["en", "fr", "es"],
265
+ },
266
+ };
267
+
268
+ export default withIntlayer(nextConfig);
269
+ ```
270
+
271
+ ```javascript fileName="next.config.cjs" codeFormat="commonjs"
272
+ const { withIntlayer } = require("next-intlayer/server");
273
+
274
+ /** @type {import('next').NextConfig} */
275
+ const nextConfig = {
276
+ /* your Next.js config options */
277
+ i18n: {
278
+ defaultLocale: "en",
279
+ locales: ["en", "fr", "es"],
280
+ },
281
+ };
282
+
283
+ module.exports = withIntlayer(nextConfig);
284
+ ```
285
+
286
+ ### Step 5: Set Up i18next Client Configuration
287
+
288
+ Create an i18next configuration file to load the generated resources:
166
289
 
167
290
  ```typescript fileName="i18n/client.ts" codeFormat="typescript"
168
291
  import i18next from "i18next";
292
+ import { initReactI18next } from "react-i18next";
169
293
  import resourcesToBackend from "i18next-resources-to-backend";
170
294
 
171
- i18next.use(
172
- resourcesToBackend(
173
- (language: string, namespace: string) =>
174
- import(`../i18next/resources/${language}/${namespace}.json`)
295
+ i18next
296
+ .use(initReactI18next)
297
+ .use(
298
+ resourcesToBackend(
299
+ (language: string, namespace: string) =>
300
+ import(`../intl/messages/${language}/${namespace}.json`)
301
+ )
175
302
  )
176
- );
303
+ .init({
304
+ fallbackLng: "en",
305
+ // Add other i18next configuration options as needed
306
+ });
307
+
308
+ export default i18next;
177
309
  ```
178
310
 
179
311
  ```javascript fileName="i18n/client.mjs" codeFormat="esm"
180
312
  import i18next from "i18next";
313
+ import { initReactI18next } from "react-i18next";
181
314
  import resourcesToBackend from "i18next-resources-to-backend";
182
315
 
183
- i18next.use(
184
- resourcesToBackend(
185
- (language, namespace) =>
186
- import(`../i18next/resources/${language}/${namespace}.json`)
316
+ i18next
317
+ .use(initReactI18next)
318
+ .use(
319
+ resourcesToBackend(
320
+ (language, namespace) =>
321
+ import(`../intl/messages/${language}/${namespace}.json`)
322
+ )
187
323
  )
188
- );
324
+ .init({
325
+ fallbackLng: "en",
326
+ });
327
+
328
+ export default i18next;
189
329
  ```
190
330
 
191
331
  ```javascript fileName="i18n/client.cjs" codeFormat="commonjs"
192
332
  const i18next = require("i18next");
333
+ const { initReactI18next } = require("react-i18next");
193
334
  const resourcesToBackend = require("i18next-resources-to-backend");
194
335
 
195
- i18next.use(
196
- resourcesToBackend(
197
- (language, namespace) =>
198
- import(`../i18next/resources/${language}/${namespace}.json`)
336
+ i18next
337
+ .use(initReactI18next)
338
+ .use(
339
+ resourcesToBackend(
340
+ (language, namespace) =>
341
+ import(`../intl/messages/${language}/${namespace}.json`)
342
+ )
199
343
  )
200
- );
344
+ .init({
345
+ fallbackLng: "en",
346
+ });
347
+
348
+ module.exports = i18next;
201
349
  ```
202
350
 
203
- ### Dictionary
351
+ ### Step 6: Declare Your Content
204
352
 
205
- Examples of content declaration files in various formats:
353
+ Create content declaration files alongside your components:
206
354
 
207
- ```typescript fileName="**/*.content.ts" contentDeclarationFormat="typescript"
355
+ ```typescript fileName="src/components/Hero/Hero.content.ts" contentDeclarationFormat="typescript"
208
356
  import { t, type Dictionary } from "intlayer";
209
357
 
210
- const content = {
211
- key: "my-content",
358
+ const heroContent = {
359
+ key: "hero",
212
360
  content: {
213
- myTranslatedContent: t({
214
- en: "Hello World",
215
- es: "Hola Mundo",
216
- fr: "Bonjour le monde",
361
+ title: t({
362
+ en: "Welcome to Our Platform",
363
+ fr: "Bienvenue sur notre plateforme",
364
+ es: "Bienvenido a nuestra plataforma",
217
365
  }),
366
+ description: t({
367
+ en: "Discover amazing features and possibilities",
368
+ fr: "Découvrez des fonctionnalités et possibilités incroyables",
369
+ es: "Descubre características y posibilidades increíbles",
370
+ }),
371
+ cta: {
372
+ primary: t({
373
+ en: "Get Started",
374
+ fr: "Commencer",
375
+ es: "Empezar",
376
+ }),
377
+ secondary: t({
378
+ en: "Learn More",
379
+ fr: "En savoir plus",
380
+ es: "Saber más",
381
+ }),
382
+ },
218
383
  },
219
384
  } satisfies Dictionary;
220
385
 
221
- export default content;
386
+ export default heroContent;
222
387
  ```
223
388
 
224
- ```javascript fileName="**/*.content.mjs" contentDeclarationFormat="esm"
389
+ ```javascript fileName="src/components/Hero/Hero.content.mjs" contentDeclarationFormat="esm"
225
390
  import { t } from "intlayer";
226
391
 
227
392
  /** @type {import('intlayer').Dictionary} */
228
- const content = {
229
- key: "my-content",
393
+ const heroContent = {
394
+ key: "hero",
230
395
  content: {
231
- myTranslatedContent: t({
232
- en: "Hello World",
233
- es: "Hola Mundo",
234
- fr: "Bonjour le monde",
396
+ title: t({
397
+ en: "Welcome to Our Platform",
398
+ fr: "Bienvenue sur notre plateforme",
399
+ es: "Bienvenido a nuestra plataforma",
400
+ }),
401
+ description: t({
402
+ en: "Discover amazing features and possibilities",
403
+ fr: "Découvrez des fonctionnalités et possibilités incroyables",
404
+ es: "Descubre características y posibilidades increíbles",
235
405
  }),
406
+ cta: {
407
+ primary: t({
408
+ en: "Get Started",
409
+ fr: "Commencer",
410
+ es: "Empezar",
411
+ }),
412
+ secondary: t({
413
+ en: "Learn More",
414
+ fr: "En savoir plus",
415
+ es: "Saber más",
416
+ }),
417
+ },
236
418
  },
237
419
  };
420
+
421
+ export default heroContent;
238
422
  ```
239
423
 
240
- ```javascript fileName="**/*.content.cjs" contentDeclarationFormat="commonjs"
424
+ ```javascript fileName="src/components/Hero/Hero.content.cjs" contentDeclarationFormat="commonjs"
241
425
  const { t } = require("intlayer");
242
426
 
243
- module.exports = {
244
- key: "my-content",
427
+ /** @type {import('intlayer').Dictionary} */
428
+ const heroContent = {
429
+ key: "hero",
245
430
  content: {
246
- myTranslatedContent: t({
247
- en: "Hello World",
248
- es: "Hola Mundo",
249
- fr: "Bonjour le monde",
431
+ title: t({
432
+ en: "Welcome to Our Platform",
433
+ fr: "Bienvenue sur notre plateforme",
434
+ es: "Bienvenido a nuestra plataforma",
250
435
  }),
436
+ description: t({
437
+ en: "Discover amazing features and possibilities",
438
+ fr: "Découvrez des fonctionnalités et possibilités incroyables",
439
+ es: "Descubre características y posibilidades increíbles",
440
+ }),
441
+ cta: {
442
+ primary: t({
443
+ en: "Get Started",
444
+ fr: "Commencer",
445
+ es: "Empezar",
446
+ }),
447
+ secondary: t({
448
+ en: "Learn More",
449
+ fr: "En savoir plus",
450
+ es: "Saber más",
451
+ }),
452
+ },
251
453
  },
252
454
  };
455
+
456
+ module.exports = heroContent;
253
457
  ```
254
458
 
255
- ```json fileName="**/*.content.json" contentDeclarationFormat="json"
459
+ ```json fileName="src/components/Hero/Hero.content.json" contentDeclarationFormat="json"
256
460
  {
257
461
  "$schema": "https://intlayer.org/schema.json",
258
- "key": "my-content",
462
+ "key": "hero",
259
463
  "content": {
260
- "myTranslatedContent": {
464
+ "title": {
465
+ "nodeType": "translation",
466
+ "translation": {
467
+ "en": "Welcome to Our Platform",
468
+ "fr": "Bienvenue sur notre plateforme",
469
+ "es": "Bienvenido a nuestra plataforma"
470
+ }
471
+ },
472
+ "description": {
261
473
  "nodeType": "translation",
262
474
  "translation": {
263
- "en": "Hello World",
264
- "fr": "Bonjour le monde",
265
- "es": "Hola Mundo"
475
+ "en": "Discover amazing features and possibilities",
476
+ "fr": "Découvrez des fonctionnalités et possibilités incroyables",
477
+ "es": "Descubre características y posibilidades increíbles"
478
+ }
479
+ },
480
+ "cta": {
481
+ "primary": {
482
+ "nodeType": "translation",
483
+ "translation": {
484
+ "en": "Get Started",
485
+ "fr": "Commencer",
486
+ "es": "Empezar"
487
+ }
488
+ },
489
+ "secondary": {
490
+ "nodeType": "translation",
491
+ "translation": {
492
+ "en": "Learn More",
493
+ "fr": "En savoir plus",
494
+ "es": "Saber más"
495
+ }
266
496
  }
267
497
  }
268
498
  }
269
499
  }
270
500
  ```
271
501
 
272
- ### Build the next-i18next Resources
502
+ > Content declarations can be placed anywhere in your `src` directory (or configured `contentDir`). The file must match the pattern `*.content.{ts,tsx,js,jsx,mjs,cjs,json}`. For more details, see the [content declaration documentation](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/dictionary/content_file.md).
503
+
504
+ ### Step 7: Build i18next Resources
273
505
 
274
- To build the next-i18next resources, run the following command:
506
+ Generate the i18next JSON files from your Intlayer content declarations:
275
507
 
276
508
  ```bash packageManager="npm"
277
- npx run intlayer build
509
+ npx intlayer build
278
510
  ```
279
511
 
280
512
  ```bash packageManager="yarn"
@@ -285,83 +517,451 @@ yarn intlayer build
285
517
  pnpm intlayer build
286
518
  ```
287
519
 
288
- This will generate resources in the `./i18next/resources` directory. The expected output:
520
+ This will generate files in the `./intl/messages` directory:
289
521
 
290
522
  ```bash
291
- .
292
- └── i18next
293
- └── resources
294
- └── en
295
- └── my-content.json
296
- └── fr
297
- └── my-content.json
523
+ intl
524
+ └── messages
525
+ ├── en
526
+ └── hero.json
527
+ ├── fr
528
+ └── hero.json
298
529
  └── es
299
- └── my-content.json
530
+ └── hero.json
300
531
  ```
301
532
 
302
- Note: The i18next namespace corresponds to the Intlayer declaration key.
533
+ Each JSON file contains translations extracted from the corresponding Intlayer content declarations.
303
534
 
304
- ### Implement Next.js Plugin
535
+ ### Step 8: Utilize Content in Your Code
305
536
 
306
- Once configured, implement the Next.js plugin to rebuild your i18next resources whenever Intlayer content declaration files are updated.
537
+ Access your translations using next-i18next's hooks:
307
538
 
308
- ```typescript fileName="next.config.mjs"
309
- import { withIntlayer } from "next-intlayer/server";
539
+ ```typescript fileName="src/components/Hero/Hero.tsx" codeFormat="typescript"
540
+ import type { FC } from "react";
541
+ import { useTranslation } from "next-i18next";
310
542
 
311
- /** @type {import('next').NextConfig} */
312
- const nextConfig = {};
543
+ const Hero: FC = () => {
544
+ const { t } = useTranslation("hero");
313
545
 
314
- export default withIntlayer(nextConfig);
546
+ return (
547
+ <section>
548
+ <h1>{t("title")}</h1>
549
+ <p>{t("description")}</p>
550
+ <div>
551
+ <button>{t("cta.primary")}</button>
552
+ <button>{t("cta.secondary")}</button>
553
+ </div>
554
+ </section>
555
+ );
556
+ };
557
+
558
+ export default Hero;
315
559
  ```
316
560
 
317
- ### Using Content in Next.js Components
561
+ ```jsx fileName="src/components/Hero/Hero.mjx" codeFormat="esm"
562
+ import { useTranslation } from "next-i18next";
318
563
 
319
- After implementing the Next.js plugin, you can use the content in your components:
564
+ const Hero = () => {
565
+ const { t } = useTranslation("hero");
320
566
 
321
- ```typescript fileName="src/components/myComponent/index.tsx" codeFormat="typescript"
567
+ return (
568
+ <section>
569
+ <h1>{t("title")}</h1>
570
+ <p>{t("description")}</p>
571
+ <div>
572
+ <button>{t("cta.primary")}</button>
573
+ <button>{t("cta.secondary")}</button>
574
+ </div>
575
+ </section>
576
+ );
577
+ };
578
+
579
+ export default Hero;
580
+ ```
581
+
582
+ ```jsx fileName="src/components/Hero/Hero.csx" codeFormat="commonjs"
583
+ const { useTranslation } = require("next-i18next");
584
+
585
+ const Hero = () => {
586
+ const { t } = useTranslation("hero");
587
+
588
+ return (
589
+ <section>
590
+ <h1>{t("title")}</h1>
591
+ <p>{t("description")}</p>
592
+ <div>
593
+ <button>{t("cta.primary")}</button>
594
+ <button>{t("cta.secondary")}</button>
595
+ </div>
596
+ </section>
597
+ );
598
+ };
599
+
600
+ module.exports = Hero;
601
+ ```
602
+
603
+ > The namespace in `useTranslation("hero")` corresponds to the `key` field in your Intlayer content declaration.
604
+
605
+ ### (Optional) Step 9: Internationalization of Metadata
606
+
607
+ For page metadata, use next-i18next's `serverSideTranslations`:
608
+
609
+ ```typescript fileName="src/pages/index.tsx" codeFormat="typescript"
610
+ import { GetStaticProps } from "next";
611
+ import { serverSideTranslations } from "next-i18next/serverSideTranslations";
612
+ import { useTranslation } from "next-i18next";
613
+ import Head from "next/head";
614
+
615
+ export default function Home() {
616
+ const { t } = useTranslation("common");
617
+
618
+ return (
619
+ <>
620
+ <Head>
621
+ <title>{t("meta.title")}</title>
622
+ <meta name="description" content={t("meta.description")} />
623
+ </Head>
624
+ {/* Page content */}
625
+ </>
626
+ );
627
+ }
628
+
629
+ export const getStaticProps: GetStaticProps = async ({ locale }) => {
630
+ return {
631
+ props: {
632
+ ...(await serverSideTranslations(locale ?? "en", ["common"])),
633
+ },
634
+ };
635
+ };
636
+ ```
637
+
638
+ Create a corresponding metadata content declaration:
639
+
640
+ ```typescript fileName="src/content/metadata.content.ts" contentDeclarationFormat="typescript"
641
+ import { t, type Dictionary } from "intlayer";
642
+
643
+ const metadataContent = {
644
+ key: "common",
645
+ content: {
646
+ meta: {
647
+ title: t({
648
+ en: "My Amazing App",
649
+ fr: "Mon Application Incroyable",
650
+ es: "Mi Aplicación Increíble",
651
+ }),
652
+ description: t({
653
+ en: "Discover the best features of our platform",
654
+ fr: "Découvrez les meilleures fonctionnalités de notre plateforme",
655
+ es: "Descubre las mejores características de nuestra plataforma",
656
+ }),
657
+ },
658
+ },
659
+ } satisfies Dictionary;
660
+
661
+ export default metadataContent;
662
+ ```
663
+
664
+ ### (Optional) Step 10: Internationalization of sitemap.xml and robots.txt
665
+
666
+ For sitemap and robots.txt internationalization, you can use next-i18next's locale information:
667
+
668
+ ```typescript fileName="src/pages/sitemap.xml.ts" codeFormat="typescript"
669
+ import { GetServerSideProps } from "next";
670
+
671
+ const SITE_URL = "https://example.com";
672
+
673
+ function generateSiteMap(locales: string[]) {
674
+ return `<?xml version="1.0" encoding="UTF-8"?>
675
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
676
+ xmlns:xhtml="http://www.w3.org/1999/xhtml">
677
+ ${locales
678
+ .map((locale) => {
679
+ return `
680
+ <url>
681
+ <loc>${SITE_URL}/${locale}</loc>
682
+ ${locales
683
+ .map((altLocale) => {
684
+ return `
685
+ <xhtml:link
686
+ rel="alternate"
687
+ hreflang="${altLocale}"
688
+ href="${SITE_URL}/${altLocale}"/>
689
+ `;
690
+ })
691
+ .join("")}
692
+ </url>
693
+ `;
694
+ })
695
+ .join("")}
696
+ </urlset>
697
+ `;
698
+ }
699
+
700
+ export const getServerSideProps: GetServerSideProps = async ({ res }) => {
701
+ const locales = ["en", "fr", "es"];
702
+ const sitemap = generateSiteMap(locales);
703
+
704
+ res.setHeader("Content-Type", "text/xml");
705
+ res.write(sitemap);
706
+ res.end();
707
+
708
+ return {
709
+ props: {},
710
+ };
711
+ };
712
+
713
+ export default function SiteMap() {
714
+ return null;
715
+ }
716
+ ```
717
+
718
+ ### (Optional) Step 11: Change the Language of Your Content
719
+
720
+ Implement a language switcher using next-i18next:
721
+
722
+ ```typescript fileName="src/components/LanguageSwitcher.tsx" codeFormat="typescript"
723
+ import { useRouter } from "next/router";
724
+ import Link from "next/link";
322
725
  import type { FC } from "react";
323
- import { useTranslation } from "react-i18next";
324
726
 
325
- const IndexPage: FC = () => {
326
- const { t } = useTranslation();
727
+ const LanguageSwitcher: FC = () => {
728
+ const router = useRouter();
729
+ const { locales, locale: currentLocale, asPath } = router;
327
730
 
328
731
  return (
329
732
  <div>
330
- <h1>{t("my-content.title")}</h1>
331
- <p>{t("my-content.description")}</p>
733
+ <p>Current Language: {currentLocale}</p>
734
+ <ul>
735
+ {locales?.map((locale) => (
736
+ <li key={locale}>
737
+ <Link href={asPath} locale={locale}>
738
+ <a style={{ fontWeight: locale === currentLocale ? "bold" : "normal" }}>
739
+ {locale.toUpperCase()}
740
+ </a>
741
+ </Link>
742
+ </li>
743
+ ))}
744
+ </ul>
332
745
  </div>
333
746
  );
334
747
  };
335
748
 
336
- export default IndexPage;
749
+ export default LanguageSwitcher;
337
750
  ```
338
751
 
339
- ```jsx fileName="src/components/myComponent/index.mjx" codeFormat="esm"
340
- import { useTranslation } from "react-i18next";
752
+ ```jsx fileName="src/components/LanguageSwitcher.mjx" codeFormat="esm"
753
+ import { useRouter } from "next/router";
754
+ import Link from "next/link";
341
755
 
342
- const IndexPage = () => {
343
- const { t } = useTranslation();
756
+ const LanguageSwitcher = () => {
757
+ const router = useRouter();
758
+ const { locales, locale: currentLocale, asPath } = router;
344
759
 
345
760
  return (
346
761
  <div>
347
- <h1>{t("my-content.title")}</h1>
348
- <p>{t("my-content.description")}</p>
762
+ <p>Current Language: {currentLocale}</p>
763
+ <ul>
764
+ {locales?.map((locale) => (
765
+ <li key={locale}>
766
+ <Link href={asPath} locale={locale}>
767
+ <a
768
+ style={{
769
+ fontWeight: locale === currentLocale ? "bold" : "normal",
770
+ }}
771
+ >
772
+ {locale.toUpperCase()}
773
+ </a>
774
+ </Link>
775
+ </li>
776
+ ))}
777
+ </ul>
349
778
  </div>
350
779
  );
351
780
  };
781
+
782
+ export default LanguageSwitcher;
352
783
  ```
353
784
 
354
- ```jsx fileName="src/components/myComponent/index.cjx" codeFormat="commonjs"
355
- const { useTranslation } = require("react-i18next");
785
+ ```jsx fileName="src/components/LanguageSwitcher.csx" codeFormat="commonjs"
786
+ const { useRouter } = require("next/router");
787
+ const Link = require("next/link");
356
788
 
357
- const IndexPage = () => {
358
- const { t } = useTranslation();
789
+ const LanguageSwitcher = () => {
790
+ const router = useRouter();
791
+ const { locales, locale: currentLocale, asPath } = router;
359
792
 
360
793
  return (
361
794
  <div>
362
- <h1>{t("my-content.title")}</h1>
363
- <p>{t("my-content.description")}</p>
795
+ <p>Current Language: {currentLocale}</p>
796
+ <ul>
797
+ {locales?.map((locale) => (
798
+ <li key={locale}>
799
+ <Link href={asPath} locale={locale}>
800
+ <a
801
+ style={{
802
+ fontWeight: locale === currentLocale ? "bold" : "normal",
803
+ }}
804
+ >
805
+ {locale.toUpperCase()}
806
+ </a>
807
+ </Link>
808
+ </li>
809
+ ))}
810
+ </ul>
364
811
  </div>
365
812
  );
366
813
  };
814
+
815
+ module.exports = LanguageSwitcher;
816
+ ```
817
+
818
+ ### (Optional) Step 12: Creating a Localized Link Component
819
+
820
+ Create a custom Link component that preserves locale context:
821
+
822
+ ```typescript fileName="src/components/LocalizedLink.tsx" codeFormat="typescript"
823
+ import Link, { LinkProps } from "next/link";
824
+ import { useRouter } from "next/router";
825
+ import type { FC, PropsWithChildren } from "react";
826
+
827
+ const LocalizedLink: FC<PropsWithChildren<LinkProps>> = ({
828
+ children,
829
+ href,
830
+ ...props
831
+ }) => {
832
+ const router = useRouter();
833
+ const { locale } = router;
834
+
835
+ return (
836
+ <Link href={href} locale={locale} {...props}>
837
+ {children}
838
+ </Link>
839
+ );
840
+ };
841
+
842
+ export default LocalizedLink;
843
+ ```
844
+
845
+ ```jsx fileName="src/components/LocalizedLink.mjx" codeFormat="esm"
846
+ import Link from "next/link";
847
+ import { useRouter } from "next/router";
848
+
849
+ const LocalizedLink = ({ children, href, ...props }) => {
850
+ const router = useRouter();
851
+ const { locale } = router;
852
+
853
+ return (
854
+ <Link href={href} locale={locale} {...props}>
855
+ {children}
856
+ </Link>
857
+ );
858
+ };
859
+
860
+ export default LocalizedLink;
861
+ ```
862
+
863
+ ```jsx fileName="src/components/LocalizedLink.csx" codeFormat="commonjs"
864
+ const Link = require("next/link");
865
+ const { useRouter } = require("next/router");
866
+
867
+ const LocalizedLink = ({ children, href, ...props }) => {
868
+ const router = useRouter();
869
+ const { locale } = router;
870
+
871
+ return (
872
+ <Link href={href} locale={locale} {...props}>
873
+ {children}
874
+ </Link>
875
+ );
876
+ };
877
+
878
+ module.exports = LocalizedLink;
367
879
  ```
880
+
881
+ ---
882
+
883
+ ## TypeScript Configuration
884
+
885
+ Intlayer generates TypeScript type definitions for your content. To enable these types:
886
+
887
+ ```json5 fileName="tsconfig.json"
888
+ {
889
+ "compilerOptions": {
890
+ // Your existing TypeScript config
891
+ },
892
+ "include": [
893
+ "src",
894
+ ".intlayer/**/*.ts", // Include Intlayer auto-generated types
895
+ ],
896
+ }
897
+ ```
898
+
899
+ This provides:
900
+
901
+ - **Autocompletion** for translation keys
902
+ - **Type checking** to catch missing translations
903
+ - **IntelliSense** support in your IDE
904
+
905
+ ---
906
+
907
+ ## Git Configuration
908
+
909
+ Exclude generated files from version control:
910
+
911
+ ```plaintext fileName=".gitignore"
912
+ # Ignore files generated by Intlayer
913
+ .intlayer
914
+ intl
915
+ ```
916
+
917
+ These files are automatically regenerated during the build process and don't need to be committed to your repository.
918
+
919
+ ---
920
+
921
+ ## VS Code Extension
922
+
923
+ Intlayer provides a VS Code extension to enhance your development experience:
924
+
925
+ [Install from VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=intlayer.intlayer-vs-code-extension)
926
+
927
+ Features:
928
+
929
+ - **Autocompletion** for content keys
930
+ - **Inline previews** of translations
931
+ - **Error detection** for missing translations
932
+ - **Quick actions** for managing content
933
+
934
+ For more details, see the [VS Code Extension documentation](https://intlayer.org/doc/vs-code-extension).
935
+
936
+ ---
937
+
938
+ ## Development Workflow
939
+
940
+ When working with this setup:
941
+
942
+ 1. **Declare content** in `*.content.*` files alongside your components
943
+ 2. **Build translations** with `intlayer build` (or let Next.js plugin auto-rebuild in dev mode)
944
+ 3. **Use translations** in components via `useTranslation` from next-i18next
945
+ 4. **Benefit from TypeScript** autocompletion and type checking
946
+
947
+ ---
948
+
949
+ ## Going Further
950
+
951
+ - **Visual Editor**: Consider implementing the [Intlayer Visual Editor](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_visual_editor.md) for non-technical team members
952
+ - **CMS Integration**: Externalize your content using the [Intlayer CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_CMS.md)
953
+ - **Full Intlayer Migration**: For new projects or major refactors, consider using [pure Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_with_nextjs_16.md) for the best developer experience
954
+
955
+ ---
956
+
957
+ ## Conclusion
958
+
959
+ By combining Intlayer's superior content declaration system with next-i18next's mature i18n infrastructure, you get:
960
+
961
+ ✅ **Better content organization** - Co-located with components
962
+ ✅ **Type safety** - Auto-generated TypeScript types
963
+ ✅ **Easier maintenance** - Single source of truth for translations
964
+ ✅ **Compatibility** - Works with existing i18next ecosystem
965
+ ✅ **Flexibility** - Gradual migration path from pure next-i18next
966
+
967
+ This approach is ideal for teams that want to improve their i18n workflow while maintaining compatibility with the i18next ecosystem.