@intlayer/docs 8.6.10 → 8.7.0-canary.1

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 (129) hide show
  1. package/blog/ar/i18n_using_next-i18next.md +1 -1
  2. package/blog/ar/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
  3. package/blog/de/i18n_using_next-i18next.md +1 -1
  4. package/blog/de/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
  5. package/blog/en/i18n_using_next-i18next.md +1 -1
  6. package/blog/en/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
  7. package/blog/en-GB/i18n_using_next-i18next.md +1 -1
  8. package/blog/en-GB/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  9. package/blog/es/i18n_using_next-i18next.md +1 -1
  10. package/blog/es/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
  11. package/blog/fr/i18n_using_next-i18next.md +1 -1
  12. package/blog/fr/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  13. package/blog/hi/i18n_using_next-i18next.md +1 -1
  14. package/blog/id/i18n_using_next-i18next.md +1 -1
  15. package/blog/id/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
  16. package/blog/it/i18n_using_next-i18next.md +1 -1
  17. package/blog/it/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  18. package/blog/ja/i18n_using_next-i18next.md +1 -1
  19. package/blog/ja/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  20. package/blog/ko/i18n_using_next-i18next.md +1 -1
  21. package/blog/ko/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  22. package/blog/pl/i18n_using_next-i18next.md +1 -1
  23. package/blog/pl/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
  24. package/blog/pt/i18n_using_next-i18next.md +1 -1
  25. package/blog/pt/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  26. package/blog/ru/i18n_using_next-i18next.md +1 -1
  27. package/blog/ru/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  28. package/blog/tr/i18n_using_next-i18next.md +1 -1
  29. package/blog/uk/i18n_using_next-i18next.md +1 -1
  30. package/blog/uk/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
  31. package/blog/vi/i18n_using_next-i18next.md +1 -1
  32. package/blog/vi/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
  33. package/blog/zh/i18n_using_next-i18next.md +1 -1
  34. package/blog/zh/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  35. package/docs/ar/bundle_optimization.md +454 -0
  36. package/docs/ar/intlayer_with_next-i18next.md +1 -1
  37. package/docs/ar/intlayer_with_next-intl.md +1 -1
  38. package/docs/ar/intlayer_with_tanstack+solid.md +24 -5
  39. package/docs/ar/intlayer_with_tanstack.md +45 -68
  40. package/docs/bn/bundle_optimization.md +454 -0
  41. package/docs/cs/bundle_optimization.md +454 -0
  42. package/docs/de/bundle_optimization.md +454 -0
  43. package/docs/de/intlayer_with_next-i18next.md +1 -1
  44. package/docs/de/intlayer_with_next-intl.md +1 -1
  45. package/docs/de/intlayer_with_tanstack+solid.md +24 -5
  46. package/docs/de/intlayer_with_tanstack.md +45 -68
  47. package/docs/en/bundle_optimization.md +36 -8
  48. package/docs/en/intlayer_with_next-i18next.md +1 -1
  49. package/docs/en/intlayer_with_next-intl.md +1 -1
  50. package/docs/en/intlayer_with_tanstack+solid.md +24 -5
  51. package/docs/en/intlayer_with_tanstack.md +45 -68
  52. package/docs/en-GB/bundle_optimization.md +454 -0
  53. package/docs/en-GB/intlayer_with_next-i18next.md +1 -1
  54. package/docs/en-GB/intlayer_with_next-intl.md +1 -1
  55. package/docs/en-GB/intlayer_with_tanstack+solid.md +24 -5
  56. package/docs/en-GB/intlayer_with_tanstack.md +47 -70
  57. package/docs/es/bundle_optimization.md +454 -0
  58. package/docs/es/intlayer_with_next-i18next.md +1 -1
  59. package/docs/es/intlayer_with_next-intl.md +1 -1
  60. package/docs/es/intlayer_with_tanstack+solid.md +24 -5
  61. package/docs/es/intlayer_with_tanstack.md +45 -68
  62. package/docs/fr/bundle_optimization.md +454 -0
  63. package/docs/fr/intlayer_with_next-i18next.md +1 -1
  64. package/docs/fr/intlayer_with_next-intl.md +1 -1
  65. package/docs/fr/intlayer_with_tanstack+solid.md +24 -5
  66. package/docs/fr/intlayer_with_tanstack.md +45 -68
  67. package/docs/hi/bundle_optimization.md +454 -0
  68. package/docs/hi/intlayer_with_next-i18next.md +1 -1
  69. package/docs/hi/intlayer_with_next-intl.md +1 -1
  70. package/docs/hi/intlayer_with_tanstack+solid.md +24 -5
  71. package/docs/hi/intlayer_with_tanstack.md +45 -68
  72. package/docs/id/bundle_optimization.md +454 -0
  73. package/docs/id/intlayer_with_next-i18next.md +1 -1
  74. package/docs/id/intlayer_with_next-intl.md +1 -1
  75. package/docs/id/intlayer_with_tanstack+solid.md +24 -5
  76. package/docs/id/intlayer_with_tanstack.md +45 -68
  77. package/docs/it/bundle_optimization.md +454 -0
  78. package/docs/it/intlayer_with_next-i18next.md +1 -1
  79. package/docs/it/intlayer_with_next-intl.md +1 -1
  80. package/docs/it/intlayer_with_tanstack+solid.md +24 -5
  81. package/docs/it/intlayer_with_tanstack.md +45 -68
  82. package/docs/ja/bundle_optimization.md +454 -0
  83. package/docs/ja/intlayer_with_next-i18next.md +1 -1
  84. package/docs/ja/intlayer_with_next-intl.md +1 -1
  85. package/docs/ja/intlayer_with_tanstack+solid.md +24 -5
  86. package/docs/ja/intlayer_with_tanstack.md +45 -36
  87. package/docs/ko/bundle_optimization.md +454 -0
  88. package/docs/ko/intlayer_with_next-i18next.md +1 -1
  89. package/docs/ko/intlayer_with_next-intl.md +1 -1
  90. package/docs/ko/intlayer_with_tanstack+solid.md +24 -5
  91. package/docs/ko/intlayer_with_tanstack.md +45 -68
  92. package/docs/nl/bundle_optimization.md +454 -0
  93. package/docs/pl/bundle_optimization.md +454 -0
  94. package/docs/pl/intlayer_with_next-i18next.md +1 -1
  95. package/docs/pl/intlayer_with_next-intl.md +1 -1
  96. package/docs/pl/intlayer_with_tanstack+solid.md +24 -5
  97. package/docs/pl/intlayer_with_tanstack.md +45 -68
  98. package/docs/pt/bundle_optimization.md +454 -0
  99. package/docs/pt/intlayer_with_next-i18next.md +1 -1
  100. package/docs/pt/intlayer_with_next-intl.md +1 -1
  101. package/docs/pt/intlayer_with_tanstack+solid.md +24 -5
  102. package/docs/pt/intlayer_with_tanstack.md +45 -68
  103. package/docs/ru/bundle_optimization.md +454 -0
  104. package/docs/ru/intlayer_with_next-i18next.md +1 -1
  105. package/docs/ru/intlayer_with_next-intl.md +1 -1
  106. package/docs/ru/intlayer_with_tanstack+solid.md +24 -5
  107. package/docs/ru/intlayer_with_tanstack.md +45 -68
  108. package/docs/tr/bundle_optimization.md +454 -0
  109. package/docs/tr/intlayer_with_next-i18next.md +1 -1
  110. package/docs/tr/intlayer_with_next-intl.md +1 -1
  111. package/docs/tr/intlayer_with_tanstack+solid.md +24 -5
  112. package/docs/tr/intlayer_with_tanstack.md +45 -68
  113. package/docs/uk/bundle_optimization.md +454 -0
  114. package/docs/uk/intlayer_with_next-i18next.md +1 -1
  115. package/docs/uk/intlayer_with_next-intl.md +1 -1
  116. package/docs/uk/intlayer_with_tanstack+solid.md +24 -5
  117. package/docs/uk/intlayer_with_tanstack.md +45 -68
  118. package/docs/ur/bundle_optimization.md +454 -0
  119. package/docs/vi/bundle_optimization.md +454 -0
  120. package/docs/vi/intlayer_with_next-i18next.md +1 -1
  121. package/docs/vi/intlayer_with_next-intl.md +1 -1
  122. package/docs/vi/intlayer_with_tanstack+solid.md +24 -5
  123. package/docs/vi/intlayer_with_tanstack.md +45 -68
  124. package/docs/zh/bundle_optimization.md +454 -0
  125. package/docs/zh/intlayer_with_next-i18next.md +1 -1
  126. package/docs/zh/intlayer_with_next-intl.md +1 -1
  127. package/docs/zh/intlayer_with_tanstack+solid.md +24 -5
  128. package/docs/zh/intlayer_with_tanstack.md +45 -68
  129. package/package.json +7 -7
