@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: Optimización del tamaño y rendimiento del bundle i18n
5
+ description: Reduzca el tamaño del bundle de su aplicación optimizando el contenido de internacionalización (i18n). Aprenda a aprovechar el tree shaking y la carga diferida para los diccionarios con Intlayer.
6
+ keywords:
7
+ - Optimización de bundle
8
+ - Automatización de contenido
9
+ - Contenido dinámico
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: "Se añadieron las opciones `minify` y `purge` a la configuración de construcción"
22
+ ---
23
+
24
+ # Optimización del tamaño y rendimiento del bundle i18n
25
+
26
+ Uno de los desafíos más comunes con las soluciones i18n tradicionales que dependen de archivos JSON es la gestión del tamaño del contenido. Si los desarrolladores no separan manualmente el contenido en namespaces, los usuarios a menudo terminan descargando traducciones para cada página y potencialmente para cada idioma solo para ver una sola página.
27
+
28
+ Por ejemplo, una aplicación con 10 páginas traducidas a 10 idiomas podría resultar en que un usuario descargue el contenido de 100 páginas, aunque solo necesite **una** (la página actual en el idioma actual). Esto conduce a un desperdicio de ancho de banda y tiempos de carga más lentos.
29
+
30
+ **Intlayer resuelve este problema a través de la optimización en tiempo de compilación.** Analiza su código para detectar qué diccionarios se usan realmente por componente y reinyecta solo el contenido necesario en su bundle.
31
+
32
+ ## Tabla de contenidos
33
+
34
+ <TOC />
35
+
36
+ ## Escanee su bundle
37
+
38
+ Analizar su bundle es el primer paso para identificar archivos JSON "pesados" y oportunidades de división de código (code-splitting). Estas herramientas generan un mapa de árbol visual del código compilado de su aplicación, lo que le permite ver exactamente qué librerías están consumiendo más espacio.
39
+
40
+ <Tabs>
41
+ <Tab value="vite">
42
+
43
+ ### Vite / Rollup
44
+
45
+ Vite utiliza Rollup internamente. El complemento `rollup-plugin-visualizer` genera un archivo HTML interactivo que muestra el tamaño de cada módulo en su gráfico.
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, // Abrir automáticamente el informe en su navegador
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
+ Para proyectos que utilizan App Router y Turbopack, Next.js proporciona un analizador experimental integrado que no requiere dependencias adicionales.
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 está utilizando el empaquetador Webpack predeterminado en Next.js, use el analizador de bundle oficial. Actívelo configurando una variable de entorno durante su construcción.
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
+ // Su configuración de Next.js
120
+ });
121
+ ```
122
+
123
+ **Uso:**
124
+
125
+ ```bash
126
+ ANALYZE=true npm run build
127
+ ```
128
+
129
+ </Tab>
130
+ <Tab value="Webpack (CRA / Angular / etc)">
131
+
132
+ ### Webpack estándar
133
+
134
+ Para Create React App (ejected), Angular o configuraciones personalizadas de Webpack, use el estándar de la industria `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
+ ## Cómo funciona
170
+
171
+ Intlayer utiliza un **enfoque por componente**. A diferencia de los archivos JSON globales, su contenido se define junto o dentro de sus componentes. Durante el proceso de construcción, Intlayer:
172
+
173
+ 1. **Analiza** su código para encontrar llamadas a `useIntlayer`.
174
+ 2. **Construye** el contenido del diccionario correspondiente.
175
+ 3. **Reemplaza** la llamada a `useIntlayer` con código optimizado basado en su configuración.
176
+
177
+ Esto garantiza que:
178
+
179
+ - Si un componente no se importa, su contenido no se incluye en el bundle (eliminación de código muerto).
180
+ - Si un componente se carga de forma diferida (lazy-loading), su contenido también se carga de forma diferida.
181
+
182
+ ## Configuración por plataforma
183
+
184
+ <Tabs>
185
+ <Tab value="nextjs">
186
+
187
+ ### Next.js
188
+
189
+ Next.js requiere el complemento `@intlayer/swc` para manejar la transformación, ya que Next.js utiliza SWC para las construcciones.
190
+
191
+ > Este complemento no se instala de forma predeterminada porque los complementos de SWC todavía son experimentales para Next.js. Podría cambiar en el futuro.
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
+ Una vez instalado, Intlayer detectará y utilizará automáticamente el complemento.
210
+
211
+ </Tab>
212
+ <Tab value="vite">
213
+
214
+ ### Vite
215
+
216
+ Vite utiliza el complemento `@intlayer/babel`, que se incluye como dependencia de `vite-intlayer`. La optimización está habilitada de forma predeterminada. No hay nada más que hacer.
217
+
218
+ </Tab>
219
+ <Tab value="webpack">
220
+
221
+ ### Webpack
222
+
223
+ Para habilitar la optimización del bundle con Intlayer en Webpack, debe instalar y configurar el complemento Babel (`@intlayer/babel`) o SWC (`@intlayer/swc`) adecuado.
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
+ ## Configuración
256
+
257
+ Puede controlar cómo Intlayer optimiza su bundle a través de la propiedad `build` en su `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
+ * Minificar los diccionarios para reducir el tamaño del bundle.
273
+ */
274
+ minify: true;
275
+
276
+ /**
277
+ * Purgar las claves no utilizadas en los diccionarios
278
+ */
279
+ purge: true;
280
+
281
+ /**
282
+ * Indica si la construcción debe verificar los tipos de TypeScript
283
+ */
284
+ checkTypes: false;
285
+ },
286
+ };
287
+
288
+ export default config;
289
+ ```
290
+
291
+ > Se recomienda mantener la opción predeterminada para `optimize` en la gran mayoría de los casos.
292
+
293
+ > Consulte la documentación de configuración para más detalles: [Configuración](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/configuration.md)
294
+
295
+ ### Opciones de construcción
296
+
297
+ Las siguientes opciones están disponibles bajo el objeto de configuración `build`:
298
+
299
+ | Propiedad | Tipo | Predeterminado | Descripción |
300
+ | :------------- | :-------- | :------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
301
+ | **`optimize`** | `boolean` | `undefined` | Controla si la optimización de la construcción está habilitada. Si es `true`, Intlayer reemplaza las llamadas a diccionarios con inyecciones optimizadas. Si es `false`, la optimización se deshabilita. Ideal en prod. |
302
+ | **`minify`** | `boolean` | `false` | Si se deben minificar los diccionarios para reducir el tamaño del bundle. |
303
+ | **`purge`** | `boolean` | `false` | Si se deben purgar las claves no utilizadas en los diccionarios. |
304
+
305
+ ### Minificación
306
+
307
+ Minificar diccionarios elimina espacios en blanco innecesarios, comentarios y reduce el tamaño del contenido JSON. Esto es especialmente útil para diccionarios grandes.
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
+ > Nota: La minificación se ignora si `optimize` está deshabilitado o si el Editor Visual está habilitado (ya que el editor necesita el contenido completo para permitir la edición).
322
+
323
+ ### Purgado
324
+
325
+ El purgado garantiza que solo las claves realmente utilizadas en su código se incluyan en el bundle final de diccionarios. Esto puede reducir significativamente el tamaño de su bundle si tiene diccionarios grandes con muchas claves que no se usan en todas las partes de su aplicación.
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
+ > Nota: El purgado se ignora si `optimize` está deshabilitado.
340
+
341
+ ### Modo de importación
342
+
343
+ Para aplicaciones grandes, que incluyen varias páginas y configuraciones regionales, sus archivos JSON pueden representar una parte significativa del tamaño de su bundle. Intlayer le permite controlar cómo se cargan los diccionarios.
344
+
345
+ El modo de importación puede definirse por defecto globalmente en su archivo `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
+ Así como para cada diccionario en sus archivos `.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", // Sobrescribir el modo de importación predeterminado
367
+ content: {
368
+ // ...
369
+ },
370
+ };
371
+
372
+ export default appContent;
373
+ ```
374
+
375
+ | Propiedad | Tipo | Predeterminado | Descripción |
376
+ | :--------------- | :--------------------------------- | :------------- | :------------------------------------------------------------------------------------------------------------------------------ |
377
+ | **`importMode`** | `'static'`, `'dynamic'`, `'fetch'` | `'static'` | **Obsoleto**: Use `dictionary.importMode` en su lugar. Determina cómo se cargan los diccionarios (ver detalles a continuación). |
378
+
379
+ La configuración `importMode` dicta cómo se inyecta el contenido del diccionario en su componente.
380
+ Puede definirlo globalmente en el archivo `intlayer.config.ts` bajo el objeto `dictionary`, o puede sobrescribirlo para un diccionario específico en su archivo `.content.ts`.
381
+
382
+ ### 1. Modo estático (`default`)
383
+
384
+ En modo estático, Intlayer reemplaza `useIntlayer` con `useDictionary` e inyecta el diccionario directamente en el bundle de JavaScript.
385
+
386
+ - **Pros:** Renderizado instantáneo (síncrono), cero solicitudes de red adicionales durante la hidratación.
387
+ - **Contras:** El bundle incluye traducciones para **todos** los idiomas disponibles para ese componente específico.
388
+ - **Ideal para:** Aplicaciones de una sola página (SPA).
389
+
390
+ **Ejemplo de código transformado:**
391
+
392
+ ```tsx
393
+ // Su código
394
+ const content = useIntlayer("my-key");
395
+
396
+ // Código optimizado (Estatico)
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. Modo dinámico
410
+
411
+ En modo dinámico, Intlayer reemplaza `useIntlayer` con `useDictionaryAsync`. Esto utiliza `import()` (mecanismo similar a Suspense) para cargar de forma diferida específicamente el JSON para la configuración regional actual.
412
+
413
+ - **Pros:** **Tree shaking a nivel de locale.** Un usuario que vea la versión en inglés _solo_ descargará el diccionario en inglés. El diccionario en francés nunca se carga.
414
+ - **Contras:** Activa una solicitud de red (obtención de activos) por componente durante la hidratación.
415
+ - **Ideal para:** Bloques de texto grandes, artículos o aplicaciones que admiten muchos idiomas donde el tamaño del bundle es crítico.
416
+
417
+ **Ejemplo de código transformado:**
418
+
419
+ ```tsx
420
+ // Su código
421
+ const content = useIntlayer("my-key");
422
+
423
+ // Código optimizado (Dinámico)
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
+ > Al usar `importMode: 'dynamic'`, si tiene 100 componentes que usan `useIntlayer` en una sola página, el navegador intentará 100 descargas separadas. Para evitar esta "cascada" de solicitudes, agrupe el contenido en menos archivos `.content` (por ejemplo, un diccionario por sección de la página) en lugar de uno por componente átomo.
437
+
438
+ ### 3. Modo Fetch
439
+
440
+ Se comporta de manera similar al modo dinámico, pero intenta obtener diccionarios de la API de Live Sync de Intlayer primero. Si la llamada a la API falla o el contenido no está marcado para actualizaciones en vivo, recurre a la importación dinámica.
441
+
442
+ > Consulte la documentación del CMS para más detalles: [CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/intlayer_CMS.md)
443
+
444
+ > En modo fetch, no se pueden usar el purgado y la minificación.
445
+
446
+ ## Resumen: Estático vs Dinámico
447
+
448
+ | Característica | Modo estático | Modo dinámico |
449
+ | :----------------------- | :-------------------------------------------------------- | :---------------------------------------- |
450
+ | **Tamaño del bundle JS** | Más grande (incluye todos los idiomas para el comp.) | Más pequeño (solo código, sin contenido) |
451
+ | **Carga inicial** | Instantánea (El contenido está en el bundle) | Ligero retraso (Obtiene el JSON) |
452
+ | **Solicitudes de red** | 0 solicitudes adicionales | 1 solicitud por diccionario |
453
+ | **Tree Shaking** | A nivel de componente | A nivel de componente + A nivel de locale |
454
+ | **Mejor caso de uso** | Componentes de interfaz de usuario, aplicaciones pequeñas | Páginas con mucho texto, muchos idiomas |
@@ -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
- // Utilidad 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
- // Ayudantes
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 @@ Luego podemos crear un hook `useLocalizedNavigate` para la navegación programá
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
  },