@intlayer/docs 7.0.3 → 7.0.4
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.
- package/blog/ar/intlayer_with_i18next.md +68 -106
- package/blog/ar/intlayer_with_next-i18next.md +84 -288
- package/blog/ar/intlayer_with_next-intl.md +58 -337
- package/blog/ar/intlayer_with_react-i18next.md +68 -290
- package/blog/ar/intlayer_with_react-intl.md +63 -266
- package/blog/de/intlayer_with_i18next.md +77 -97
- package/blog/de/intlayer_with_next-i18next.md +69 -296
- package/blog/de/intlayer_with_next-intl.md +59 -340
- package/blog/de/intlayer_with_react-i18next.md +68 -290
- package/blog/de/intlayer_with_react-intl.md +62 -264
- package/blog/en/intlayer_with_i18next.md +67 -103
- package/blog/en/intlayer_with_next-i18next.md +69 -294
- package/blog/en/intlayer_with_next-intl.md +48 -300
- package/blog/en/intlayer_with_react-i18next.md +61 -289
- package/blog/en/intlayer_with_react-intl.md +61 -284
- package/blog/en/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/en-GB/intlayer_with_i18next.md +67 -103
- package/blog/en-GB/intlayer_with_next-i18next.md +71 -292
- package/blog/en-GB/intlayer_with_next-intl.md +58 -337
- package/blog/en-GB/intlayer_with_react-i18next.md +67 -289
- package/blog/en-GB/intlayer_with_react-intl.md +61 -264
- package/blog/es/intlayer_with_i18next.md +67 -103
- package/blog/es/intlayer_with_next-i18next.md +71 -296
- package/blog/es/intlayer_with_next-intl.md +57 -338
- package/blog/es/intlayer_with_react-i18next.md +68 -290
- package/blog/es/intlayer_with_react-intl.md +62 -265
- package/blog/fr/intlayer_with_i18next.md +66 -104
- package/blog/fr/intlayer_with_next-i18next.md +82 -285
- package/blog/fr/intlayer_with_next-intl.md +57 -338
- package/blog/fr/intlayer_with_react-i18next.md +67 -289
- package/blog/fr/intlayer_with_react-intl.md +61 -264
- package/blog/hi/intlayer_with_i18next.md +68 -104
- package/blog/hi/intlayer_with_next-i18next.md +74 -299
- package/blog/hi/intlayer_with_next-intl.md +57 -239
- package/blog/hi/intlayer_with_react-i18next.md +69 -291
- package/blog/hi/intlayer_with_react-intl.md +65 -268
- package/blog/id/intlayer_with_i18next.md +126 -0
- package/blog/id/intlayer_with_next-i18next.md +142 -0
- package/blog/id/intlayer_with_next-intl.md +113 -0
- package/blog/id/intlayer_with_react-i18next.md +124 -0
- package/blog/id/intlayer_with_react-intl.md +122 -0
- package/blog/it/intlayer_with_i18next.md +67 -103
- package/blog/it/intlayer_with_next-i18next.md +71 -296
- package/blog/it/intlayer_with_next-intl.md +57 -338
- package/blog/it/intlayer_with_react-i18next.md +68 -290
- package/blog/it/intlayer_with_react-intl.md +62 -265
- package/blog/ja/intlayer_with_i18next.md +68 -103
- package/blog/ja/intlayer_with_next-i18next.md +85 -283
- package/blog/ja/intlayer_with_next-intl.md +58 -336
- package/blog/ja/intlayer_with_react-i18next.md +68 -290
- package/blog/ja/intlayer_with_react-intl.md +62 -264
- package/blog/ko/intlayer_with_i18next.md +80 -96
- package/blog/ko/intlayer_with_next-i18next.md +85 -287
- package/blog/ko/intlayer_with_next-intl.md +68 -327
- package/blog/ko/intlayer_with_react-i18next.md +68 -290
- package/blog/ko/intlayer_with_react-intl.md +64 -266
- package/blog/pl/intlayer_with_i18next.md +126 -0
- package/blog/pl/intlayer_with_next-i18next.md +142 -0
- package/blog/pl/intlayer_with_next-intl.md +111 -0
- package/blog/pl/intlayer_with_react-i18next.md +124 -0
- package/blog/pl/intlayer_with_react-intl.md +122 -0
- package/blog/pt/intlayer_with_i18next.md +67 -103
- package/blog/pt/intlayer_with_next-i18next.md +72 -293
- package/blog/pt/intlayer_with_next-intl.md +57 -256
- package/blog/pt/intlayer_with_react-i18next.md +104 -78
- package/blog/pt/intlayer_with_react-intl.md +62 -266
- package/blog/ru/intlayer_with_i18next.md +66 -104
- package/blog/ru/intlayer_with_next-i18next.md +71 -296
- package/blog/ru/intlayer_with_next-intl.md +58 -337
- package/blog/ru/intlayer_with_react-i18next.md +68 -290
- package/blog/ru/intlayer_with_react-intl.md +62 -265
- package/blog/tr/intlayer_with_i18next.md +71 -107
- package/blog/tr/intlayer_with_next-i18next.md +72 -297
- package/blog/tr/intlayer_with_next-intl.md +58 -339
- package/blog/tr/intlayer_with_react-i18next.md +69 -291
- package/blog/tr/intlayer_with_react-intl.md +63 -285
- package/blog/vi/intlayer_with_i18next.md +126 -0
- package/blog/vi/intlayer_with_next-i18next.md +142 -0
- package/blog/vi/intlayer_with_next-intl.md +111 -0
- package/blog/vi/intlayer_with_react-i18next.md +124 -0
- package/blog/vi/intlayer_with_react-intl.md +122 -0
- package/blog/zh/intlayer_with_i18next.md +67 -102
- package/blog/zh/intlayer_with_next-i18next.md +72 -296
- package/blog/zh/intlayer_with_next-intl.md +58 -336
- package/blog/zh/intlayer_with_react-i18next.md +68 -290
- package/blog/zh/intlayer_with_react-intl.md +63 -106
- package/dist/cjs/generated/blog.entry.cjs +13 -1
- package/dist/cjs/generated/blog.entry.cjs.map +1 -1
- package/dist/cjs/generated/docs.entry.cjs +13 -1
- package/dist/cjs/generated/docs.entry.cjs.map +1 -1
- package/dist/cjs/generated/frequentQuestions.entry.cjs +13 -1
- package/dist/cjs/generated/frequentQuestions.entry.cjs.map +1 -1
- package/dist/cjs/generated/legal.entry.cjs +13 -1
- package/dist/cjs/generated/legal.entry.cjs.map +1 -1
- package/dist/esm/generated/blog.entry.mjs +13 -2
- package/dist/esm/generated/blog.entry.mjs.map +1 -1
- package/dist/esm/generated/docs.entry.mjs +13 -2
- package/dist/esm/generated/docs.entry.mjs.map +1 -1
- package/dist/esm/generated/frequentQuestions.entry.mjs +13 -2
- package/dist/esm/generated/frequentQuestions.entry.mjs.map +1 -1
- package/dist/esm/generated/legal.entry.mjs +13 -2
- package/dist/esm/generated/legal.entry.mjs.map +1 -1
- package/dist/types/generated/blog.entry.d.ts.map +1 -1
- package/dist/types/generated/docs.entry.d.ts.map +1 -1
- package/dist/types/generated/frequentQuestions.entry.d.ts.map +1 -1
- package/dist/types/generated/legal.entry.d.ts.map +1 -1
- package/docs/ar/plugins/sync-json.md +244 -0
- package/docs/de/plugins/sync-json.md +244 -0
- package/docs/de/releases/v7.md +1 -18
- package/docs/en/CI_CD.md +1 -1
- package/docs/en/configuration.md +1 -1
- package/docs/en/formatters.md +1 -1
- package/docs/en/how_works_intlayer.md +1 -1
- package/docs/en/intlayer_CMS.md +1 -1
- package/docs/en/intlayer_cli.md +26 -1
- package/docs/en/intlayer_with_nextjs_14.md +3 -1
- package/docs/en/intlayer_with_nextjs_15.md +3 -1
- package/docs/en/intlayer_with_nextjs_16.md +3 -1
- package/docs/en/intlayer_with_nextjs_page_router.md +1 -1
- package/docs/en/intlayer_with_nuxt.md +1 -1
- package/docs/en/intlayer_with_react_native+expo.md +1 -1
- package/docs/en/intlayer_with_react_router_v7.md +1 -1
- package/docs/en/intlayer_with_tanstack.md +1 -1
- package/docs/en/intlayer_with_vite+preact.md +1 -1
- package/docs/en/intlayer_with_vite+react.md +1 -1
- package/docs/en/intlayer_with_vite+solid.md +1 -1
- package/docs/en/intlayer_with_vite+svelte.md +1 -1
- package/docs/en/intlayer_with_vite+vue.md +1 -1
- package/docs/en/plugins/sync-json.md +1 -1
- package/docs/en/roadmap.md +1 -1
- package/docs/en-GB/plugins/sync-json.md +244 -0
- package/docs/es/plugins/sync-json.md +244 -0
- package/docs/es/releases/v7.md +1 -18
- package/docs/fr/intlayer_with_nextjs_16.md +2 -51
- package/docs/fr/plugins/sync-json.md +244 -0
- package/docs/fr/releases/v7.md +1 -18
- package/docs/hi/intlayer_with_nextjs_16.md +3 -2
- package/docs/hi/plugins/sync-json.md +244 -0
- package/docs/id/plugins/sync-json.md +244 -0
- package/docs/id/releases/v7.md +1 -18
- package/docs/it/plugins/sync-json.md +244 -0
- package/docs/it/releases/v7.md +1 -18
- package/docs/ja/intlayer_with_nextjs_16.md +44 -205
- package/docs/ja/plugins/sync-json.md +244 -0
- package/docs/ja/releases/v7.md +1 -18
- package/docs/ko/plugins/sync-json.md +244 -0
- package/docs/ko/releases/v7.md +1 -18
- package/docs/pl/plugins/sync-json.md +244 -0
- package/docs/pt/intlayer_with_nextjs_16.md +1 -52
- package/docs/pt/plugins/sync-json.md +244 -0
- package/docs/ru/plugins/sync-json.md +244 -0
- package/docs/tr/plugins/sync-json.md +245 -0
- package/docs/vi/plugins/sync-json.md +244 -0
- package/docs/zh/plugins/sync-json.md +244 -0
- package/package.json +14 -14
- package/src/generated/blog.entry.ts +26 -3
- package/src/generated/docs.entry.ts +26 -3
- package/src/generated/frequentQuestions.entry.ts +26 -3
- package/src/generated/legal.entry.ts +26 -3
|
@@ -1,345 +1,122 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2025-01-02
|
|
3
|
-
updatedAt: 2025-
|
|
4
|
-
title:
|
|
5
|
-
description:
|
|
3
|
+
updatedAt: 2025-10-29
|
|
4
|
+
title: How to automate your react-intl JSON translations using Intlayer
|
|
5
|
+
description: Automate your JSON translations with Intlayer and react-intl for enhanced internationalization in React applications.
|
|
6
6
|
keywords:
|
|
7
7
|
- react-intl
|
|
8
8
|
- Intlayer
|
|
9
9
|
- Internationalization
|
|
10
10
|
- Blog
|
|
11
|
-
-
|
|
11
|
+
- i18n
|
|
12
12
|
- JavaScript
|
|
13
13
|
- React
|
|
14
|
+
- FormatJS
|
|
14
15
|
slugs:
|
|
15
16
|
- blog
|
|
16
17
|
- intlayer-with-react-intl
|
|
18
|
+
history:
|
|
19
|
+
- version: 7.0.0
|
|
20
|
+
date: 2025-10-29
|
|
21
|
+
changes: Change to syncJSON plugin
|
|
17
22
|
---
|
|
18
23
|
|
|
19
|
-
#
|
|
24
|
+
# How to automate your react-intl JSON translations using Intlayer
|
|
20
25
|
|
|
21
|
-
|
|
26
|
+
## What is Intlayer?
|
|
22
27
|
|
|
23
|
-
|
|
28
|
+
**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 React applications.
|
|
24
29
|
|
|
25
|
-
|
|
26
|
-
- **react-intl** provides React components and hooks (like `<FormattedMessage>` and `useIntl()`) to display localized strings.
|
|
30
|
+
See a concrete comparison with react-intl in our [react-i18next vs. react-intl vs. Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/blog/en/react-i18next_vs_react-intl_vs_intlayer.md) blog post.
|
|
27
31
|
|
|
28
|
-
|
|
32
|
+
## Why Combine Intlayer with react-intl?
|
|
29
33
|
|
|
30
|
-
|
|
34
|
+
While Intlayer provides an excellent standalone i18n solution (see our [React integration guide](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_with_vite+react.md)), you might want to combine it with react-intl for several reasons:
|
|
31
35
|
|
|
32
|
-
|
|
36
|
+
1. **Existing codebase**: You have an established react-intl implementation and want to gradually migrate to Intlayer's improved developer experience.
|
|
37
|
+
2. **Legacy requirements**: Your project requires compatibility with existing react-intl plugins or workflows.
|
|
38
|
+
3. **Team familiarity**: Your team is comfortable with react-intl but wants better content management.
|
|
33
39
|
|
|
34
|
-
|
|
35
|
-
Intlayer content declaration files can live alongside your React components, preventing “orphaned” translations if components are moved or removed. For example:
|
|
40
|
+
**For that, Intlayer can be implemented as an adapter for react-intl to help automating your JSON translations in CLI or CI/CD pipelines, testing your translations, and more.**
|
|
36
41
|
|
|
37
|
-
|
|
38
|
-
.
|
|
39
|
-
└── src
|
|
40
|
-
└── components
|
|
41
|
-
└── MyComponent
|
|
42
|
-
├── index.content.ts # Intlayer content declaration
|
|
43
|
-
└── index.tsx # React component
|
|
44
|
-
```
|
|
42
|
+
This guide shows you how to leverage Intlayer's superior content declaration system while maintaining compatibility with react-intl.
|
|
45
43
|
|
|
46
|
-
|
|
47
|
-
Each content declaration file collects all translations needed by a component. This is particularly helpful in TypeScript projects: missing translations can be caught at **compile time**.
|
|
44
|
+
## Table of Contents
|
|
48
45
|
|
|
49
|
-
|
|
50
|
-
Whenever you add or update translations, Intlayer regenerates message JSON files. You can then pass these into react-intl’s `<IntlProvider>`.
|
|
46
|
+
<TOC/>
|
|
51
47
|
|
|
52
|
-
|
|
48
|
+
## Step-by-Step Guide to Set Up Intlayer with react-intl
|
|
53
49
|
|
|
54
|
-
|
|
50
|
+
### Step 1: Install Dependencies
|
|
55
51
|
|
|
56
|
-
|
|
52
|
+
Install the necessary packages:
|
|
57
53
|
|
|
58
|
-
```bash
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
```bash packageManager="npm"
|
|
55
|
+
npm install intlayer @intlayer/sync-json-plugin
|
|
56
|
+
```
|
|
61
57
|
|
|
62
|
-
|
|
63
|
-
|
|
58
|
+
```bash packageManager="pnpm"
|
|
59
|
+
pnpm add intlayer @intlayer/sync-json-plugin
|
|
60
|
+
```
|
|
64
61
|
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
```bash packageManager="yarn"
|
|
63
|
+
yarn add intlayer @intlayer/sync-json-plugin
|
|
67
64
|
```
|
|
68
65
|
|
|
69
|
-
|
|
66
|
+
**Package descriptions:**
|
|
70
67
|
|
|
71
|
-
- **intlayer**: Core
|
|
72
|
-
-
|
|
68
|
+
- **intlayer**: Core library for internationalization management, content declaration, and building
|
|
69
|
+
- **@intlayer/sync-json-plugin**: Plugin to export Intlayer content declarations to react-intl compatible JSON format
|
|
73
70
|
|
|
74
|
-
|
|
71
|
+
### Step 2: Implement the Intlayer plugin to wrap the JSON
|
|
75
72
|
|
|
76
|
-
|
|
73
|
+
Create an Intlayer configuration file to define your supported locales:
|
|
77
74
|
|
|
78
|
-
|
|
75
|
+
**If you want to also export JSON dictionaries for react-intl**, add the `syncJSON` plugin:
|
|
79
76
|
|
|
80
|
-
```typescript
|
|
77
|
+
```typescript fileName="intlayer.config.ts"
|
|
81
78
|
import { Locales, type IntlayerConfig } from "intlayer";
|
|
79
|
+
import { syncJSON } from "@intlayer/sync-json-plugin";
|
|
82
80
|
|
|
83
81
|
const config: IntlayerConfig = {
|
|
84
82
|
internationalization: {
|
|
85
|
-
// Add as many locales as you wish
|
|
86
83
|
locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
|
|
87
84
|
defaultLocale: Locales.ENGLISH,
|
|
88
85
|
},
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
reactIntlMessagesDir: "./react-intl/messages",
|
|
95
|
-
},
|
|
86
|
+
plugins: [
|
|
87
|
+
syncJSON({
|
|
88
|
+
source: ({ key, locale }) => `./intl/messages/${locale}/${key}.json`,
|
|
89
|
+
}),
|
|
90
|
+
],
|
|
96
91
|
};
|
|
97
92
|
|
|
98
93
|
export default config;
|
|
99
94
|
```
|
|
100
95
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
---
|
|
104
|
-
|
|
105
|
-
## Creating Your Intlayer Dictionarys
|
|
106
|
-
|
|
107
|
-
Intlayer scans your codebase (by default, under `./src`) for files matching `*.content.{ts,tsx,js,jsx,mjs,mjx,cjs,cjx,json}`.
|
|
108
|
-
Here’s a **TypeScript** example:
|
|
109
|
-
|
|
110
|
-
```typescript title="src/components/MyComponent/index.content.ts"
|
|
111
|
-
import { t, type Dictionary } from "intlayer";
|
|
112
|
-
|
|
113
|
-
const content = {
|
|
114
|
-
// "key" becomes the top-level message key in your react-intl JSON file
|
|
115
|
-
key: "my-component",
|
|
116
|
-
|
|
117
|
-
content: {
|
|
118
|
-
// Each call to t() declares a translatable field
|
|
119
|
-
helloWorld: t({
|
|
120
|
-
en: "Hello World",
|
|
121
|
-
es: "Hola Mundo",
|
|
122
|
-
fr: "Bonjour le monde",
|
|
123
|
-
}),
|
|
124
|
-
description: t({
|
|
125
|
-
en: "This is a description",
|
|
126
|
-
fr: "Ceci est une description",
|
|
127
|
-
es: "Esta es una descripción",
|
|
128
|
-
}),
|
|
129
|
-
},
|
|
130
|
-
} satisfies Dictionary;
|
|
131
|
-
|
|
132
|
-
export default content;
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
If you prefer JSON or different JS flavors (`.cjs`, `.mjs`), the structure is largely the same see [Intlayer docs on content declaration](https://intlayer.org/en/doc/concept/content).
|
|
136
|
-
|
|
137
|
-
---
|
|
138
|
-
|
|
139
|
-
## Building the react-intl Messages
|
|
140
|
-
|
|
141
|
-
To generate the actual message JSON files for **react-intl**, run:
|
|
142
|
-
|
|
143
|
-
```bash
|
|
144
|
-
# with npm
|
|
145
|
-
npx intlayer dictionaries build
|
|
146
|
-
|
|
147
|
-
# with yarn
|
|
148
|
-
yarn intlayer build
|
|
149
|
-
|
|
150
|
-
# with pnpm
|
|
151
|
-
pnpm intlayer build
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
This scans all `*.content.*` files, compiles them, and writes the results to the directory specified in your **`intlayer.config.ts`** in this example, `./react-intl/messages`.
|
|
155
|
-
A typical output might look like:
|
|
156
|
-
|
|
157
|
-
```bash
|
|
158
|
-
.
|
|
159
|
-
└── react-intl
|
|
160
|
-
└── messages
|
|
161
|
-
├── en.json
|
|
162
|
-
├── fr.json
|
|
163
|
-
└── es.json
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
Each file is a JSON object whose **top-level keys** correspond to each **`content.key`** from your declarations. The **sub-keys** (like `helloWorld`) reflect the translations declared within that content item.
|
|
167
|
-
|
|
168
|
-
For example, the **en.json** might look like:
|
|
169
|
-
|
|
170
|
-
```json fileName="react-intl/messages/en/my-component.json"
|
|
171
|
-
{
|
|
172
|
-
"helloWorld": "Hello World",
|
|
173
|
-
"description": "This is a description"
|
|
174
|
-
}
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
---
|
|
178
|
-
|
|
179
|
-
## Initializing react-intl in Your React App
|
|
180
|
-
|
|
181
|
-
### 1. Load the Generated Messages
|
|
182
|
-
|
|
183
|
-
Where you configure your app’s root component (e.g., `src/main.tsx` or `src/index.tsx`), you’ll need to:
|
|
184
|
-
|
|
185
|
-
1. **Import** the generated message files (either statically or dynamically).
|
|
186
|
-
2. **Provide** them to `<IntlProvider>` from `react-intl`.
|
|
187
|
-
|
|
188
|
-
A simple approach is to import them **statically**:
|
|
189
|
-
|
|
190
|
-
```typescript title="src/index.tsx"
|
|
191
|
-
import React from "react";
|
|
192
|
-
import ReactDOM from "react-dom/client";
|
|
193
|
-
import { IntlProvider } from "react-intl";
|
|
194
|
-
import App from "./App";
|
|
195
|
-
|
|
196
|
-
// Import the JSON files from the build output.
|
|
197
|
-
// Alternatively, you can import dynamically based on the user's chosen locale.
|
|
198
|
-
import en from "../react-intl/messages/en.json";
|
|
199
|
-
import fr from "../react-intl/messages/fr.json";
|
|
200
|
-
import es from "../react-intl/messages/es.json";
|
|
96
|
+
The `syncJSON` plugin will automatically wrap the JSON. It will read and write the JSON files without changing the content architecture.
|
|
201
97
|
|
|
98
|
+
If you want to make coexist that JSON with intlayer content declaration files (`.content` files), Intlayer will proceed this way:
|
|
202
99
|
|
|
100
|
+
1. load both JSON and content declaration files and transform them into a intlayer dictionary.
|
|
101
|
+
2. if there is conflicts between the JSON and the content declaration files, Intlayer will process to the merge of that all dictionaries. Depending of the priority of the plugins, and the one of the content declaration file (all are configurable).
|
|
203
102
|
|
|
204
|
-
|
|
205
|
-
const messages = import.meta.glob("../react-intl/messages/**/*.json", {
|
|
206
|
-
eager: true,
|
|
207
|
-
});
|
|
103
|
+
If changes are made using the CLI to translate the JSON, or using the CMS, Intlayer will update the JSON file with the new translations.
|
|
208
104
|
|
|
209
|
-
|
|
210
|
-
const messagesRecord: Record<string, Record<string, any>> = {};
|
|
105
|
+
To see more details about the `syncJSON` plugin, please refer to the [syncJSON plugin documentation](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/plugins/sync-json.md).
|
|
211
106
|
|
|
212
|
-
|
|
213
|
-
// Extract locale and namespace from the file path
|
|
214
|
-
const [, locale, namespace] = path.match(/messages\/(\w+)\/(.+?)\.json$/) ?? [];
|
|
215
|
-
if (locale && namespace) {
|
|
216
|
-
messagesRecord[locale] = messagesRecord[locale] ?? {};
|
|
217
|
-
messagesRecord[locale][namespace] = module.default; // Assign JSON content
|
|
218
|
-
}
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
// Merge namespaces for each locale
|
|
222
|
-
const mergeMessages = (locale: string) =>
|
|
223
|
-
Object.values(messagesRecord[locale] ?? {}).reduce(
|
|
224
|
-
(acc, namespaceMessages) => ({ ...acc, ...namespaceMessages }),
|
|
225
|
-
{}
|
|
226
|
-
);
|
|
227
|
-
|
|
228
|
-
// If you have a mechanism to detect the user's language, set it here.
|
|
229
|
-
// For simplicity, let's pick English.
|
|
230
|
-
const locale = "en";
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
|
|
234
|
-
<React.StrictMode>
|
|
235
|
-
<IntlProvider locale={locale} messages={mergeMessages(locale)}>
|
|
236
|
-
<App />
|
|
237
|
-
</IntlProvider>
|
|
238
|
-
</React.StrictMode>
|
|
239
|
-
);
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
> **Tip**: For real projects, you might:
|
|
243
|
-
>
|
|
244
|
-
> - Dynamically load the JSON messages at runtime.
|
|
245
|
-
> - Use environment-based, browser-based, or user account–based locale detection.
|
|
246
|
-
|
|
247
|
-
### 2. Use `<FormattedMessage>` or `useIntl()`
|
|
248
|
-
|
|
249
|
-
Once your messages are loaded into `<IntlProvider>`, any child component can use react-intl to access localized strings. There are two main approaches:
|
|
250
|
-
|
|
251
|
-
- **`<FormattedMessage>`** component
|
|
252
|
-
- **`useIntl()`** hook
|
|
253
|
-
|
|
254
|
-
---
|
|
255
|
-
|
|
256
|
-
## Using Translations in React Components
|
|
257
|
-
|
|
258
|
-
### Approach A: `<FormattedMessage>`
|
|
259
|
-
|
|
260
|
-
For quick inline usage:
|
|
261
|
-
|
|
262
|
-
```tsx title="src/components/MyComponent/index.tsx"
|
|
263
|
-
import React from "react";
|
|
264
|
-
import { FormattedMessage } from "react-intl";
|
|
265
|
-
|
|
266
|
-
export default function MyComponent() {
|
|
267
|
-
return (
|
|
268
|
-
<div>
|
|
269
|
-
<h1>
|
|
270
|
-
{/* “my-component.helloWorld” references the key from en.json, fr.json, etc. */}
|
|
271
|
-
<FormattedMessage id="my-component.helloWorld" />
|
|
272
|
-
</h1>
|
|
273
|
-
|
|
274
|
-
<p>
|
|
275
|
-
<FormattedMessage id="my-component.description" />
|
|
276
|
-
</p>
|
|
277
|
-
</div>
|
|
278
|
-
);
|
|
279
|
-
}
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
> The **`id`** prop in `<FormattedMessage>` must match the **top-level key** (`my-component`) plus any sub-keys (`helloWorld`).
|
|
283
|
-
|
|
284
|
-
### Approach B: `useIntl()`
|
|
285
|
-
|
|
286
|
-
For more dynamic usage:
|
|
287
|
-
|
|
288
|
-
```tsx title="src/components/MyComponent/index.tsx"
|
|
289
|
-
import React from "react";
|
|
290
|
-
import { useIntl } from "react-intl";
|
|
291
|
-
|
|
292
|
-
export default function MyComponent() {
|
|
293
|
-
const intl = useIntl();
|
|
294
|
-
|
|
295
|
-
return (
|
|
296
|
-
<div>
|
|
297
|
-
<h1>{intl.formatMessage({ id: "my-component.helloWorld" })}</h1>
|
|
298
|
-
<p>{intl.formatMessage({ id: "my-component.description" })}</p>
|
|
299
|
-
</div>
|
|
300
|
-
);
|
|
301
|
-
}
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
Either approach is valid choose whichever style suits your app.
|
|
305
|
-
|
|
306
|
-
---
|
|
307
|
-
|
|
308
|
-
## Updating or Adding New Translations
|
|
309
|
-
|
|
310
|
-
1. **Add or modify** content in any `*.content.*` file.
|
|
311
|
-
2. Rerun `intlayer build` to regenerate the JSON files under `./react-intl/messages`.
|
|
312
|
-
3. React (and react-intl) will pick up the updates next time you rebuild or reload your application.
|
|
313
|
-
|
|
314
|
-
---
|
|
315
|
-
|
|
316
|
-
## TypeScript Integration (Optional)
|
|
317
|
-
|
|
318
|
-
If you’re using TypeScript, Intlayer can **generate type definitions** for your translations.
|
|
107
|
+
## Git Configuration
|
|
319
108
|
|
|
320
|
-
|
|
109
|
+
It's recommended to ignore auto-generated Intlayer files:
|
|
321
110
|
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
// ...
|
|
326
|
-
},
|
|
327
|
-
"include": ["src", "types"],
|
|
328
|
-
}
|
|
111
|
+
```plaintext fileName=".gitignore"
|
|
112
|
+
# Ignore files generated by Intlayer
|
|
113
|
+
.intlayer
|
|
329
114
|
```
|
|
330
115
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
---
|
|
334
|
-
|
|
335
|
-
## Git Configuration
|
|
116
|
+
These files can be regenerated during your build process and don't need to be committed to version control.
|
|
336
117
|
|
|
337
|
-
|
|
118
|
+
### VS Code Extension
|
|
338
119
|
|
|
339
|
-
|
|
340
|
-
# Ignore intlayer build artifacts
|
|
341
|
-
.intlayer
|
|
342
|
-
react-intl
|
|
343
|
-
```
|
|
120
|
+
For improved developer experience, install the official **Intlayer VS Code Extension**:
|
|
344
121
|
|
|
345
|
-
|
|
122
|
+
[Install from the VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=intlayer.intlayer-vs-code-extension)
|
|
@@ -27,7 +27,7 @@ This is not a full tutorial. It’s a comparison to help you pick.
|
|
|
27
27
|
|
|
28
28
|
We focus on **Next.js 13+ App Router** (with **React Server Components**) and evaluate:
|
|
29
29
|
|
|
30
|
-
<TOC
|
|
30
|
+
<TOC/>
|
|
31
31
|
|
|
32
32
|
> **tl;dr**: All three can localize a Next.js app. If you want **component-scoped content**, **strict TypeScript types**, **build-time missing-key checks**, **tree-shaken dictionaries**, and **first-class App Router + SEO helpers**, **Intlayer** is the most complete, modern choice.
|
|
33
33
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2024-12-24
|
|
3
|
-
updatedAt: 2025-
|
|
4
|
-
title:
|
|
5
|
-
description:
|
|
3
|
+
updatedAt: 2025-10-29
|
|
4
|
+
title: How to automate your i18next JSON translations using Intlayer
|
|
5
|
+
description: Automate your JSON translations with Intlayer and i18next for enhanced internationalisation in JavaScript applications.
|
|
6
6
|
keywords:
|
|
7
7
|
- Intlayer
|
|
8
8
|
- i18next
|
|
@@ -14,149 +14,113 @@ keywords:
|
|
|
14
14
|
- Next.js
|
|
15
15
|
- JavaScript
|
|
16
16
|
- TypeScript
|
|
17
|
+
- Migration
|
|
18
|
+
- Integration
|
|
17
19
|
slugs:
|
|
18
20
|
- blog
|
|
19
21
|
- intlayer-with-i18next
|
|
22
|
+
history:
|
|
23
|
+
- version: 7.0.0
|
|
24
|
+
date: 2025-10-29
|
|
25
|
+
changes: Change to syncJSON plugin
|
|
20
26
|
---
|
|
21
27
|
|
|
22
|
-
#
|
|
28
|
+
# How to automate your i18next JSON translations using Intlayer
|
|
23
29
|
|
|
24
|
-
|
|
30
|
+
## What is Intlayer?
|
|
25
31
|
|
|
26
|
-
Intlayer is
|
|
32
|
+
**Intlayer** is an innovative, open-source internationalisation library designed to address the shortcomings of traditional i18n solutions. It offers a modern approach to content management in JavaScript applications.
|
|
27
33
|
|
|
28
|
-
|
|
34
|
+
See a concrete comparison with i18next in 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.
|
|
29
35
|
|
|
30
|
-
|
|
36
|
+
## Why Combine Intlayer with i18next?
|
|
31
37
|
|
|
32
|
-
|
|
38
|
+
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 i18next for several reasons:
|
|
33
39
|
|
|
34
|
-
|
|
35
|
-
|
|
40
|
+
1. **Existing codebase**: You have an established i18next implementation and want to gradually migrate to Intlayer's improved developer experience.
|
|
41
|
+
2. **Legacy requirements**: Your project requires compatibility with existing i18next plugins or workflows.
|
|
42
|
+
3. **Team familiarity**: Your team is comfortable with i18next but wants better content management.
|
|
36
43
|
|
|
37
|
-
|
|
44
|
+
**For that, Intlayer can be implemented as an adapter for i18next to help automate your JSON translations in CLI or CI/CD pipelines, test your translations, and more.**
|
|
38
45
|
|
|
39
|
-
|
|
46
|
+
This guide shows you how to leverage Intlayer's superior content declaration system while maintaining compatibility with i18next.
|
|
40
47
|
|
|
41
|
-
|
|
48
|
+
## Table of Contents
|
|
42
49
|
|
|
43
|
-
|
|
50
|
+
<TOC/>
|
|
44
51
|
|
|
45
|
-
|
|
52
|
+
## Step-by-Step Guide to Set Up Intlayer with i18next
|
|
46
53
|
|
|
47
|
-
|
|
54
|
+
### Step 1: Install Dependencies
|
|
48
55
|
|
|
49
|
-
|
|
56
|
+
Install the necessary packages:
|
|
50
57
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
58
|
+
```bash packageManager="npm"
|
|
59
|
+
npm install intlayer @intlayer/sync-json-plugin
|
|
60
|
+
```
|
|
54
61
|
|
|
55
|
-
|
|
62
|
+
```bash packageManager="pnpm"
|
|
63
|
+
pnpm add intlayer @intlayer/sync-json-plugin
|
|
64
|
+
```
|
|
56
65
|
|
|
57
|
-
|
|
66
|
+
```bash packageManager="yarn"
|
|
67
|
+
yarn add intlayer @intlayer/sync-json-plugin
|
|
68
|
+
```
|
|
58
69
|
|
|
59
|
-
|
|
70
|
+
**Package descriptions:**
|
|
60
71
|
|
|
61
|
-
|
|
72
|
+
- **intlayer**: Core library for internationalisation management, content declaration, and building
|
|
73
|
+
- **@intlayer/sync-json-plugin**: Plugin to export Intlayer content declarations to i18next compatible JSON format
|
|
62
74
|
|
|
63
|
-
|
|
64
|
-
import { Locales, type IntlayerConfig } from "intlayer";
|
|
75
|
+
### Step 2: Implement the Intlayer plugin to wrap the JSON
|
|
65
76
|
|
|
66
|
-
|
|
67
|
-
content: {
|
|
68
|
-
// Indicate that Intlayer will export both Intlayer and i18next dictionaries
|
|
69
|
-
dictionaryOutput: ["intlayer", "i18next"],
|
|
70
|
-
// Relative path from the project root to the directory where i18n dictionaries will be exported
|
|
71
|
-
i18nextResourcesDir: "./i18next/dictionaries",
|
|
72
|
-
},
|
|
73
|
-
};
|
|
77
|
+
Create an Intlayer configuration file to define your supported locales:
|
|
74
78
|
|
|
75
|
-
export
|
|
76
|
-
```
|
|
79
|
+
**If you want to also export JSON dictionaries for i18next**, add the `syncJSON` plugin:
|
|
77
80
|
|
|
78
|
-
```
|
|
79
|
-
import { Locales } from "intlayer";
|
|
81
|
+
```typescript fileName="intlayer.config.ts"
|
|
82
|
+
import { Locales, type IntlayerConfig } from "intlayer";
|
|
83
|
+
import { syncJSON } from "@intlayer/sync-json-plugin";
|
|
80
84
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
dictionaryOutput: ["intlayer", "i18next"],
|
|
86
|
-
// Relative path from the project root to the directory where i18n dictionaries will be exported
|
|
87
|
-
i18nextResourcesDir: "./i18next/dictionaries",
|
|
85
|
+
const config: IntlayerConfig = {
|
|
86
|
+
internationalization: {
|
|
87
|
+
locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
|
|
88
|
+
defaultLocale: Locales.ENGLISH,
|
|
88
89
|
},
|
|
90
|
+
plugins: [
|
|
91
|
+
syncJSON({
|
|
92
|
+
source: ({ key, locale }) => `./intl/messages/${locale}/${key}.json`,
|
|
93
|
+
}),
|
|
94
|
+
],
|
|
89
95
|
};
|
|
90
96
|
|
|
91
97
|
export default config;
|
|
92
98
|
```
|
|
93
99
|
|
|
94
|
-
|
|
95
|
-
const { Locales } = require("intlayer");
|
|
96
|
-
|
|
97
|
-
/** @type {import('intlayer').IntlayerConfig} */
|
|
98
|
-
const config = {
|
|
99
|
-
content: {
|
|
100
|
-
// Indicate that Intlayer will export both Intlayer and i18next dictionaries
|
|
101
|
-
dictionaryOutput: ["intlayer", "i18next"],
|
|
102
|
-
// Relative path from the project root to the directory where i18n dictionaries will be exported
|
|
103
|
-
i18nextResourcesDir: "./i18next/dictionaries",
|
|
104
|
-
},
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
module.exports = config;
|
|
108
|
-
```
|
|
100
|
+
The `syncJSON` plugin will automatically wrap the JSON. It will read and write the JSON files without changing the content architecture.
|
|
109
101
|
|
|
110
|
-
|
|
102
|
+
If you want to make that JSON coexist with Intlayer content declaration files (`.content` files), Intlayer will proceed as follows:
|
|
111
103
|
|
|
112
|
-
|
|
104
|
+
1. load both JSON and content declaration files and transform them into an Intlayer dictionary.
|
|
105
|
+
2. if there are conflicts between the JSON and the content declaration files, Intlayer will proceed to merge all those dictionaries. This depends on the priority of the plugins and that of the content declaration file (all are configurable).
|
|
113
106
|
|
|
114
|
-
|
|
107
|
+
If changes are made using the CLI to translate the JSON, or using the CMS, Intlayer will update the JSON file with the new translations.
|
|
115
108
|
|
|
116
|
-
|
|
117
|
-
// i18n/client.ts
|
|
109
|
+
## Git Configuration
|
|
118
110
|
|
|
119
|
-
|
|
120
|
-
import resourcesToBackend from "i18next-resources-to-backend";
|
|
111
|
+
It is recommended to ignore auto-generated Intlayer files:
|
|
121
112
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
resourcesToBackend(
|
|
126
|
-
(language: string, namespace: string) =>
|
|
127
|
-
import(`../i18next/dictionaries/${language}/${namespace}.json`)
|
|
128
|
-
)
|
|
129
|
-
);
|
|
113
|
+
```plaintext fileName=".gitignore"
|
|
114
|
+
# Ignore files generated by Intlayer
|
|
115
|
+
.intlayer
|
|
130
116
|
```
|
|
131
117
|
|
|
132
|
-
|
|
133
|
-
// i18n/client.mjs
|
|
118
|
+
These files can be regenerated during your build process and do not need to be committed to version control.
|
|
134
119
|
|
|
135
|
-
|
|
136
|
-
import resourcesToBackend from "i18next-resources-to-backend";
|
|
120
|
+
### VS Code Extension
|
|
137
121
|
|
|
138
|
-
|
|
139
|
-
// Your i18next configuration
|
|
140
|
-
.use(
|
|
141
|
-
resourcesToBackend(
|
|
142
|
-
(language, namespace) =>
|
|
143
|
-
import(`../i18next/dictionaries/${language}/${namespace}.json`)
|
|
144
|
-
)
|
|
145
|
-
);
|
|
146
|
-
```
|
|
122
|
+
For an improved developer experience, install the official **Intlayer VS Code Extension**:
|
|
147
123
|
|
|
148
|
-
|
|
149
|
-
// i18n/client.cjs
|
|
124
|
+
[Install from the VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=intlayer.intlayer-vs-code-extension)
|
|
150
125
|
|
|
151
|
-
|
|
152
|
-
const resourcesToBackend = require("i18next-resources-to-backend");
|
|
153
|
-
|
|
154
|
-
i18next
|
|
155
|
-
// Your i18next configuration
|
|
156
|
-
.use(
|
|
157
|
-
resourcesToBackend(
|
|
158
|
-
(language, namespace) =>
|
|
159
|
-
import(`../i18next/dictionaries/${language}/${namespace}.json`)
|
|
160
|
-
)
|
|
161
|
-
);
|
|
162
|
-
```
|
|
126
|
+
[Install from the VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=intlayer.intlayer-vs-code-extension)
|