@intlayer/docs 5.7.7 → 5.8.0-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.
- package/blog/ar/intlayer_with_next-i18next.md +3 -4
- package/blog/ar/intlayer_with_next-intl.md +3 -4
- package/blog/ar/intlayer_with_react-i18next.md +1 -1
- package/blog/ar/intlayer_with_react-intl.md +1 -1
- package/blog/de/intlayer_with_next-i18next.md +3 -4
- package/blog/de/intlayer_with_react-intl.md +1 -1
- package/blog/en/intlayer_with_next-i18next.md +3 -4
- package/blog/en/intlayer_with_next-intl.md +3 -4
- package/blog/en/intlayer_with_react-i18next.md +1 -1
- package/blog/en/intlayer_with_react-intl.md +1 -1
- package/blog/en-GB/intlayer_with_next-i18next.md +3 -4
- package/blog/en-GB/intlayer_with_next-intl.md +3 -4
- package/blog/en-GB/intlayer_with_react-i18next.md +1 -1
- package/blog/en-GB/intlayer_with_react-intl.md +1 -1
- package/blog/es/intlayer_with_next-i18next.md +3 -4
- package/blog/es/intlayer_with_next-intl.md +3 -4
- package/blog/es/intlayer_with_react-i18next.md +1 -1
- package/blog/es/intlayer_with_react-intl.md +1 -1
- package/blog/fr/intlayer_with_next-i18next.md +3 -4
- package/blog/fr/intlayer_with_next-intl.md +3 -4
- package/blog/fr/intlayer_with_react-i18next.md +1 -1
- package/blog/fr/intlayer_with_react-intl.md +1 -1
- package/blog/hi/intlayer_with_next-i18next.md +3 -4
- package/blog/hi/intlayer_with_next-intl.md +3 -4
- package/blog/hi/intlayer_with_react-i18next.md +1 -1
- package/blog/hi/intlayer_with_react-intl.md +1 -1
- package/blog/it/intlayer_with_next-i18next.md +3 -4
- package/blog/it/intlayer_with_next-intl.md +3 -4
- package/blog/it/intlayer_with_react-i18next.md +1 -1
- package/blog/it/intlayer_with_react-intl.md +1 -1
- package/blog/ja/intlayer_with_next-i18next.md +3 -4
- package/blog/ja/intlayer_with_next-intl.md +3 -4
- package/blog/ja/intlayer_with_react-intl.md +1 -1
- package/blog/ko/intlayer_with_next-i18next.md +3 -4
- package/blog/ko/intlayer_with_next-intl.md +3 -4
- package/blog/ko/intlayer_with_react-intl.md +1 -1
- package/blog/pt/intlayer_with_next-i18next.md +3 -4
- package/blog/pt/intlayer_with_next-intl.md +3 -4
- package/blog/pt/intlayer_with_react-intl.md +1 -1
- package/blog/ru/intlayer_with_next-i18next.md +3 -4
- package/blog/ru/intlayer_with_next-intl.md +3 -4
- package/blog/ru/intlayer_with_react-i18next.md +1 -1
- package/blog/ru/intlayer_with_react-intl.md +1 -1
- package/blog/zh/intlayer_with_next-i18next.md +3 -4
- package/blog/zh/intlayer_with_next-intl.md +3 -4
- package/blog/zh/intlayer_with_react-i18next.md +1 -1
- package/blog/zh/intlayer_with_react-intl.md +1 -1
- package/dist/cjs/generated/docs.entry.cjs +41 -0
- package/dist/cjs/generated/docs.entry.cjs.map +1 -1
- package/dist/esm/generated/docs.entry.mjs +41 -0
- package/dist/esm/generated/docs.entry.mjs.map +1 -1
- package/dist/types/generated/docs.entry.d.ts +1 -0
- package/dist/types/generated/docs.entry.d.ts.map +1 -1
- package/docs/ar/CI_CD.md +67 -41
- package/docs/ar/formatters.md +239 -0
- package/docs/ar/interest_of_intlayer.md +162 -49
- package/docs/ar/introduction.md +3 -3
- package/docs/ar/packages/intlayer/index.md +3 -3
- package/docs/ar/packages/next-intlayer/index.md +3 -3
- package/docs/de/CI_CD.md +63 -37
- package/docs/de/formatters.md +239 -0
- package/docs/de/interest_of_intlayer.md +161 -47
- package/docs/de/introduction.md +3 -3
- package/docs/de/packages/intlayer/index.md +3 -3
- package/docs/de/packages/next-intlayer/index.md +3 -3
- package/docs/de/packages/react-intlayer/index.md +3 -3
- package/docs/en/CI_CD.md +51 -27
- package/docs/en/formatters.md +250 -0
- package/docs/en/interest_of_intlayer.md +159 -46
- package/docs/en/introduction.md +3 -3
- package/docs/en/packages/intlayer/index.md +3 -3
- package/docs/en/packages/next-intlayer/index.md +3 -3
- package/docs/en/packages/react-intlayer/index.md +3 -3
- package/docs/en-GB/CI_CD.md +58 -32
- package/docs/en-GB/formatters.md +239 -0
- package/docs/en-GB/interest_of_intlayer.md +160 -53
- package/docs/en-GB/packages/intlayer/index.md +3 -3
- package/docs/en-GB/packages/next-intlayer/index.md +3 -3
- package/docs/en-GB/packages/react-intlayer/index.md +3 -3
- package/docs/es/CI_CD.md +68 -42
- package/docs/es/formatters.md +239 -0
- package/docs/es/interest_of_intlayer.md +159 -47
- package/docs/es/introduction.md +3 -3
- package/docs/es/packages/intlayer/index.md +3 -3
- package/docs/es/packages/next-intlayer/index.md +3 -3
- package/docs/fr/formatters.md +239 -0
- package/docs/fr/interest_of_intlayer.md +160 -46
- package/docs/fr/introduction.md +3 -3
- package/docs/fr/packages/intlayer/index.md +3 -3
- package/docs/fr/packages/next-intlayer/index.md +3 -3
- package/docs/fr/packages/react-intlayer/index.md +3 -3
- package/docs/hi/CI_CD.md +69 -44
- package/docs/hi/formatters.md +239 -0
- package/docs/hi/interest_of_intlayer.md +158 -42
- package/docs/hi/introduction.md +3 -3
- package/docs/hi/packages/intlayer/index.md +3 -3
- package/docs/hi/packages/next-intlayer/index.md +3 -3
- package/docs/hi/packages/react-intlayer/index.md +3 -3
- package/docs/it/CI_CD.md +67 -41
- package/docs/it/formatters.md +239 -0
- package/docs/it/interest_of_intlayer.md +160 -46
- package/docs/it/introduction.md +3 -3
- package/docs/it/packages/intlayer/index.md +3 -3
- package/docs/it/packages/next-intlayer/index.md +3 -3
- package/docs/it/packages/react-intlayer/index.md +3 -3
- package/docs/ja/CI_CD.md +67 -41
- package/docs/ja/formatters.md +261 -0
- package/docs/ja/interest_of_intlayer.md +157 -48
- package/docs/ja/introduction.md +3 -3
- package/docs/ja/packages/intlayer/index.md +3 -3
- package/docs/ja/packages/next-intlayer/index.md +3 -3
- package/docs/ja/packages/react-intlayer/index.md +3 -3
- package/docs/ko/CI_CD.md +63 -37
- package/docs/ko/formatters.md +258 -0
- package/docs/ko/interest_of_intlayer.md +160 -48
- package/docs/ko/introduction.md +3 -3
- package/docs/ko/packages/intlayer/index.md +3 -3
- package/docs/ko/packages/next-intlayer/index.md +3 -3
- package/docs/ko/packages/react-intlayer/index.md +3 -3
- package/docs/pt/CI_CD.md +67 -41
- package/docs/pt/formatters.md +239 -0
- package/docs/pt/interest_of_intlayer.md +162 -47
- package/docs/pt/introduction.md +3 -3
- package/docs/pt/packages/intlayer/index.md +3 -3
- package/docs/pt/packages/next-intlayer/index.md +3 -3
- package/docs/pt/packages/react-intlayer/index.md +3 -3
- package/docs/ru/CI_CD.md +70 -44
- package/docs/ru/formatters.md +239 -0
- package/docs/ru/interest_of_intlayer.md +168 -50
- package/docs/ru/introduction.md +3 -3
- package/docs/ru/packages/intlayer/index.md +3 -3
- package/docs/ru/packages/next-intlayer/index.md +3 -3
- package/docs/ru/packages/react-intlayer/index.md +3 -3
- package/docs/zh/CI_CD.md +62 -36
- package/docs/zh/formatters.md +239 -0
- package/docs/zh/interest_of_intlayer.md +158 -48
- package/docs/zh/introduction.md +3 -3
- package/docs/zh/packages/intlayer/index.md +3 -3
- package/docs/zh/packages/next-intlayer/index.md +3 -3
- package/docs/zh/packages/react-intlayer/index.md +3 -3
- package/package.json +12 -12
- package/src/generated/docs.entry.ts +41 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2024-08-13
|
|
3
|
+
updatedAt: 2025-08-20
|
|
4
|
+
title: Formatters
|
|
5
|
+
description: Locale-aware formatting utilities based on Intl for numbers, percentages, currency, dates, relative time, units, and compact notation. Includes a cached Intl helper.
|
|
6
|
+
keywords:
|
|
7
|
+
- Formatters
|
|
8
|
+
- Intl
|
|
9
|
+
- Number
|
|
10
|
+
- Currency
|
|
11
|
+
- Percentage
|
|
12
|
+
- Date
|
|
13
|
+
- Relative Time
|
|
14
|
+
- Units
|
|
15
|
+
- Compact
|
|
16
|
+
- Internationalisation
|
|
17
|
+
slugs:
|
|
18
|
+
- doc
|
|
19
|
+
- formatters
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
# Intlayer Formatters
|
|
23
|
+
|
|
24
|
+
## Overview
|
|
25
|
+
|
|
26
|
+
Intlayer provides a set of lightweight helpers built on top of the native `Intl` APIs, plus a cached `Intl` wrapper to avoid repeatedly constructing heavy formatters. These utilities are fully locale-aware and can be used from the main `intlayer` package.
|
|
27
|
+
|
|
28
|
+
### Import
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import {
|
|
32
|
+
Intl,
|
|
33
|
+
number,
|
|
34
|
+
percentage,
|
|
35
|
+
currency,
|
|
36
|
+
date,
|
|
37
|
+
relativeTime,
|
|
38
|
+
units,
|
|
39
|
+
compact,
|
|
40
|
+
} from "intlayer";
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
If you are using React, hooks are also available; see `react-intlayer/format`.
|
|
44
|
+
|
|
45
|
+
## Cached Intl
|
|
46
|
+
|
|
47
|
+
The exported `Intl` is a thin, cached wrapper around the global `Intl`. It memoises instances of `NumberFormat`, `DateTimeFormat`, `RelativeTimeFormat`, which avoids rebuilding the same formatter repeatedly.
|
|
48
|
+
|
|
49
|
+
Because formatter construction is relatively expensive, this caching improves performance without changing behaviour. The wrapper exposes the same API as the native `Intl`, so usage is identical.
|
|
50
|
+
|
|
51
|
+
- Caching is per process and transparent to callers.
|
|
52
|
+
|
|
53
|
+
> If `Intl.DisplayNames` is not available in the environment, a single dev-only warning is printed (consider a polyfill).
|
|
54
|
+
|
|
55
|
+
Example:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { Intl } from "intlayer";
|
|
59
|
+
|
|
60
|
+
const numberFormat = new Intl.NumberFormat("en-GB", {
|
|
61
|
+
style: "currency",
|
|
62
|
+
currency: "GBP",
|
|
63
|
+
});
|
|
64
|
+
numberFormat.format(1234.5); // "£1,234.50"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Formatters
|
|
68
|
+
|
|
69
|
+
All helpers below are exported from `intlayer`.
|
|
70
|
+
|
|
71
|
+
### `number(value, options?)`
|
|
72
|
+
|
|
73
|
+
Formats a numeric value using locale-aware grouping and decimals.
|
|
74
|
+
|
|
75
|
+
- **value**: `number | string`
|
|
76
|
+
- **options**: `Intl.NumberFormatOptions & { locale?: LocalesValues }`
|
|
77
|
+
|
|
78
|
+
Examples:
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
import { number } from "intlayer";
|
|
82
|
+
|
|
83
|
+
number(123456.789); // "123,456.789" (in en-US)
|
|
84
|
+
number("1000000", { locale: "fr" }); // "1 000 000"
|
|
85
|
+
number(1234.5, { minimumFractionDigits: 2 }); // "1,234.50"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### `percentage(value, options?)`
|
|
89
|
+
|
|
90
|
+
Formats a number as a percentage string.
|
|
91
|
+
|
|
92
|
+
Behaviour: values greater than 1 are interpreted as whole percentages and normalised (e.g., `25` → `25%`, `0.25` → `25%`).
|
|
93
|
+
|
|
94
|
+
- **value**: `number | string`
|
|
95
|
+
- **options**: `Intl.NumberFormatOptions & { locale?: LocalesValues }`
|
|
96
|
+
|
|
97
|
+
Examples:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
import { percentage } from "intlayer";
|
|
101
|
+
|
|
102
|
+
percentage(0.25); // "25%"
|
|
103
|
+
percentage(25); // "25%"
|
|
104
|
+
percentage(0.237, { minimumFractionDigits: 1 }); // "23.7%"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### `currency(value, options?)`
|
|
108
|
+
|
|
109
|
+
Formats a value as localised currency. Defaults to `USD` with two fraction digits.
|
|
110
|
+
|
|
111
|
+
- **value**: `number | string`
|
|
112
|
+
- **options**: `Intl.NumberFormatOptions & { locale?: LocalesValues }`
|
|
113
|
+
- Common fields: `currency` (e.g., `"EUR"`), `currencyDisplay` (`"symbol" | "code" | "name"`)
|
|
114
|
+
|
|
115
|
+
Examples:
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
import { currency } from "intlayer";
|
|
119
|
+
|
|
120
|
+
currency(1234.5, { currency: "EUR" }); // "€1,234.50"
|
|
121
|
+
currency("5000", { locale: "fr", currency: "CAD", currencyDisplay: "code" }); // "5 000,00 CAD"
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### `date(date, optionsOrPreset?)`
|
|
125
|
+
|
|
126
|
+
Formats a date/time value with `Intl.DateTimeFormat`.
|
|
127
|
+
|
|
128
|
+
- **date**: `Date | string | number`
|
|
129
|
+
- **optionsOrPreset**: `Intl.DateTimeFormatOptions & { locale?: LocalesValues }` or one of the presets:
|
|
130
|
+
- Presets: `"short" | "long" | "dateOnly" | "timeOnly" | "full"`
|
|
131
|
+
|
|
132
|
+
Examples:
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
import { date } from "intlayer";
|
|
136
|
+
|
|
137
|
+
date(new Date(), "short"); // e.g., "08/02/25, 14:30"
|
|
138
|
+
date("2025-08-02T14:30:00Z", { locale: "fr", month: "long", day: "numeric" }); // "2 août"
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### `relativeTime(from, to = new Date(), options?)`
|
|
142
|
+
|
|
143
|
+
Formats relative time between two instants with `Intl.RelativeTimeFormat`.
|
|
144
|
+
|
|
145
|
+
- Pass "now" as the first argument and the target as the second to obtain natural phrasing.
|
|
146
|
+
- **from**: `Date | string | number`
|
|
147
|
+
- **to**: `Date | string | number` (defaults to `new Date()`)
|
|
148
|
+
- **options**: `{ locale?: LocalesValues; unit?: Intl.RelativeTimeFormatUnit; numeric?: Intl.RelativeTimeFormatNumeric; style?: Intl.RelativeTimeFormatStyle }`
|
|
149
|
+
- Default `unit` is `"second"`.
|
|
150
|
+
|
|
151
|
+
Examples:
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
import { relativeTime } from "intlayer";
|
|
155
|
+
|
|
156
|
+
const now = new Date();
|
|
157
|
+
const in3Days = new Date(now.getTime() + 3 * 864e5);
|
|
158
|
+
relativeTime(now, in3Days, { unit: "day" }); // "in 3 days"
|
|
159
|
+
|
|
160
|
+
const twoHoursAgo = new Date(now.getTime() - 2 * 3600e3);
|
|
161
|
+
relativeTime(now, twoHoursAgo, { unit: "hour", numeric: "auto" }); // "2 hours ago"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### `units(value, options?)`
|
|
165
|
+
|
|
166
|
+
Formats a numeric value as a localised unit string using `Intl.NumberFormat` with `style: 'unit'`.
|
|
167
|
+
|
|
168
|
+
- **value**: `number | string`
|
|
169
|
+
- **options**: `Intl.NumberFormatOptions & { locale?: LocalesValues }`
|
|
170
|
+
- Common fields: `unit` (e.g., `"kilometre"`, `"byte"`), `unitDisplay` (`"short" | "narrow" | "long"`)
|
|
171
|
+
- Defaults: `unit: 'day'`, `unitDisplay: 'short'`, `useGrouping: false`
|
|
172
|
+
|
|
173
|
+
Examples:
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
import { units } from "intlayer";
|
|
177
|
+
|
|
178
|
+
units(5, { unit: "kilometre", unitDisplay: "long", locale: "en-GB" }); // "5 kilometres"
|
|
179
|
+
units(1024, { unit: "byte", unitDisplay: "narrow" }); // "1,024B" (locale-dependent)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### `compact(value, options?)`
|
|
183
|
+
|
|
184
|
+
Formats a number using compact notation (e.g., `1.2K`, `1M`).
|
|
185
|
+
|
|
186
|
+
- **value**: `number | string`
|
|
187
|
+
- **options**: `Intl.NumberFormatOptions & { locale?: LocalesValues }` (uses `notation: 'compact'` under the hood)
|
|
188
|
+
|
|
189
|
+
Examples:
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
import { compact } from "intlayer";
|
|
193
|
+
|
|
194
|
+
compact(1200); // "1.2K"
|
|
195
|
+
compact("1000000", { locale: "fr", compactDisplay: "long" }); // "1 million"
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Notes
|
|
199
|
+
|
|
200
|
+
- All helpers accept `string` inputs; these are internally coerced to numbers or dates.
|
|
201
|
+
- The locale defaults to your configured `internationalization.defaultLocale` if not provided.
|
|
202
|
+
- These utilities are thin wrappers; for advanced formatting, pass through the standard `Intl` options.
|
|
203
|
+
|
|
204
|
+
## Entry points and re-exports (`@index.ts`)
|
|
205
|
+
|
|
206
|
+
The formatters reside in the core package and are re-exported from higher-level packages to keep imports ergonomic across runtimes:
|
|
207
|
+
|
|
208
|
+
Examples:
|
|
209
|
+
|
|
210
|
+
```ts
|
|
211
|
+
// App code (recommended)
|
|
212
|
+
import { number, currency, date, Intl } from "intlayer";
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### React
|
|
216
|
+
|
|
217
|
+
Client components:
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
import { useNumber, useCurrency, useDate } from "react-intlayer/format";
|
|
221
|
+
// or in Next.js apps
|
|
222
|
+
import { useNumber, useCurrency, useDate } from "next-intlayer/client/format";
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Server components (or React Server runtime):
|
|
226
|
+
|
|
227
|
+
```ts
|
|
228
|
+
import { useNumber, useCurrency, useDate } from "intlayer/server/format";
|
|
229
|
+
// or in Next.js apps
|
|
230
|
+
import { useNumber, useCurrency, useDate } from "next-intlayer/server/format";
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
> These hooks will consider the locale from the `IntlayerProvider` or `IntlayerServerProvider`
|
|
234
|
+
|
|
235
|
+
## Doc History
|
|
236
|
+
|
|
237
|
+
| Version | Date | Changes |
|
|
238
|
+
| ------- | ---------- | ---------------------------- |
|
|
239
|
+
| 5.8.0 | 2025-08-18 | Add formatters documentation |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2024-08-14
|
|
3
|
-
updatedAt: 2025-
|
|
3
|
+
updatedAt: 2025-08-20
|
|
4
4
|
title: Interest of Intlayer
|
|
5
5
|
description: Discover the benefits and advantages of using Intlayer in your projects. Understand why Intlayer stands out among other frameworks.
|
|
6
6
|
keywords:
|
|
@@ -11,105 +11,159 @@ keywords:
|
|
|
11
11
|
- Comparison
|
|
12
12
|
slugs:
|
|
13
13
|
- doc
|
|
14
|
-
-
|
|
15
|
-
- interest
|
|
14
|
+
- why
|
|
16
15
|
---
|
|
17
16
|
|
|
18
|
-
#
|
|
17
|
+
# Why you should consider Intlayer?
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
## What is Intlayer?
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
**Intlayer** is an internationalisation library designed specifically for JavaScript developers. It allows the declaration of your content everywhere in your code. It converts declarations of multilingual content into structured dictionaries to integrate easily in your code. Using TypeScript, **Intlayer** makes your development stronger and more efficient.
|
|
22
|
+
|
|
23
|
+
## Why was Intlayer created?
|
|
24
|
+
|
|
25
|
+
Intlayer was created to solve a common problem that affects all common i18n libraries such as `next-intl`, `react-i18next`, `react-intl`, `next-i18next`, `react-intl`, and `vue-i18n`.
|
|
26
|
+
|
|
27
|
+
All these solutions adopt a centralised approach to list and manage your content. For example:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
.
|
|
31
|
+
├── locales
|
|
32
|
+
│ ├── en.json
|
|
33
|
+
│ ├── fr.json
|
|
34
|
+
│ └── es.json
|
|
35
|
+
├── i18n.ts
|
|
36
|
+
└── src
|
|
37
|
+
└── components
|
|
38
|
+
└── MyComponent
|
|
39
|
+
└── index.tsx
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Or here using namespaces:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
.
|
|
46
|
+
├── locales
|
|
47
|
+
│ ├── en
|
|
48
|
+
│ │ ├── footer.json
|
|
49
|
+
│ │ └── navbar.json
|
|
50
|
+
│ ├── fr
|
|
51
|
+
│ │ ├── footer.json
|
|
52
|
+
│ │ └── navbar.json
|
|
53
|
+
│ └── es
|
|
54
|
+
│ ├── footer.json
|
|
55
|
+
│ └── navbar.json
|
|
56
|
+
├── i18n.ts
|
|
57
|
+
└── src
|
|
58
|
+
└── components
|
|
59
|
+
└── MyComponent
|
|
60
|
+
└── index.tsx
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
This type of architecture slows down the development process and makes the codebase more complex to maintain for several reasons:
|
|
64
|
+
|
|
65
|
+
1. **For any new component created, you should:**
|
|
66
|
+
- Create the new resource/namespace in the `locales` folder
|
|
67
|
+
- Remember to import the new namespace in your page
|
|
68
|
+
- Translate your content (often done manually by copy/paste from AI providers)
|
|
69
|
+
|
|
70
|
+
2. **For any change made on your components, you should:**
|
|
71
|
+
- Search for the related resource/namespace (far from the component)
|
|
72
|
+
- Translate your content
|
|
73
|
+
- Ensure your content is up to date for any locale
|
|
74
|
+
- Verify your namespace doesn't include unused keys/values
|
|
75
|
+
- Ensure the structure of your JSON files is the same for all locales
|
|
76
|
+
|
|
77
|
+
On professional projects using these solutions, localisation platforms are often used to help manage the translation of your content. However, this can quickly become costly for large projects.
|
|
78
|
+
|
|
79
|
+
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`).
|
|
23
80
|
|
|
24
81
|
```bash codeFormat="typescript"
|
|
25
82
|
.
|
|
26
|
-
└──
|
|
83
|
+
└── components
|
|
27
84
|
└── MyComponent
|
|
28
85
|
├── index.content.ts
|
|
86
|
+
├── index.test.tsx
|
|
87
|
+
├── index.stories.tsx
|
|
29
88
|
└── index.tsx
|
|
30
89
|
```
|
|
31
90
|
|
|
32
91
|
```bash codeFormat="commonjs"
|
|
33
92
|
.
|
|
34
|
-
└──
|
|
93
|
+
└── components
|
|
35
94
|
└── MyComponent
|
|
36
95
|
├── index.content.cjs
|
|
37
|
-
|
|
96
|
+
├── index.test.mjs
|
|
97
|
+
├── index.stories.mjs
|
|
98
|
+
└── index.tsx
|
|
38
99
|
```
|
|
39
100
|
|
|
40
101
|
```bash codeFormat="esm"
|
|
41
102
|
.
|
|
42
|
-
└──
|
|
103
|
+
└── components
|
|
43
104
|
└── MyComponent
|
|
44
105
|
├── index.content.mjs
|
|
45
|
-
|
|
106
|
+
├── index.test.mjs
|
|
107
|
+
├── index.stories.mjs
|
|
108
|
+
└── index.tsx
|
|
46
109
|
```
|
|
47
110
|
|
|
48
|
-
```tsx fileName="./
|
|
111
|
+
```tsx fileName="./components/MyComponent/index.content.ts" codeFormat="typescript"
|
|
49
112
|
import { t, type Dictionary } from "intlayer";
|
|
50
113
|
|
|
51
114
|
const componentExampleContent = {
|
|
52
115
|
key: "component-example",
|
|
53
116
|
content: {
|
|
54
117
|
myTranslatedContent: t({
|
|
55
|
-
"en-GB": "Hello World",
|
|
56
118
|
en: "Hello World",
|
|
57
|
-
fr: "Bonjour le monde",
|
|
58
119
|
es: "Hola Mundo",
|
|
120
|
+
fr: "Bonjour le monde",
|
|
59
121
|
}),
|
|
60
122
|
},
|
|
61
123
|
} satisfies Dictionary;
|
|
62
124
|
|
|
63
|
-
// Export the content dictionary for the component
|
|
64
125
|
export default componentExampleContent;
|
|
65
126
|
```
|
|
66
127
|
|
|
67
|
-
```jsx fileName="./
|
|
128
|
+
```jsx fileName="./components/MyComponent/index.mjx" codeFormat="esm"
|
|
68
129
|
import { t } from "intlayer";
|
|
69
130
|
|
|
70
131
|
/** @type {import('intlayer').Dictionary} */
|
|
71
|
-
// Define the content dictionary for the component
|
|
72
132
|
const componentExampleContent = {
|
|
73
133
|
key: "component-example",
|
|
74
134
|
content: {
|
|
75
135
|
myTranslatedContent: t({
|
|
76
|
-
"en-GB": "Hello World",
|
|
77
136
|
en: "Hello World",
|
|
78
|
-
fr: "Bonjour le monde",
|
|
79
137
|
es: "Hola Mundo",
|
|
138
|
+
fr: "Bonjour le monde",
|
|
80
139
|
}),
|
|
81
140
|
},
|
|
82
141
|
};
|
|
83
142
|
|
|
84
|
-
// Export the content dictionary for the component
|
|
85
143
|
export default componentExampleContent;
|
|
86
144
|
```
|
|
87
145
|
|
|
88
|
-
```jsx fileName="./
|
|
146
|
+
```jsx fileName="./components/MyComponent/index.csx" codeFormat="commonjs"
|
|
89
147
|
const { t } = require("intlayer");
|
|
90
148
|
|
|
91
149
|
/** @type {import('intlayer').Dictionary} */
|
|
92
|
-
// Define the content dictionary for the component
|
|
93
150
|
const componentExampleContent = {
|
|
94
151
|
key: "component-example",
|
|
95
152
|
content: {
|
|
96
153
|
myTranslatedContent: t({
|
|
97
|
-
"en-GB": "Hello World",
|
|
98
154
|
en: "Hello World",
|
|
99
|
-
fr: "Bonjour le monde",
|
|
100
155
|
es: "Hola Mundo",
|
|
156
|
+
fr: "Bonjour le monde",
|
|
101
157
|
}),
|
|
102
158
|
},
|
|
103
159
|
};
|
|
104
160
|
|
|
105
|
-
// Export the content dictionary for the component
|
|
106
161
|
module.exports = componentExampleContent;
|
|
107
162
|
```
|
|
108
163
|
|
|
109
|
-
```tsx fileName="./
|
|
164
|
+
```tsx fileName="./components/MyComponent/index.tsx" codeFormat="typescript"
|
|
110
165
|
import { useIntlayer } from "react-intlayer";
|
|
111
166
|
|
|
112
|
-
// Component that uses the Intlayer hook to retrieve translated content
|
|
113
167
|
export const ComponentExample = () => {
|
|
114
168
|
const { myTranslatedContent } = useIntlayer("component-example");
|
|
115
169
|
|
|
@@ -117,7 +171,7 @@ export const ComponentExample = () => {
|
|
|
117
171
|
};
|
|
118
172
|
```
|
|
119
173
|
|
|
120
|
-
```jsx fileName="./
|
|
174
|
+
```jsx fileName="./components/MyComponent/index.mjx" codeFormat="esm"
|
|
121
175
|
import { useIntlayer } from "react-intlayer";
|
|
122
176
|
|
|
123
177
|
const ComponentExample = () => {
|
|
@@ -127,7 +181,7 @@ const ComponentExample = () => {
|
|
|
127
181
|
};
|
|
128
182
|
```
|
|
129
183
|
|
|
130
|
-
```jsx fileName="./
|
|
184
|
+
```jsx fileName="./components/MyComponent/index.csx" codeFormat="commonjs"
|
|
131
185
|
const { useIntlayer } = require("react-intlayer");
|
|
132
186
|
|
|
133
187
|
const ComponentExample = () => {
|
|
@@ -137,27 +191,80 @@ const ComponentExample = () => {
|
|
|
137
191
|
};
|
|
138
192
|
```
|
|
139
193
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
-
|
|
194
|
+
This approach allows you to:
|
|
195
|
+
|
|
196
|
+
1. **Increase the speed of development**
|
|
197
|
+
- `.content.{{ts|mjs|cjs|json}}` files can be created using a VSCode extension
|
|
198
|
+
- Autocompletion AI tools in your IDE (such as GitHub Copilot) can help you declare your content, reducing copy/paste
|
|
199
|
+
|
|
200
|
+
2. **Reduce the complexity of your codebase**
|
|
201
|
+
|
|
202
|
+
3. **Increase the maintainability of your codebase**
|
|
203
|
+
|
|
204
|
+
4. **Duplicate your components and their related content more easily (Example: login/register components, etc.)**
|
|
205
|
+
- By limiting the risk of impacting other components' content
|
|
206
|
+
- By copy/pasting your content from one application to another without external dependencies
|
|
207
|
+
|
|
208
|
+
5. **Avoid polluting your codebase with unused keys/values for unused components**
|
|
209
|
+
- If you don't use a component, you don't need to import its content
|
|
210
|
+
- If you delete a component, you'll more easily remember to remove its related content as it will be present in the same folder
|
|
211
|
+
|
|
212
|
+
6. **Reduce reasoning cost for AI agents to declare your multilingual content**
|
|
213
|
+
- The AI agent won't have to scan your entire codebase to know where to implement your content
|
|
214
|
+
- Translations can easily be done by autocompletion AI tools in your IDE (such as GitHub Copilot)
|
|
215
|
+
|
|
216
|
+
7. **Optimise loading performance**
|
|
217
|
+
- If a component is lazy-loaded, its related content will be loaded at the same time
|
|
218
|
+
|
|
219
|
+
## Additional features of Intlayer
|
|
220
|
+
|
|
221
|
+
| Feature | Description |
|
|
222
|
+
| ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
223
|
+
| ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
224
|
+
|  | **Cross-Framework Support**<br><br>Intlayer is compatible with all major frameworks and libraries, including Next.js, React, Vite, Vue.js, Nuxt, Preact, Express, and more. |
|
|
225
|
+
|  | **JavaScript-Powered Content Management**<br><br>Harness the flexibility of JavaScript to define and manage your content efficiently. <br><br> - [Content declaration](https://intlayer.org/doc/concept/content) |
|
|
226
|
+
|  | **Per-Locale Content Declaration File**<br><br>Accelerate your development by declaring your content once, prior to auto-generation.<br><br> - [Per-Locale Content Declaration File](https://intlayer.org/doc/concept/per-locale-file) |
|
|
227
|
+
|  | **Type-Safe Environment**<br><br>Leverage TypeScript to ensure your content definitions and code are error-free, while also benefiting from IDE autocompletion.<br><br> - [TypeScript configuration](https://intlayer.org/doc/environment/vite-and-react#configure-typescript) |
|
|
228
|
+
|  | **Simplified Setup**<br><br>Get up and running quickly with minimal configuration. Adjust settings for internationalisation, routing, AI, build, and content handling with ease. <br><br> - [Explore Next.js integration](https://intlayer.org/doc/environment/nextjs) |
|
|
229
|
+
|  | **Simplified Content Retrieval**<br><br>No need to call your `t` function for each piece of content. Retrieve all your content directly using a single hook.<br><br> - [React integration](https://intlayer.org/doc/environment/create-react-app) |
|
|
230
|
+
|  | **Consistent Server Component Implementation**<br><br>Perfectly suited for Next.js server components, use the same implementation for both client and server components, no need to pass your `t` function across each server component. <br><br> - [Server Components](https://intlayer.org/doc/environment/nextjs#step-7-utilise-content-in-your-code) |
|
|
231
|
+
|  | **Organised Codebase**<br><br>Keep your codebase more organised: 1 component = 1 dictionary in the same folder. Translations close to their respective components enhance maintainability and clarity. <br><br> - [How Intlayer works](https://intlayer.org/doc/concept/how-works-intlayer) |
|
|
232
|
+
|  | **Enhanced Routing**<br><br>Full support for app routing, adapting seamlessly to complex application structures, for Next.js, React, Vite, Vue.js, etc.<br><br> - [Explore Next.js integration](https://intlayer.org/doc/environment/nextjs) |
|
|
233
|
+
|  | **Markdown Support**<br><br>Import and interpret locale files and remote Markdown for multilingual content such as privacy policies, documentation, etc. Interpret and make Markdown metadata accessible in your code.<br><br> - [Content files](https://intlayer.org/doc/concept/content/file) |
|
|
234
|
+
|  | **Free Visual Editor & CMS**<br><br>A free visual editor and CMS are available for content writers, removing the need for a localisation platform. Keep your content synchronised using Git, or externalise it totally or partially with the CMS.<br><br> - [Intlayer Editor](https://intlayer.org/doc/concept/editor) <br> - [Intlayer CMS](https://intlayer.org/doc/concept/cms) |
|
|
235
|
+
|  | **Tree-shakable Content**<br><br>Tree-shakable content, reducing the size of the final bundle. Loads content per component, excluding any unused content from your bundle. Supports lazy loading to enhance app loading efficiency. <br><br> - [App build optimisation](https://intlayer.org/doc/concept/how-works-intlayer#app-build-optimization) |
|
|
236
|
+
|  | **Static Rendering**<br><br>Does not block Static Rendering. <br><br> - [Next.js integration](https://intlayer.org/doc/environment/nextjs) |
|
|
237
|
+
|  | **AI-Powered Translation**<br><br>Transform your website into 231 languages with just one click using Intlayer's advanced AI-powered translation tools with your own AI provider/API key. <br><br> - [CI/CD integration](https://intlayer.org/doc/concept/ci-cd) <br> - [Intlayer CLI](https://intlayer.org/doc/concept/cli) <br> - [Auto fill](https://intlayer.org/doc/concept/auto-fill) |
|
|
238
|
+
|  | **MCP Server Integration**<br><br>Provides an MCP (Model Context Protocol) server for IDE automation, enabling seamless content management and i18n workflows directly within your development environment. <br><br> - [MCP Server](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/mcp_server.md) |
|
|
239
|
+
|  | **VSCode Extension**<br><br>Intlayer provides a VSCode extension to help you manage your content and translations, build your dictionaries, translate your content, and more. <br><br> - [VSCode Extension](https://intlayer.org/doc/vs-code-extension) |
|
|
240
|
+
|  | **Interoperability**<br><br>Enables interoperability with react-i18next, next-i18next, next-intl, and react-intl. <br><br> - [Intlayer and react-intl](https://intlayer.org/blog/intlayer-with-react-intl) <br> - [Intlayer and next-intl](https://intlayer.org/blog/intlayer-with-next-intl) <br> - [Intlayer and next-i18next](https://intlayer.org/blog/intlayer-with-next-i18next) |
|
|
241
|
+
|
|
242
|
+
## Comparison of Intlayer with other solutions
|
|
243
|
+
|
|
244
|
+
| Feature | Intlayer | React-i18next / i18next | React-Intl (FormatJS) | LinguiJS | next-intl | next-i18next | vue-i18n |
|
|
245
|
+
| --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | -------------------------------------------------- | -------------------------------------------------- | -------------------------------------------------- | -------------------------------------------------- | --------------------------------------------------------- |
|
|
246
|
+
| **Translations Near Components** | Yes, content collocated with each component | No | No | No | No | No | Yes - using `Single File Components` (SFCs) |
|
|
247
|
+
| **TypeScript Integration** | Advanced, auto-generated strict types | Basic; extra config for safety | Good, but less strict | Typings, needs config | Good | Basic | Good (types available; key-safety needs setup) |
|
|
248
|
+
| **Missing Translation Detection** | Build-time error/warning | Mostly fallback strings at runtime | Fallback strings | Needs extra config | Runtime fallback | Runtime fallback | Runtime fallback/warnings (configurable) |
|
|
249
|
+
| **Rich Content (JSX/Markdown/components)** | Direct support, even React nodes | Limited / interpolation only | ICU syntax, not real JSX | Limited | Not designed for rich nodes | Limited | Limited (components via `<i18n-t>`, Markdown via plugins) |
|
|
250
|
+
| **AI-powered Translation** | Yes, supports multiple AI providers. Usable using your own API keys. Considers the context of your application and content scope | No | No | No | No | No | No |
|
|
251
|
+
| **Visual Editor** | Yes, local Visual Editor + optional CMS; can externalise codebase content; embeddable | No / available via external localisation platforms | No / available via external localisation platforms | No / available via external localisation platforms | No / available via external localisation platforms | No / available via external localisation platforms | No / available via external localisation platforms |
|
|
252
|
+
| **Localised Routing** | Built-in, middleware support | Plugins or manual config | Not built-in | Plugin/manual config | Built-in | Built-in | Manual via Vue Router (Nuxt i18n handles it) |
|
|
253
|
+
| **Dynamic Route Generation** | Yes | Plugin/ecosystem or manual setup | Not provided | Plugin/manual | Yes | Yes | Not provided (Nuxt i18n provides) |
|
|
254
|
+
| **Pluralisation** | Enumeration-based patterns; see docs | Configurable (plugins like i18next-icu) | Advanced (ICU) | Advanced (ICU/messageformat) | Good | Good | Advanced (built-in plural rules) |
|
|
255
|
+
| **Formatting (dates, numbers, currencies)** | Optimised formatters (Intl under the hood) | Via plugins or custom Intl usage | Advanced ICU formatters | ICU/CLI helpers | Good (Intl helpers) | Good (Intl helpers) | Built-in date/number formatters (Intl) |
|
|
256
|
+
| **Content Format** | .tsx, .ts, .js, .json, .md, .txt | .json | .json, .js | .po, .json | .json, .js, .ts | .json | .json, .js |
|
|
257
|
+
| **ICU support** | WIP (native ICU) | Via plugin (i18next-icu) | Yes | Yes | Yes | Via plugin (i18next-icu) | Via custom formatter/compiler |
|
|
258
|
+
| **SEO Helpers (hreflang, sitemap)** | Built-in tools: helpers for sitemap, **robots.txt**, metadata | Community plugins/manual | Not core | Not core | Good | Good | Not core (Nuxt i18n provides helpers) |
|
|
259
|
+
| **Ecosystem / Community** | Smaller but growing fast and reactive | Largest and most mature | Large, enterprise | Growing, smaller | Mid-size, Next.js-focused | Mid-size, Next.js-focused | Large in Vue ecosystem |
|
|
260
|
+
| **Server-side Rendering & Server Components** | Yes, streamlined for SSR / React Server Components | Supported, some configuration needed | Supported in Next.js | Supported | Full support | Full support | SSR via Nuxt/Vue SSR (no RSC) |
|
|
261
|
+
| **Tree-shaking (load only used content)** | Yes, per-component at build time via Babel/SWC plugins | Usually loads all (can be improved with namespaces/code-splitting) | Usually loads all | Not default | Partial | Partial | Partial (with code-splitting/manual setup) |
|
|
262
|
+
| **Lazy loading** | Yes, per-locale/per-component | Yes (e.g., backends/namespaces on demand) | Yes (split locale bundles) | Yes (dynamic catalogue imports) | Yes (per-route/per-locale) | Yes (per-route/per-locale) | Yes (async locale messages) |
|
|
263
|
+
| **Management of Large Projects** | Encourages modularity, suited for design systems | Requires good file discipline | Central catalogues can become large | Can become complex | Modular with setup | Modular with setup | Modular with Vue Router/Nuxt i18n setup |
|
|
264
|
+
|
|
265
|
+
## Document History
|
|
266
|
+
|
|
267
|
+
| Version | Date | Changes |
|
|
268
|
+
| ------- | ---------- | ------------------------- |
|
|
269
|
+
| 5.8.0 | 2025-08-19 | Updated comparative table |
|
|
270
|
+
| 5.5.10 | 2025-06-29 | Initial history |
|
|
@@ -148,8 +148,8 @@ const clientComponentContent = {
|
|
|
148
148
|
content: {
|
|
149
149
|
myTranslatedContent: t({
|
|
150
150
|
en: "Hello World",
|
|
151
|
-
fr: "Bonjour le monde",
|
|
152
151
|
es: "Hola Mundo",
|
|
152
|
+
fr: "Bonjour le monde",
|
|
153
153
|
}),
|
|
154
154
|
numberOfCar: enu({
|
|
155
155
|
"<-1": "Less than minus one car",
|
|
@@ -174,8 +174,8 @@ const clientComponentContent = {
|
|
|
174
174
|
content: {
|
|
175
175
|
myTranslatedContent: t({
|
|
176
176
|
en: "Hello World",
|
|
177
|
-
fr: "Bonjour le monde",
|
|
178
177
|
es: "Hola Mundo",
|
|
178
|
+
fr: "Bonjour le monde",
|
|
179
179
|
}),
|
|
180
180
|
numberOfCar: enu({
|
|
181
181
|
"<-1": "Less than minus one car",
|
|
@@ -234,8 +234,8 @@ const clientComponentContent = {
|
|
|
234
234
|
content: {
|
|
235
235
|
myTranslatedContent: t({
|
|
236
236
|
en: "Hello World",
|
|
237
|
-
fr: "Bonjour le monde",
|
|
238
237
|
es: "Hola Mundo",
|
|
238
|
+
fr: "Bonjour le monde",
|
|
239
239
|
}),
|
|
240
240
|
numberOfCar: enu({
|
|
241
241
|
"<-1": "Less than minus one car",
|