@@ -0,0 +1,454 @@
1
+ ---
2
+ createdAt: 2025-11-25
3
+ updatedAt: 2026-04-08
4
+ title: Optimisation de la taille et des performances du bundle i18n
5
+ description: Réduisez la taille du bundle de votre application en optimisant le contenu d'internationalisation (i18n). Apprenez à exploiter le tree shaking et le lazy loading pour les dictionnaires avec Intlayer.
6
+ keywords:
7
+ - Optimisation du bundle
8
+ - Automatisation du contenu
9
+ - Contenu dynamique
10
+ - Intlayer
11
+ - Next.js
12
+ - JavaScript
13
+ - React
14
+ slugs:
15
+ - doc
16
+ - concept
17
+ - bundle-optimization
18
+ history:
19
+ - version: 8.7.0
20
+ date: 2026-04-08
21
+ changes: "Ajout des options `minify` et `purge` à la configuration de build"
22
+ ---
23
+
24
+ # Optimisation de la taille et des performances du bundle i18n
25
+
26
+ L'un des défis les plus courants avec les solutions i18n traditionnelles basées sur des fichiers JSON est la gestion de la taille du contenu. Si les développeurs ne séparent pas manuellement le contenu en namespaces, les utilisateurs finissent souvent par télécharger les traductions de chaque page et potentiellement de chaque langue simplement pour afficher une seule page.
27
+
28
+ Par exemple, une application avec 10 pages traduites en 10 langues peut entraîner le téléchargement par un utilisateur du contenu de 100 pages, alors qu'il n'a besoin que d'**une seule** (la page actuelle dans la langue actuelle). Cela conduit à un gaspillage de bande passante et à des temps de chargement plus lents.
29
+
30
+ **Intlayer résout ce problème grâce à une optimisation au moment de la compilation.** Il analyse votre code pour détecter quels dictionnaires sont réellement utilisés par composant et réinjecte uniquement le contenu nécessaire dans votre bundle.
31
+
32
+ ## Table des matières
33
+
34
+ <TOC />
35
+
36
+ ## Analyser votre bundle
37
+
38
+ L'analyse de votre bundle est la première étape pour identifier les fichiers JSON "lourds" et les opportunités de fractionnement de code (code-splitting). Ces outils génèrent une carte arborescente (treemap) visuelle du code compilé de votre application, vous permettant de voir exactement quelles bibliothèques consomment le plus d'espace.
39
+
40
+ <Tabs>
41
+ <Tab value="vite">
42
+
43
+ ### Vite / Rollup
44
+
45
+ Vite utilise Rollup sous le capot. Le plugin `rollup-plugin-visualizer` génère un fichier HTML interactif montrant la taille de chaque module dans votre graphique.
46
+
47
+ ```bash
48
+ npm install -D rollup-plugin-visualizer
49
+ ```
50
+
51
+ ```typescript fileName="vite.config.ts"
52
+ import { defineConfig } from "vite";
53
+ import { visualizer } from "rollup-plugin-visualizer";
54
+
55
+ export default defineConfig({
56
+ plugins: [
57
+ visualizer({
58
+ open: true, // Ouvre automatiquement le rapport dans votre navigateur
59
+ filename: "stats.html",
60
+ gzipSize: true,
61
+ brotliSize: true,
62
+ }),
63
+ ],
64
+ });
65
+ ```
66
+
67
+ </Tab>
68
+ <Tab value="nextjs (turbopack)">
69
+
70
+ ### Next.js (Turbopack)
71
+
72
+ Pour les projets utilisant l'App Router et Turbopack, Next.js fournit un analyseur expérimental intégré qui ne nécessite aucune dépendance supplémentaire.
73
+
74
+ ```bash packageManager='npm'
75
+ npx next experimental-analyze
76
+ ```
77
+
78
+ ```bash packageManager='yarn'
79
+ yarn next experimental-analyze
80
+ ```
81
+
82
+ ```bash packageManager='pnpm'
83
+ pnpm next experimental-analyze
84
+ ```
85
+
86
+ ```bash packageManager='bun'
87
+ bun next experimental-analyze
88
+ ```
89
+
90
+ </Tab>
91
+ <Tab value="nextjs (Webpack)">
92
+
93
+ ### Next.js (Webpack)
94
+
95
+ Si vous utilisez le bundler Webpack par défaut dans Next.js, utilisez l'analyseur de bundle officiel. Déclenchez-le en définissant une variable d'environnement lors de votre build.
96
+
97
+ ```bash packageManager='npm'
98
+ npm install -D @next/bundle-analyzer
99
+ ```
100
+
101
+ ```bash packageManager='yarn'
102
+ yarn add -D @next/bundle-analyzer
103
+ ```
104
+
105
+ ```bash packageManager='pnpm'
106
+ pnpm add -D @next/bundle-analyzer
107
+ ```
108
+
109
+ ```bash packageManager='bun'
110
+ bun add -d @next/bundle-analyzer
111
+ ```
112
+
113
+ ```javascript fileName="next.config.js"
114
+ const withBundleAnalyzer = require("@next/bundle-analyzer")({
115
+ enabled: process.env.ANALYZE === "true",
116
+ });
117
+
118
+ module.exports = withBundleAnalyzer({
119
+ // Votre configuration Next.js
120
+ });
121
+ ```
122
+
123
+ **Utilisation :**
124
+
125
+ ```bash
126
+ ANALYZE=true npm run build
127
+ ```
128
+
129
+ </Tab>
130
+ <Tab value="Webpack (CRA / Angular / etc)">
131
+
132
+ ### Webpack standard
133
+
134
+ Pour Create React App (ejected), Angular ou les configurations Webpack personnalisées, utilisez le standard de l'industrie `webpack-bundle-analyzer`.
135
+
136
+ ```bash packageManager='npm'
137
+ npm install -D webpack-bundle-analyzer
138
+ ```
139
+
140
+ ```bash packageManager='yarn'
141
+ yarn add -D webpack-bundle-analyzer
142
+ ```
143
+
144
+ ```bash packageManager='pnpm'
145
+ pnpm add -D webpack-bundle-analyzer
146
+ ```
147
+
148
+ ```bash packageManager='bun'
149
+ bun add -d webpack-bundle-analyzer
150
+ ```
151
+
152
+ ```typescript fileName="webpack.config.ts
153
+ import { BundleAnalyzerPlugin } from "webpack-bundle-analyzer";
154
+
155
+ export default {
156
+ plugins: [
157
+ new BundleAnalyzerPlugin({
158
+ analyzerMode: "static",
159
+ reportFilename: "bundle-analyzer.html",
160
+ openAnalyzer: false,
161
+ }),
162
+ ],
163
+ };
164
+ ```
165
+
166
+ </Tab>
167
+ </Tabs>
168
+
169
+ ## Comment ça fonctionne
170
+
171
+ Intlayer utilise une **approche par composant**. Contrairement aux fichiers JSON globaux, votre contenu est défini à côté ou à l'intérieur de vos composants. Lors du processus de build, Intlayer :
172
+
173
+ 1. **Analyse** votre code pour trouver les appels à `useIntlayer`.
174
+ 2. **Construit** le contenu du dictionnaire correspondant.
175
+ 3. **Remplace** l'appel à `useIntlayer` par un code optimisé basé sur votre configuration.
176
+
177
+ Cela garantit que :
178
+
179
+ - Si un composant n'est pas importé, son contenu n'est pas inclus dans le bundle (élimination de code mort).
180
+ - Si un composant est chargé de manière paresseuse (lazy-loaded), son contenu l'est aussi.
181
+
182
+ ## Configuration par plateforme
183
+
184
+ <Tabs>
185
+ <Tab value="nextjs">
186
+
187
+ ### Next.js
188
+
189
+ Next.js nécessite le plugin `@intlayer/swc` pour gérer la transformation, car Next.js utilise SWC pour les builds.
190
+
191
+ > Ce plugin n'est pas installé par défaut car les plugins SWC sont encore expérimentaux pour Next.js. Cela peut changer à l'avenir.
192
+
193
+ ```bash packageManager="npm"
194
+ npm install -D @intlayer/swc
195
+ ```
196
+
197
+ ```bash packageManager="yarn"
198
+ yarn add -D @intlayer/swc
199
+ ```
200
+
201
+ ```bash packageManager="pnpm"
202
+ pnpm add -D @intlayer/swc
203
+ ```
204
+
205
+ ```bash packageManager="bun"
206
+ bun add -d @intlayer/swc
207
+ ```
208
+
209
+ Une fois installé, Intlayer détectera et utilisera automatiquement le plugin.
210
+
211
+ </Tab>
212
+ <Tab value="vite">
213
+
214
+ ### Vite
215
+
216
+ Vite utilise le plugin `@intlayer/babel` qui est inclus comme dépendance de `vite-intlayer`. L'optimisation est activée par défaut. Rien d'autre à faire.
217
+
218
+ </Tab>
219
+ <Tab value="webpack">
220
+
221
+ ### Webpack
222
+
223
+ Pour activer l'optimisation du bundle avec Intlayer sur Webpack, vous devez installer et configurer le plugin Babel (`@intlayer/babel`) ou SWC (`@intlayer/swc`) approprié.
224
+
225
+ ```bash packageManager="npm"
226
+ npm install -D @intlayer/babel
227
+ ```
228
+
229
+ ```bash packageManager="yarn"
230
+ yarn add -D @intlayer/babel
231
+ ```
232
+
233
+ ```bash packageManager="pnpm"
234
+ pnpm add -D @intlayer/babel
235
+ ```
236
+
237
+ ```bash packageManager="bun"
238
+ bun add -d @intlayer/babel
239
+ ```
240
+
241
+ ```typescript fileName="babel.config.js"
242
+ const {
243
+ getOptimizePluginOptions,
244
+ intlayerOptimizeBabelPlugin,
245
+ } = require("@intlayer/babel");
246
+
247
+ module.exports = {
248
+ plugins: [[intlayerOptimizeBabelPlugin, getOptimizePluginOptions()]],
249
+ };
250
+ ```
251
+
252
+ </Tab>
253
+ </Tabs>
254
+
255
+ ## Configuration
256
+
257
+ Vous pouvez contrôler la manière dont Intlayer optimise votre bundle via la propriété `build` dans votre fichier `intlayer.config.ts`.
258
+
259
+ ```typescript fileName="intlayer.config.ts"
260
+ import { Locales, type IntlayerConfig } from "intlayer";
261
+
262
+ const config: IntlayerConfig = {
263
+ internationalization: {
264
+ locales: [Locales.ENGLISH, Locales.FRENCH],
265
+ defaultLocale: Locales.ENGLISH,
266
+ },
267
+ dictionary: {
268
+ importMode: "dynamic",
269
+ },
270
+ build: {
271
+ /**
272
+ * Minifier les dictionnaires pour réduire la taille du bundle.
273
+ */
274
+ minify: true;
275
+
276
+ /**
277
+ * Purger les clés inutilisées dans les dictionnaires
278
+ */
279
+ purge: true;
280
+
281
+ /**
282
+ * Indique si le build doit vérifier les types TypeScript
283
+ */
284
+ checkTypes: false;
285
+ },
286
+ };
287
+
288
+ export default config;
289
+ ```
290
+
291
+ > Conserver l'option par défaut pour `optimize` est recommandé dans la grande majorité des cas.
292
+
293
+ > Voir la documentation de configuration pour plus de détails : [Configuration](https://github.com/aymericzip/intlayer/blob/main/docs/docs/fr/configuration.md)
294
+
295
+ ### Options de build
296
+
297
+ Les options suivantes sont disponibles sous l'objet de configuration `build` :
298
+
299
+ | Propriété | Type | Par défaut | Description |
300
+ | :------------- | :-------- | :---------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
301
+ | **`optimize`** | `boolean` | `undefined` | Contrôle si l'optimisation du build est activée. Si `true`, Intlayer remplace les appels aux dictionnaires par des injections optimisées. Si `false`, l'optimisation est désactivée. Idéalement à `true` en prod. |
302
+ | **`minify`** | `boolean` | `false` | Indique s'il faut minifier les dictionnaires pour réduire la taille du bundle. |
303
+ | **`purge`** | `boolean` | `false` | Indique s'il faut purger les clés inutilisées dans les dictionnaires. |
304
+
305
+ ### Minification
306
+
307
+ La minification des dictionnaires supprime les espaces inutiles, les commentaires et réduit la taille du contenu JSON. C'est particulièrement utile pour les dictionnaires volumineux.
308
+
309
+ ```typescript fileName="intlayer.config.ts"
310
+ import type { IntlayerConfig } from "intlayer";
311
+
312
+ const config: IntlayerConfig = {
313
+ build: {
314
+ minify: true,
315
+ },
316
+ };
317
+
318
+ export default config;
319
+ ```
320
+
321
+ > Note : La minification est ignorée si `optimize` est désactivé ou si l'Éditeur Visuel est activé (car l'éditeur a besoin du contenu complet pour permettre l'édition).
322
+
323
+ ### Purge
324
+
325
+ La purge garantit que seules les clés réellement utilisées dans votre code sont incluses dans le bundle final de dictionnaires. Cela peut réduire considérablement la taille de votre bundle si vous avez de grands dictionnaires avec de nombreuses clés qui ne sont pas utilisées dans chaque partie de votre application.
326
+
327
+ ```typescript fileName="intlayer.config.ts"
328
+ import type { IntlayerConfig } from "intlayer";
329
+
330
+ const config: IntlayerConfig = {
331
+ build: {
332
+ purge: true,
333
+ },
334
+ };
335
+
336
+ export default config;
337
+ ```
338
+
339
+ > Note : La purge est ignorée si `optimize` est désactivé.
340
+
341
+ ### Mode d'importation
342
+
343
+ Pour les grandes applications comprenant plusieurs pages et locales, vos fichiers JSON peuvent représenter une partie importante de la taille de votre bundle. Intlayer vous permet de contrôler la manière dont les dictionnaires sont chargés.
344
+
345
+ Le mode d'importation peut être défini par défaut globalement dans votre fichier `intlayer.config.ts`.
346
+
347
+ ```typescript fileName="intlayer.config.ts"
348
+ import type { IntlayerConfig } from "intlayer";
349
+
350
+ const config: IntlayerConfig = {
351
+ build: {
352
+ minify: true,
353
+ },
354
+ };
355
+
356
+ export default config;
357
+ ```
358
+
359
+ Ainsi que pour chaque dictionnaire dans vos fichiers `.content.{{ts|tsx|js|jsx|mjs|cjs|json|jsonc|json5}}`.
360
+
361
+ ```ts
362
+ import { type Dictionary, t } from "intlayer";
363
+
364
+ const appContent: Dictionary = {
365
+ key: "app",
366
+ importMode: "dynamic", // Surcharge le mode d'importation par défaut
367
+ content: {
368
+ // ...
369
+ },
370
+ };
371
+
372
+ export default appContent;
373
+ ```
374
+
375
+ | Propriété | Type | Par défaut | Description |
376
+ | :--------------- | :--------------------------------- | :--------- | :--------------------------------------------------------------------------------------------------------------------------- |
377
+ | **`importMode`** | `'static'`, `'dynamic'`, `'fetch'` | `'static'` | **Obsolète** : Utilisez `dictionary.importMode` à la place. Détermine comment les dictionnaires sont chargés (voir détails). |
378
+
379
+ Le paramètre `importMode` dicte comment le contenu du dictionnaire est injecté dans votre composant.
380
+ Vous pouvez le définir globalement dans le fichier `intlayer.config.ts` sous l'objet `dictionary`, ou vous pouvez le surcharger pour un dictionnaire spécifique dans son fichier `.content.ts`.
381
+
382
+ ### 1. Mode Statique (`default`)
383
+
384
+ En mode statique, Intlayer remplace `useIntlayer` par `useDictionary` et injecte le dictionnaire directement dans le bundle JavaScript.
385
+
386
+ - **Avantages :** Rendu instantané (synchrone), zéro requête réseau supplémentaire lors de l'hydratation.
387
+ - **Inconvénients :** Le bundle inclut les traductions pour **toutes** les langues disponibles pour ce composant spécifique.
388
+ - **Idéal pour :** Single Page Applications (SPA).
389
+
390
+ **Exemple de code transformé :**
391
+
392
+ ```tsx
393
+ // Votre code
394
+ const content = useIntlayer("my-key");
395
+
396
+ // Code optimisé (Statique)
397
+ const content = useDictionary({
398
+ key: "my-key",
399
+ content: {
400
+ nodeType: "translation",
401
+ translation: {
402
+ en: "My title",
403
+ fr: "Mon titre",
404
+ },
405
+ },
406
+ });
407
+ ```
408
+
409
+ ### 2. Mode Dynamique
410
+
411
+ En mode dynamique, Intlayer remplace `useIntlayer` par `useDictionaryAsync`. Cela utilise `import()` (mécanisme de type Suspense) pour charger paresseusement spécifiquement le JSON pour la locale actuelle.
412
+
413
+ - **Avantages :** **Tree shaking au niveau de la locale.** Un utilisateur consultant la version anglaise ne téléchargera _que_ le dictionnaire anglais. Le dictionnaire français n'est jamais chargé.
414
+ - **Inconvénients :** Déclenche une requête réseau (récupération d'asset) par composant lors de l'hydratation.
415
+ - **Idéal pour :** Gros blocs de texte, articles ou applications supportant de nombreuses langues où la taille du bundle est critique.
416
+
417
+ **Exemple de code transformé :**
418
+
419
+ ```tsx
420
+ // Votre code
421
+ const content = useIntlayer("my-key");
422
+
423
+ // Code optimisé (Dynamique)
424
+ const content = useDictionaryAsync({
425
+ en: () =>
426
+ import(".intlayer/dynamic_dictionary/my-key/en.json").then(
427
+ (mod) => mod.default
428
+ ),
429
+ fr: () =>
430
+ import(".intlayer/dynamic_dictionary/my-key/fr.json").then(
431
+ (mod) => mod.default
432
+ ),
433
+ });
434
+ ```
435
+
436
+ > Lors de l'utilisation de `importMode: 'dynamic'`, si vous avez 100 composants utilisant `useIntlayer` sur une seule page, le navigateur tentera 100 récupérations séparées. Pour éviter cette "cascade" de requêtes, regroupez le contenu dans moins de fichiers `.content` (par exemple, un dictionnaire par section de page) plutôt qu'un par composant atomique.
437
+
438
+ ### 3. Mode Fetch
439
+
440
+ Se comporte de manière similaire au mode Dynamique mais tente d'abord de récupérer les dictionnaires à partir de l'API Intlayer Live Sync. Si l'appel API échoue ou si le contenu n'est pas marqué pour les mises à jour en direct, il se replie sur l'importation dynamique.
441
+
442
+ > Voir la documentation CMS pour plus de détails : [CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/fr/intlayer_CMS.md)
443
+
444
+ > En mode fetch, la purge et la minification ne peuvent pas être utilisées.
445
+
446
+ ## Résumé : Statique vs Dynamique
447
+
448
+ | Fonctionnalité | Mode Statique | Mode Dynamique |
449
+ | :----------------------------- | :---------------------------------------------------- | :----------------------------------------------- |
450
+ | **Taille du bundle JS** | Plus grande (inclut toutes les langues pour le comp.) | Plus petite (seulement le code, pas de contenu) |
451
+ | **Chargement initial** | Instantané (le contenu est dans le bundle) | Léger délai (récupère le JSON) |
452
+ | **Requêtes réseau** | 0 requête supplémentaire | 1 requête par dictionnaire |
453
+ | **Tree Shaking** | Au niveau du composant | Au niveau du composant + Au niveau de la locale |
454
+ | **Meilleur cas d'utilisation** | Composants UI, petites applications | Pages avec beaucoup de texte, nombreuses langues |
@@ -257,7 +257,7 @@ export default function LocaleLayout({
257
257
  params: { locale: string };
258
258
  }) {
259
259
  const locale: Locale = (locales as readonly string[]).includes(params.locale)
260
- ? (params.locale as any)
260
+ ? params.locale
261
261
  : defaultLocale;
262
262
 
263
263
  const dir = isRtl(locale) ? "rtl" : "ltr";
@@ -103,7 +103,7 @@ async function loadMessages(locale: string) {
103
103
  }
104
104
 
105
105
  export default getRequestConfig(async ({ locale }) => {
106
- if (!locales.includes(locale as any)) notFound();
106
+ if (!locales.includes(locale)) notFound();
107
107
 
108
108
  return {
109
109
  messages: await loadMessages(locale),
@@ -194,9 +194,7 @@ const RootComponent: ParentComponent = (props) => {
194
194
  </head>
195
195
  <body>
196
196
  <IntlayerProvider locale={locale}>
197
- <Suspense>
198
- {props.children}
199
- </Suspense>
197
+ <Suspense>{props.children}</Suspense>
200
198
  </IntlayerProvider>
201
199
  <Scripts />
202
200
  </body>
@@ -506,12 +504,33 @@ export const Route = createFileRoute("/{-$locale}/")({
506
504
  component: RouteComponent,
507
505
  head: ({ params }) => {
508
506
  const { locale } = params;
509
- const metaContent = getIntlayer("page-metadata", locale);
507
+ const path = "/"; // The path for this route
508
+
509
+ const metaContent = getIntlayer("app", locale);
510
510
 
511
511
  return {
512
+ links: [
513
+ // Canonical link: Points to the current localized page
514
+ { rel: "canonical", href: getLocalizedUrl(path, locale) },
515
+
516
+ // Hreflang: Tell Google about all localized versions
517
+ ...localeMap(({ locale: mapLocale }) => ({
518
+ rel: "alternate",
519
+ hrefLang: mapLocale,
520
+ href: getLocalizedUrl(path, mapLocale),
521
+ })),
522
+
523
+ // x-default: For users in unmatched languages
524
+ // Define the default fallback locale (usually your primary language)
525
+ {
526
+ rel: "alternate",
527
+ hrefLang: "x-default",
528
+ href: getLocalizedUrl(path, defaultLocale),
529
+ },
530
+ ],
512
531
  meta: [
513
532
  { title: metaContent.title },
514
- { content: metaContent.description, name: "description" },
533
+ { name: "description", content: metaContent.meta.description },
515
534
  ],
516
535
  };
517
536
  },
@@ -225,9 +225,7 @@ function RootDocument({ children }: { children: ReactNode }) {
225
225
  <HeadContent />
226
226
  </head>
227
227
  <body>
228
- <IntlayerProvider locale={locale}>
229
- {children}
230
- </IntlayerProvider>
228
+ <IntlayerProvider locale={locale}>{children}</IntlayerProvider>
231
229
  <Scripts />
232
230
  </body>
233
231
  </html>
@@ -326,30 +324,20 @@ import { getPrefix } from "intlayer";
326
324
 
327
325
  export const LOCALE_ROUTE = "{-$locale}" as const;
328
326
 
329
- // Utilitaire principal
330
- export type RemoveLocaleParam<T> = T extends string
331
- ? RemoveLocaleFromString<T>
332
- : T;
327
+ export type To = StripLocalePrefix<LinkComponentProps["to"]>;
333
328
 
334
- export type To = RemoveLocaleParam<LinkComponentProps["to"]>;
335
-
336
- type CollapseDoubleSlashes<S extends string> =
337
- S extends `${infer H}//${infer T}` ? CollapseDoubleSlashes<`${H}/${T}`> : S;
329
+ export type StripLocalePrefix<T extends string | undefined> = T extends
330
+ | `/${typeof LOCALE_ROUTE}/`
331
+ | `/${typeof LOCALE_ROUTE}`
332
+ ? "/"
333
+ : T extends `/${typeof LOCALE_ROUTE}/${infer Rest}`
334
+ ? `/${Rest}`
335
+ : T;
338
336
 
339
337
  type LocalizedLinkProps = {
340
338
  to?: To;
341
339
  } & Omit<LinkComponentProps, "to">;
342
340
 
343
- // Aides
344
- type RemoveAll<
345
- S extends string,
346
- Sub extends string,
347
- > = S extends `${infer H}${Sub}${infer T}` ? RemoveAll<`${H}${T}`, Sub> : S;
348
-
349
- type RemoveLocaleFromString<S extends string> = CollapseDoubleSlashes<
350
- RemoveAll<S, typeof LOCALE_ROUTE>
351
- >;
352
-
353
341
  export const LocalizedLink: FC<LocalizedLinkProps> = (props) => {
354
342
  const { locale } = useLocale();
355
343
  const { localePrefix } = getPrefix(locale);
@@ -378,26 +366,26 @@ Ensuite, nous pouvons créer un hook `useLocalizedNavigate` pour la navigation p
378
366
  import { useNavigate } from "@tanstack/react-router";
379
367
  import { getPrefix } from "intlayer";
380
368
  import { useLocale } from "react-intlayer";
381
- import { LOCALE_ROUTE } from "@/components/localized-link";
369
+ import type { StripLocalePrefix } from "@/components/localized-link";
382
370
  import type { FileRouteTypes } from "@/routeTree.gen";
383
371
 
384
- type StripLocalePrefix<T extends string> = T extends
385
- | `/${typeof LOCALE_ROUTE}`
386
- | `/${typeof LOCALE_ROUTE}/`
387
- ? "/"
388
- : T extends `/${typeof LOCALE_ROUTE}/${infer Rest}`
389
- ? `/${Rest}`
390
- : never;
372
+ type NavigateFn = ReturnType<typeof useNavigate>;
373
+ type BaseNavigateOptions = Parameters<NavigateFn>[0];
391
374
 
392
375
  type LocalizedTo = StripLocalePrefix<FileRouteTypes["to"]>;
393
376
 
394
- type LocalizedNavigate = {
395
- (to: LocalizedTo): ReturnType<ReturnType<typeof useNavigate>>;
396
- (
397
- opts: { to: LocalizedTo } & Record<string, unknown>
398
- ): ReturnType<ReturnType<typeof useNavigate>>;
377
+ export type LocalizedNavigateOptions = Omit<
378
+ BaseNavigateOptions,
379
+ "to" | "params"
380
+ > & {
381
+ to: LocalizedTo;
382
+ params?: Omit<NonNullable<BaseNavigateOptions["params"]>, "locale">;
399
383
  };
400
384
 
385
+ type LocalizedNavigate = (
386
+ options: LocalizedNavigateOptions
387
+ ) => ReturnType<NavigateFn>;
388
+
401
389
  export const useLocalizedNavigate = () => {
402
390
  const navigate = useNavigate();
403
391
 
@@ -444,38 +432,6 @@ import { useLocalizedNavigate } from "@/hooks/useLocalizedNavigate";
444
432
 
445
433
  export const Route = createFileRoute("/{-$locale}/")({
446
434
  component: RouteComponent,
447
- head: ({ params }) => {
448
- const { locale } = params;
449
- const path = "/"; // The path for this route
450
-
451
- const metaContent = getIntlayer("app", locale);
452
-
453
- return {
454
- links: [
455
- // Canonical link: Points to the current localized page
456
- { rel: "canonical", href: getLocalizedUrl(path, locale) },
457
-
458
- // Hreflang: Tell Google about all localized versions
459
- ...localeMap(({ locale: mapLocale }) => ({
460
- rel: "alternate",
461
- hrefLang: mapLocale,
462
- href: getLocalizedUrl(path, mapLocale),
463
- })),
464
-
465
- // x-default: For users in unmatched languages
466
- // Define the default fallback locale (usually your primary language)
467
- {
468
- rel: "alternate",
469
- hrefLang: "x-default",
470
- href: getLocalizedUrl(path, defaultLocale),
471
- },
472
- ],
473
- meta: [
474
- { title: metaContent.title },
475
- { name: "description", content: metaContent.meta.description },
476
- ],
477
- };
478
- },
479
435
  });
480
436
 
481
437
  function RouteComponent() {
@@ -630,12 +586,33 @@ export const Route = createFileRoute("/{-$locale}/")({
630
586
  component: RouteComponent,
631
587
  head: ({ params }) => {
632
588
  const { locale } = params;
633
- const metaContent = getIntlayer("page-metadata", locale);
589
+ const path = "/"; // The path for this route
590
+
591
+ const metaContent = getIntlayer("app", locale);
634
592
 
635
593
  return {
594
+ links: [
595
+ // Canonical link: Points to the current localized page
596
+ { rel: "canonical", href: getLocalizedUrl(path, locale) },
597
+
598
+ // Hreflang: Tell Google about all localized versions
599
+ ...localeMap(({ locale: mapLocale }) => ({
600
+ rel: "alternate",
601
+ hrefLang: mapLocale,
602
+ href: getLocalizedUrl(path, mapLocale),
603
+ })),
604
+
605
+ // x-default: For users in unmatched languages
606
+ // Define the default fallback locale (usually your primary language)
607
+ {
608
+ rel: "alternate",
609
+ hrefLang: "x-default",
610
+ href: getLocalizedUrl(path, defaultLocale),
611
+ },
612
+ ],
636
613
  meta: [
637
614
  { title: metaContent.title },
638
- { content: metaContent.description, name: "description" },
615
+ { name: "description", content: metaContent.meta.description },
639
616
  ],
640
617
  };
641
618
  },