@intlayer/docs 8.9.4 → 8.9.6-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/docs/ar/benchmark/index.md +0 -3
  2. package/docs/ar/benchmark/nextjs.md +15 -6
  3. package/docs/ar/benchmark/solid.md +155 -0
  4. package/docs/ar/benchmark/svelte.md +148 -0
  5. package/docs/ar/benchmark/tanstack.md +12 -3
  6. package/docs/ar/benchmark/vue.md +160 -0
  7. package/docs/ar/configuration.md +16 -12
  8. package/docs/ar/dictionary/content_file.md +51 -1
  9. package/docs/ar/plugins/sync-po.md +0 -21
  10. package/docs/bn/configuration.md +16 -12
  11. package/docs/cs/configuration.md +16 -12
  12. package/docs/de/benchmark/index.md +0 -3
  13. package/docs/de/benchmark/nextjs.md +15 -6
  14. package/docs/de/benchmark/solid.md +155 -0
  15. package/docs/de/benchmark/svelte.md +148 -0
  16. package/docs/de/benchmark/tanstack.md +12 -3
  17. package/docs/de/benchmark/vue.md +160 -0
  18. package/docs/de/configuration.md +16 -12
  19. package/docs/de/dictionary/content_file.md +52 -2
  20. package/docs/de/plugins/sync-po.md +0 -22
  21. package/docs/en/benchmark/nextjs.md +11 -2
  22. package/docs/en/benchmark/solid.md +22 -4
  23. package/docs/en/benchmark/svelte.md +17 -5
  24. package/docs/en/benchmark/tanstack.md +18 -3
  25. package/docs/en/benchmark/vue.md +17 -11
  26. package/docs/en/configuration.md +16 -13
  27. package/docs/en/dictionary/content_file.md +51 -1
  28. package/docs/en/plugins/sync-po.md +0 -21
  29. package/docs/en-GB/benchmark/index.md +0 -3
  30. package/docs/en-GB/benchmark/nextjs.md +15 -6
  31. package/docs/en-GB/benchmark/solid.md +155 -0
  32. package/docs/en-GB/benchmark/svelte.md +148 -0
  33. package/docs/en-GB/benchmark/tanstack.md +12 -3
  34. package/docs/en-GB/benchmark/vue.md +160 -0
  35. package/docs/en-GB/configuration.md +15 -11
  36. package/docs/en-GB/dictionary/content_file.md +51 -1
  37. package/docs/en-GB/plugins/sync-po.md +0 -21
  38. package/docs/es/benchmark/index.md +0 -3
  39. package/docs/es/benchmark/nextjs.md +15 -6
  40. package/docs/es/benchmark/solid.md +155 -0
  41. package/docs/es/benchmark/svelte.md +148 -0
  42. package/docs/es/benchmark/tanstack.md +12 -3
  43. package/docs/es/benchmark/vue.md +160 -0
  44. package/docs/es/configuration.md +16 -12
  45. package/docs/es/dictionary/content_file.md +51 -1
  46. package/docs/es/plugins/sync-po.md +0 -21
  47. package/docs/fr/benchmark/index.md +0 -3
  48. package/docs/fr/benchmark/nextjs.md +15 -6
  49. package/docs/fr/benchmark/solid.md +155 -0
  50. package/docs/fr/benchmark/svelte.md +148 -0
  51. package/docs/fr/benchmark/tanstack.md +12 -3
  52. package/docs/fr/benchmark/vue.md +160 -0
  53. package/docs/fr/configuration.md +16 -12
  54. package/docs/fr/dictionary/content_file.md +51 -1
  55. package/docs/fr/plugins/sync-po.md +0 -21
  56. package/docs/hi/benchmark/nextjs.md +15 -6
  57. package/docs/hi/benchmark/solid.md +155 -0
  58. package/docs/hi/benchmark/svelte.md +148 -0
  59. package/docs/hi/benchmark/tanstack.md +12 -3
  60. package/docs/hi/benchmark/vue.md +160 -0
  61. package/docs/hi/configuration.md +16 -12
  62. package/docs/hi/dictionary/content_file.md +51 -1
  63. package/docs/hi/plugins/sync-po.md +0 -21
  64. package/docs/id/benchmark/index.md +0 -3
  65. package/docs/id/benchmark/nextjs.md +15 -6
  66. package/docs/id/benchmark/solid.md +155 -0
  67. package/docs/id/benchmark/svelte.md +148 -0
  68. package/docs/id/benchmark/tanstack.md +12 -3
  69. package/docs/id/benchmark/vue.md +160 -0
  70. package/docs/id/configuration.md +16 -12
  71. package/docs/id/dictionary/content_file.md +51 -1
  72. package/docs/id/plugins/sync-po.md +0 -21
  73. package/docs/it/benchmark/index.md +1 -4
  74. package/docs/it/benchmark/nextjs.md +15 -6
  75. package/docs/it/benchmark/solid.md +155 -0
  76. package/docs/it/benchmark/svelte.md +148 -0
  77. package/docs/it/benchmark/tanstack.md +12 -3
  78. package/docs/it/benchmark/vue.md +160 -0
  79. package/docs/it/configuration.md +16 -12
  80. package/docs/it/dictionary/content_file.md +51 -1
  81. package/docs/it/plugins/sync-po.md +0 -21
  82. package/docs/ja/benchmark/index.md +5 -5
  83. package/docs/ja/benchmark/nextjs.md +15 -6
  84. package/docs/ja/benchmark/solid.md +155 -0
  85. package/docs/ja/benchmark/svelte.md +148 -0
  86. package/docs/ja/benchmark/tanstack.md +12 -3
  87. package/docs/ja/benchmark/vue.md +160 -0
  88. package/docs/ja/configuration.md +16 -12
  89. package/docs/ja/dictionary/content_file.md +50 -2
  90. package/docs/ja/intlayer_with_nextjs_no_locale_path.md +4 -3
  91. package/docs/ja/plugins/sync-po.md +0 -21
  92. package/docs/ko/benchmark/nextjs.md +15 -6
  93. package/docs/ko/benchmark/solid.md +155 -0
  94. package/docs/ko/benchmark/svelte.md +148 -0
  95. package/docs/ko/benchmark/tanstack.md +12 -3
  96. package/docs/ko/benchmark/vue.md +160 -0
  97. package/docs/ko/configuration.md +16 -12
  98. package/docs/ko/dictionary/content_file.md +51 -1
  99. package/docs/ko/intlayer_with_nextjs_no_locale_path.md +3 -2
  100. package/docs/ko/plugins/sync-po.md +0 -21
  101. package/docs/nl/configuration.md +16 -12
  102. package/docs/pl/benchmark/index.md +0 -3
  103. package/docs/pl/benchmark/nextjs.md +15 -6
  104. package/docs/pl/benchmark/solid.md +155 -0
  105. package/docs/pl/benchmark/svelte.md +148 -0
  106. package/docs/pl/benchmark/tanstack.md +12 -3
  107. package/docs/pl/benchmark/vue.md +160 -0
  108. package/docs/pl/configuration.md +16 -12
  109. package/docs/pl/dictionary/content_file.md +51 -1
  110. package/docs/pl/plugins/sync-po.md +0 -21
  111. package/docs/pt/benchmark/index.md +0 -3
  112. package/docs/pt/benchmark/nextjs.md +16 -7
  113. package/docs/pt/benchmark/solid.md +155 -0
  114. package/docs/pt/benchmark/svelte.md +148 -0
  115. package/docs/pt/benchmark/tanstack.md +13 -4
  116. package/docs/pt/benchmark/vue.md +160 -0
  117. package/docs/pt/configuration.md +16 -12
  118. package/docs/pt/dictionary/content_file.md +51 -1
  119. package/docs/pt/plugins/sync-po.md +0 -21
  120. package/docs/ru/benchmark/nextjs.md +15 -6
  121. package/docs/ru/benchmark/solid.md +155 -0
  122. package/docs/ru/benchmark/svelte.md +148 -0
  123. package/docs/ru/benchmark/tanstack.md +12 -3
  124. package/docs/ru/benchmark/vue.md +160 -0
  125. package/docs/ru/configuration.md +16 -12
  126. package/docs/ru/dictionary/content_file.md +52 -2
  127. package/docs/ru/plugins/sync-po.md +0 -21
  128. package/docs/tr/benchmark/index.md +0 -3
  129. package/docs/tr/benchmark/nextjs.md +15 -6
  130. package/docs/tr/benchmark/solid.md +155 -0
  131. package/docs/tr/benchmark/svelte.md +148 -0
  132. package/docs/tr/benchmark/tanstack.md +12 -3
  133. package/docs/tr/benchmark/vue.md +160 -0
  134. package/docs/tr/configuration.md +16 -12
  135. package/docs/tr/dictionary/content_file.md +51 -1
  136. package/docs/tr/plugins/sync-po.md +0 -21
  137. package/docs/uk/benchmark/nextjs.md +15 -6
  138. package/docs/uk/benchmark/solid.md +155 -0
  139. package/docs/uk/benchmark/svelte.md +148 -0
  140. package/docs/uk/benchmark/tanstack.md +12 -3
  141. package/docs/uk/benchmark/vue.md +160 -0
  142. package/docs/uk/configuration.md +16 -12
  143. package/docs/uk/dictionary/content_file.md +51 -1
  144. package/docs/uk/plugins/sync-po.md +0 -21
  145. package/docs/ur/configuration.md +16 -12
  146. package/docs/vi/benchmark/index.md +0 -3
  147. package/docs/vi/benchmark/nextjs.md +15 -6
  148. package/docs/vi/benchmark/solid.md +155 -0
  149. package/docs/vi/benchmark/svelte.md +148 -0
  150. package/docs/vi/benchmark/tanstack.md +12 -3
  151. package/docs/vi/benchmark/vue.md +160 -0
  152. package/docs/vi/configuration.md +16 -12
  153. package/docs/vi/dictionary/content_file.md +51 -1
  154. package/docs/vi/intlayer_with_nextjs_15.md +10 -57
  155. package/docs/vi/plugins/sync-po.md +0 -21
  156. package/docs/zh/benchmark/nextjs.md +15 -6
  157. package/docs/zh/benchmark/solid.md +155 -0
  158. package/docs/zh/benchmark/svelte.md +148 -0
  159. package/docs/zh/benchmark/tanstack.md +12 -3
  160. package/docs/zh/benchmark/vue.md +160 -0
  161. package/docs/zh/configuration.md +16 -12
  162. package/docs/zh/dictionary/content_file.md +51 -3
  163. package/docs/zh/plugins/sync-po.md +0 -21
  164. package/frequent_questions/ar/intlayerNode.md +3 -3
  165. package/frequent_questions/de/intlayerNode.md +3 -3
  166. package/frequent_questions/en/intlayerNode.md +3 -3
  167. package/frequent_questions/en-GB/intlayerNode.md +3 -3
  168. package/frequent_questions/es/intlayerNode.md +3 -3
  169. package/frequent_questions/fr/intlayerNode.md +3 -3
  170. package/frequent_questions/hi/intlayerNode.md +3 -3
  171. package/frequent_questions/id/intlayerNode.md +3 -3
  172. package/frequent_questions/it/intlayerNode.md +3 -3
  173. package/frequent_questions/ja/intlayerNode.md +3 -3
  174. package/frequent_questions/ko/intlayerNode.md +3 -3
  175. package/frequent_questions/pl/intlayerNode.md +3 -3
  176. package/frequent_questions/pt/intlayerNode.md +3 -3
  177. package/frequent_questions/ru/intlayerNode.md +3 -3
  178. package/frequent_questions/tr/intlayerNode.md +3 -3
  179. package/frequent_questions/uk/intlayerNode.md +3 -3
  180. package/frequent_questions/vi/intlayerNode.md +3 -3
  181. package/frequent_questions/zh/intlayerNode.md +3 -3
  182. package/package.json +8 -8
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  createdAt: 2025-02-07
3
- updatedAt: 2026-01-28
3
+ updatedAt: 2026-05-12
4
4
  title: Archivo de Contenido
5
5
  description: Aprende a personalizar las extensiones para tus archivos de declaración de contenido. Sigue esta documentación para implementar condiciones de manera eficiente en tu proyecto.
6
6
  keywords:
@@ -12,6 +12,9 @@ slugs:
12
12
  - concept
13
13
  - content
14
14
  history:
15
+ - version: 8.9.0
16
+ date: 2026-05-12
17
+ changes: "Añadir tipo de nodo de contenido `plural`"
15
18
  - version: 8.0.0
16
19
  date: 2026-01-28
17
20
  changes: "Añadir tipo de nodo de contenido `html`"
@@ -66,6 +69,7 @@ import { type ReactNode } from "react";
66
69
  import {
67
70
  t,
68
71
  enu,
72
+ plural,
69
73
  cond,
70
74
  nest,
71
75
  md,
@@ -85,6 +89,7 @@ interface Content {
85
89
  };
86
90
  multilingualContent: string;
87
91
  quantityContent: string;
92
+ pluralContent: string;
88
93
  conditionalContent: string;
89
94
  markdownContent: never;
90
95
  htmlContent: never;
@@ -120,6 +125,10 @@ export default {
120
125
  ">5": "Algunos coches",
121
126
  ">19": "Muchos coches",
122
127
  }),
128
+ pluralContent: plural({
129
+ one: "One car",
130
+ other: "{{count}} cars",
131
+ }),
123
132
  conditionalContent: cond({
124
133
  true: "La validación está habilitada",
125
134
  false: "La validación está deshabilitada",
@@ -174,6 +183,13 @@ export default {
174
183
  ">5": "Algunos coches",
175
184
  ">19": "Muchos coches",
176
185
  },
186
+ "pluralContent": {
187
+ "nodeType": "plural",
188
+ "plural": {
189
+ "one": "One car",
190
+ "other": "{{count}} cars",
191
+ },
192
+ },
177
193
  },
178
194
  "conditionalContent": {
179
195
  "nodeType": "condición",
@@ -221,6 +237,7 @@ Los nodos de contenido son los bloques de construcción del contenido del diccio
221
237
  - **Valores primitivos**: cadenas, números, booleanos, null, undefined
222
238
  - **Nodos tipados**: Tipos especiales de contenido como traducciones, condiciones, markdown, etc.
223
239
  - **Funciones**: Contenido dinámico que puede evaluarse en tiempo de ejecución [ver Obtención de Funciones](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/dictionary/function_fetching.md)
240
+ - **Contenido Plural**: Ver Contenido Plural [Ver Contenido Plural](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/dictionary/plural.md)
224
241
  - **Contenido anidado**: Referencias a otros diccionarios
225
242
 
226
243
  #### Tipos de Contenido
@@ -539,6 +556,8 @@ multilingualContent: t({
539
556
  });
540
557
  ```
541
558
 
559
+ > Ver [Contenido de Traducción (`t`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/dictionary/translation.md) para más información.
560
+
542
561
  ### Contenido Condicional (`cond`)
543
562
 
544
563
  Contenido que cambia basado en condiciones booleanas:
@@ -552,6 +571,8 @@ conditionalContent: cond({
552
571
  });
553
572
  ```
554
573
 
574
+ > Ver [Contenido Condicional (`cond`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/dictionary/condition.md) para más información.
575
+
555
576
  ### Contenido de Enumeración (`enu`)
556
577
 
557
578
  Contenido que varía según valores enumerados:
@@ -566,6 +587,23 @@ statusContent: enu({
566
587
  });
567
588
  ```
568
589
 
590
+ > Ver [Contenido de Enumeración (`enu`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/dictionary/enumeration.md) para más información.
591
+
592
+ ### Contenido Plural (`plural`)
593
+
594
+ Contenido que varía según las reglas de plural:
595
+
596
+ ```typescript
597
+ import { plural } from "intlayer";
598
+
599
+ pluralContent: plural({
600
+ one: "One car",
601
+ other: "{{count}} cars",
602
+ });
603
+ ```
604
+
605
+ > Ver [Contenido Plural Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/dictionary/plural.md) para más información.
606
+
569
607
  ### Contenido de Inserción (`insert`)
570
608
 
571
609
  Contenido que puede ser insertado en otro contenido:
@@ -576,6 +614,8 @@ import { insert } from "intlayer";
576
614
  insertionContent: insert("Este texto puede ser insertado en cualquier lugar");
577
615
  ```
578
616
 
617
+ > Ver [Contenido de Inserción (`insert`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/dictionary/insertion.md) para más información.
618
+
579
619
  ### Contenido Anidado (`nest`)
580
620
 
581
621
  Referencias a otros diccionarios:
@@ -586,6 +626,8 @@ import { nest } from "intlayer";
586
626
  nestedContent: nest("about-page");
587
627
  ```
588
628
 
629
+ > Ver [Contenido Anidado (`nest`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/dictionary/nesting.md) para más información.
630
+
589
631
  ### Contenido Markdown (`md`)
590
632
 
591
633
  Contenido de texto enriquecido en formato Markdown:
@@ -598,6 +640,8 @@ markdownContent: md(
598
640
  );
599
641
  ```
600
642
 
643
+ > Ver [Contenido Markdown (`md`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/dictionary/markdown.md) para más información.
644
+
601
645
  ### Contenido HTML (`html`)
602
646
 
603
647
  Contenido HTML enriquecido que puede usar etiquetas estándar o componentes personalizados:
@@ -615,6 +659,8 @@ localizedHtmlContent: t({
615
659
  });
616
660
  ```
617
661
 
662
+ > Ver [Contenido HTML (`html`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/dictionary/html.md) para más información.
663
+
618
664
  ### Contenido según género (`gender`)
619
665
 
620
666
  Contenido que varía según el género:
@@ -629,6 +675,8 @@ genderContent: gender({
629
675
  });
630
676
  ```
631
677
 
678
+ > Ver [Contenido según género (`gender`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/dictionary/gender.md) para más información.
679
+
632
680
  ### Contenido de archivo (`file`)
633
681
 
634
682
  Referencias a archivos externos:
@@ -639,6 +687,8 @@ import { file } from "intlayer";
639
687
  fileContent: file("./path/to/content.txt");
640
688
  ```
641
689
 
690
+ > Ver [Contenido de archivo (`file`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/dictionary/file.md) para más información.
691
+
642
692
  ## Creación de archivos de contenido
643
693
 
644
694
  ### Estructura básica de un archivo de contenido
@@ -160,30 +160,9 @@ syncPO({
160
160
  source: ({ key, locale }) => string, // requerido
161
161
  location?: string, // etiqueta opcional, por defecto: "sync-po::path/to/source"
162
162
  priority?: number, // prioridad opcional para resolución de conflictos, por defecto: 0
163
- format?: 'icu' | 'i18next' | 'vue-i18n', // opcional, solo necesario cuando tus valores msgstr usan una sintaxis de interpolación específica
164
163
  });
165
164
  ```
166
165
 
167
- #### `format` ('icu' | 'i18next' | 'vue-i18n')
168
-
169
- Los archivos PO son siempre archivos Gettext Portable Object — eso es fijo. Esta opción solo describe la **sintaxis de interpolación** utilizada dentro de los valores `msgstr`, para que Intlayer pueda convertirlos a su propio formato en el momento del análisis (a través de `formatDictionary`) y de vuelta al escribir la salida.
170
-
171
- - `undefined` _(por defecto)_: los valores `msgstr` se tratan como cadenas simples — sin transformación. Úsalo para la mayoría de los archivos PO.
172
- - `'icu'`: los valores `msgstr` utilizan la sintaxis de mensajes ICU (ej. `{count, plural, one {# item} other {# items}}`).
173
- - `'i18next'`: los valores `msgstr` utilizan la sintaxis de interpolación de i18next (ej. `{{variable}}`).
174
- - `'vue-i18n'`: los valores `msgstr` utilizan la sintaxis de Vue I18n.
175
-
176
- > La transformación se aplica mediante `formatDictionary` de `@intlayer/chokidar` al cargar, y se revierte con `formatDictionaryOutput` al escribir. Para reglas complejas como los plurales de ICU, no se garantiza la fidelidad del viaje de ida y vuelta.
177
-
178
- **Ejemplo — los archivos PO contienen interpolación al estilo i18next:**
179
-
180
- ```ts
181
- syncPO({
182
- source: ({ key, locale }) => `./locales/${locale}/${key}.po`,
183
- format: "i18next",
184
- }),
185
- ```
186
-
187
166
  ### Múltiples fuentes de PO y prioridad
188
167
 
189
168
  Puedes añadir múltiples plugins `syncPO` para sincronizar diferentes fuentes de PO. Esto es útil cuando tienes múltiples fuentes de traducción o diferentes estructuras de PO en tu proyecto.
@@ -30,6 +30,3 @@ Les rapports détaillés et la documentation technique pour chaque framework se
30
30
  - [**Vue Benchmark Report**](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/vue.md)
31
31
  - [**Solid Benchmark Report**](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/solid.md)
32
32
  - [**Svelte Benchmark Report**](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/svelte.md)
33
- - [**Vue Benchmark Report**](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/vue.md)
34
- - [**Solid Benchmark Report**](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/solid.md)
35
- - [**Svelte Benchmark Report**](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/svelte.md)
@@ -61,6 +61,13 @@ Parce que le problème est complexe, de nombreuses solutions existent — certai
61
61
 
62
62
  Intlayer tente d'optimiser l'ensemble de ces dimensions.
63
63
 
64
+ ## TL;DR
65
+
66
+ - **Intlayer** & **next-translate** : Meilleurs choix pour la performance Next.js, offrant l'empreinte la plus faible et le meilleur support du rendu statique.
67
+ - **next-intl** : L'option la plus tendance mais lourde et complexe à optimiser pour les grandes applications.
68
+ - **next-i18next** : Populaire et riche en plugins, mais porte un poids de bundle significatif (~3× Intlayer).
69
+ - **À éviter** : **gt-next** et **lingo.dev** en raison de graves problèmes de performance, de verrouillage propriétaire et de bugs cassant le build.
70
+
64
71
  ## Testez votre application
65
72
 
66
73
  Pour mettre en lumière ces problèmes, j'ai construit un scanner gratuit que vous pouvez essayer [ici](https://intlayer.org/i18n-seo-scanner).
@@ -99,14 +106,14 @@ Enfin, `Intlayer` applique une optimisation au moment du build afin que `useIntl
99
106
  Pour ce benchmark, nous avons comparé les bibliothèques suivantes :
100
107
 
101
108
  - `Base App` (Pas de bibliothèque i18n)
102
- - `next-intlayer` (v8.7.5)
109
+ - `next-intlayer` (v8.7.12)
103
110
  - `next-i18next` (v16.0.5)
104
111
  - `next-intl` (v4.9.1)
105
112
  - `@lingui/core` (v5.3.0)
106
113
  - `next-translate` (v3.1.2)
107
114
  - `next-international` (v1.3.1)
108
115
  - `@inlang/paraglide-js` (v2.15.1)
109
- - `tolgee` (v7.0.0)
116
+ - `@tolgee/react` (v7.0.0)
110
117
  - `@lingo.dev/compiler` (v0.4.0)
111
118
  - `wuchale` (v0.22.11)
112
119
  - `gt-next` (v6.16.5)
@@ -161,10 +168,10 @@ Problèmes rencontrés :
161
168
 
162
169
  **(General Translation)** (`gt-next@6.16.5`) :
163
170
 
164
- - Pour une application de 110 Ko, `gt-react` ajoute plus de 440 Ko supplémentaires.
171
+ - Pour une application de 110 Ko, `gt-next` ajoute plus de 440 Ko supplémentaires.
165
172
  - `Quota Exceeded, please upgrade your plan` dès le tout premier build avec General Translation.
166
173
  - Les traductions ne sont pas rendues ; j'obtiens l'erreur `Error: <T> used on the client-side outside of <GTProvider>`, ce qui semble être un bug de la bibliothèque.
167
- - Lors de l'implémentation de **gt-tanstack-start-react**, je suis également tombé sur un [problème](https://github.com/generaltranslation/gt/issues/1210#event-24510646961) avec la bibliothèque : `does not provide an export named 'printAST' - @formatjs/icu-messageformat-parser`, ce qui cassait l'application. Après avoir signalé ce problème, le mainteneur l'a corrigé sous 24 heures.
174
+ - Lors de l'implémentation de **gt-next**, je suis également tombé sur un [problème](https://github.com/generaltranslation/gt/issues/1210#event-24510646961) avec la bibliothèque : `does not provide an export named 'printAST' - @formatjs/icu-messageformat-parser`, ce qui cassait l'application. Après avoir signalé ce problème, le mainteneur l'a corrigé sous 24 heures.
168
175
  - La bibliothèque bloque le rendu statique des pages Next.js.
169
176
 
170
177
  **(Lingo.dev)** (`@lingo.dev/compiler@0.4.0`) :
@@ -186,9 +193,11 @@ L'idée derrière `Wuchale` est intéressante mais pas encore viable. J'ai renco
186
193
  Personnellement, je n'aime pas devoir régénérer des fichiers JS avant chaque push, ce qui crée un risque constant de conflit de fusion via les PRs. L'outil semble également plus axé sur Vite que sur Next.js.
187
194
  Enfin, par rapport aux autres solutions, Paraglide n'utilise pas de "store" (ex: contexte React) pour récupérer la langue actuelle afin de rendre le contenu. Pour chaque nœud analysé, il demandera la langue au localStorage / cookie etc. Cela conduit à l'exécution d'une logique inutile qui impacte la réactivité des composants.
188
195
 
196
+ > Note sur paraglide : la solution injecte du code dans votre base de code à importer, par conséquent la métrique 'taille de la lib' dans le rapport de benchmark est presque de 0. La génération de code est une bonne chose, car la fonction utilisée n'inclura que la logique nécessaire (préfixe total vs pas de préfixe, cookie vs stockage etc). En comparaison, Intlayer procède à ce filtrage via des injections de variables d'environnement dans le build pour forcer le bundler à tree-shaker le contenu selon la logique. Grâce à cela, paraglide et intlayer finissent par être des solutions 6 à 10 fois plus légères que i18next ou next-intl.
197
+
189
198
  ### 3 — Solutions acceptables
190
199
 
191
- **(Tolgee)** (`tolgee@7.0.0`) :
200
+ **(Tolgee)** (`@tolgee/react@7.0.0`) :
192
201
 
193
202
  `Tolgee` traite bon nombre des problèmes mentionnés plus haut. Je l'ai trouvé plus difficile à adopter que des outils similaires. Il n'offre pas de sécurité de type (type safety), ce qui rend également plus difficile la détection des clés manquantes à la compilation. J'ai dû wrapper les fonctions de Tolgee avec les miennes pour ajouter la détection des clés manquantes.
194
203
 
@@ -216,7 +225,7 @@ Les formats de messages diffèrent également : `next-intl` utilise ICU MessageF
216
225
 
217
226
  `next-translate` est ma recommandation principale si vous aimez une API de style `t()`. C'est élégant via `next-translate-plugin`, chargeant les namespaces via `getStaticProps` avec un loader Webpack / Turbopack. C'est aussi l'option la plus légère ici (env. 2,5 Ko). Pour le découpage en namespaces, la définition par page ou par route dans la config est bien pensée et plus facile à maintenir que les alternatives principales comme **next-intl** ou **next-i18next**. Dans la version `3.1.2`, j'ai noté que le rendu statique ne fonctionnait pas ; Next.js se repliait sur le rendu dynamique.
218
227
 
219
- **(Intlayer)** (`next-intlayer@8.7.5`) :
228
+ **(Intlayer)** (`next-intlayer@8.7.12`) :
220
229
 
221
230
  Je ne jugerai pas personnellement `next-intlayer` par souci d'objectivité, puisqu'il s'agit de ma propre solution.
222
231
 
@@ -0,0 +1,155 @@
1
+ ---
2
+ createdAt: 2026-04-20
3
+ updatedAt: 2026-04-21
4
+ title: La meilleure solution i18n pour Solid en 2026 - Rapport de Benchmark
5
+ description: Comparez les bibliothèques d'internationalisation (i18n) pour Solid comme solid-primitives, solid-i18next et Intlayer. Rapport de performance détaillé sur la taille du bundle, les fuites et la réactivité.
6
+ keywords:
7
+ - benchmark
8
+ - i18n
9
+ - intl
10
+ - solid
11
+ - performance
12
+ - intlayer
13
+ slugs:
14
+ - doc
15
+ - benchmark
16
+ - solid
17
+ author: Aymeric PINEAU
18
+ applicationTemplate: https://github.com/intlayer-org/benchmark-i18n-solid-template
19
+ history:
20
+ - version: 8.7.12
21
+ date: 2026-01-06
22
+ changes: "Initialisation du benchmark"
23
+ ---
24
+
25
+ # Bibliothèques i18n Solid — Rapport de Benchmark 2026
26
+
27
+ Cette page est un rapport de benchmark pour les solutions i18n sur Solid.
28
+
29
+ ## Table des Matières
30
+
31
+ <Toc/>
32
+
33
+ ## Benchmark Interactif
34
+
35
+ <I18nBenchmark framework="vite-solid" vertical/>
36
+
37
+ ## Référence des résultats :
38
+
39
+ <iframe
40
+ src="https://intlayer.org/markdown?url=https%3A%2F%2Fraw.githubusercontent.com%2Fintlayer-org%2Fbenchmark-i18n%2Fmain%2Freport%2Fscripts%2Fsummarize-vite_solid.md"
41
+ width="100%"
42
+ height="600px"
43
+ style="border:none;">
44
+ </iframe>
45
+
46
+ > https://intlayer.org/markdown?url=https%3A%2F%2Fraw.githubusercontent.com%2Fintlayer-org%2Fbenchmark-i18n%2Fmain%2Freport%2Fscripts%2Fsummarize-vite_solid.md
47
+
48
+ Voir le dépôt complet du benchmark [ici](https://github.com/intlayer-org/benchmark-i18n/tree/main).
49
+
50
+ ## Introduction
51
+
52
+ Les solutions d'internationalisation figurent parmi les dépendances les plus lourdes d'une application Solid. Le risque principal est d'embarquer du contenu inutile : les traductions d'autres pages et d'autres locales dans le bundle d'une seule route.
53
+
54
+ À mesure que votre application grandit, ce problème peut rapidement faire exploser la quantité de JavaScript envoyée au client et ralentir la navigation.
55
+
56
+ En pratique, pour les implémentations les moins optimisées, une page internationalisée peut finir par être plusieurs fois plus lourde que la version sans i18n.
57
+
58
+ L'autre impact concerne l'expérience développeur (DX) : la façon dont vous déclarez le contenu, les types, l'organisation des namespaces, le chargement dynamique et la réactivité lors du changement de langue.
59
+
60
+ ## TL;DR
61
+
62
+ - **Intlayer** : Choix recommandé pour les applications Solid professionnelles nécessitant des fonctionnalités avancées et une optimisation poussée (v8.7.12).
63
+ - **@solid-primitives/i18n** : Excellente alternative légère pour les projets simples, bien qu'il manque de fonctionnalités avancées comme le lazy loading.
64
+ - **solid-i18next** : Option standard mais lourde (~4.7× Intlayer) avec les mêmes inconvénients que React i18next.
65
+ - **Paraglide** : Approche innovante mais DX complexe et problèmes de tree-shaking dans certaines configurations.
66
+
67
+ ## Testez votre application
68
+
69
+ Pour repérer rapidement les problèmes de fuite i18n, j'ai mis en place un scanner gratuit disponible [ici](https://intlayer.org/i18n-seo-scanner).
70
+
71
+ <iframe src="https://intlayer.org/i18n-seo-scanner" width="100%" height="600px" style="border:none;"/>
72
+
73
+ ## Le problème
74
+
75
+ Deux leviers sont essentiels pour limiter le coût d'une application multilingue :
76
+
77
+ - Découper le contenu par page / namespace afin de ne pas charger des dictionnaires entiers quand on n'en a pas besoin
78
+ - Charger la bonne locale dynamiquement, uniquement quand nécessaire
79
+
80
+ Comprendre les limitations techniques de ces approches :
81
+
82
+ **Chargement dynamique**
83
+
84
+ Sans chargement dynamique, la plupart des solutions gardent les messages en mémoire dès le premier rendu, ce qui ajoute un surcoût important pour les applications ayant beaucoup de routes et de langues.
85
+
86
+ Avec le chargement dynamique, vous acceptez un compromis : moins de JS initial, mais parfois une requête supplémentaire lors du changement de langue.
87
+
88
+ **Découpage du contenu (Splitting)**
89
+
90
+ Les syntaxes basées sur `t('a.b.c')` sont très pratiques mais encouragent souvent la conservation de gros objets JSON au runtime. Ce modèle rend le tree-shaking difficile à moins que la bibliothèque ne propose une réelle stratégie de découpage par page.
91
+
92
+ ## Méthodologie
93
+
94
+ Pour ce benchmark, nous avons comparé les bibliothèques suivantes :
95
+
96
+ - `Base App` (Pas de bibliothèque i18n)
97
+ - `solid-intlayer` (v8.7.12)
98
+ - `@solid-primitives/i18n` (v2.2.1)
99
+ - `solid-i18next` (v17.0.2)
100
+ - `@inlang/paraglide-js` (v2.17.0)
101
+
102
+ Le framework utilisé est `Solid` avec une application multilingue de **10 pages** et **10 langues**.
103
+
104
+ Nous avons comparé **quatre stratégies de chargement** :
105
+
106
+ | Stratégie | Sans namespaces (global) | Avec namespaces (scoped) |
107
+ | :----------------------- | :------------------------------------------------ | :------------------------------------------------------------------- |
108
+ | **Chargement statique** | **Static** : Tout en mémoire au démarrage. | **Scoped static** : Divisé par namespace ; tout chargé au démarrage. |
109
+ | **Chargement dynamique** | **Dynamic** : Chargement à la demande par locale. | **Scoped dynamic** : Chargement granulaire par namespace et locale. |
110
+
111
+ ## Résumé des stratégies
112
+
113
+ - **Static** : Simple ; pas de latence réseau après le chargement initial. Inconvénient : taille de bundle importante.
114
+ - **Dynamic** : Réduit le poids initial (lazy-loading). Idéal lorsque vous avez de nombreuses locales.
115
+ - **Scoped static** : Organise bien le code (séparation logique) sans requêtes réseau supplémentaires complexes.
116
+ - **Scoped dynamic** : Meilleure approche pour le _code splitting_ et la performance. Minimise la mémoire en ne chargeant que ce dont la vue actuelle et la locale active ont besoin.
117
+
118
+ ## Résultats détaillés
119
+
120
+ ### 1 — Solutions à éviter
121
+
122
+ > Aucune solution claire à éviter dans l'écosystème Solid.
123
+
124
+ ### 2 — Solutions acceptables
125
+
126
+ **(solid-i18next)** (`solid-i18next@17.0.2`) :
127
+
128
+ `solid-i18next` est probablement l'option la plus populaire car elle fut l'une des premières à servir les besoins i18n des applications JS. Elle dispose également d'un large éventail de plugins communautaires pour des problèmes spécifiques.
129
+
130
+ Le paquet est lourd (~14.6 Ko, soit environ 4.7× `solid-intlayer`).
131
+
132
+ Pourtant, elle partage les mêmes inconvénients majeurs que les stacks basées sur `t('a.b.c')` : les optimisations sont possibles mais très gourmandes en temps, et les gros projets risquent de mauvaises pratiques (namespaces + chargement dynamique + types).
133
+
134
+ **(@solid-primitives/i18n)** (`@solid-primitives/i18n@2.2.1`) :
135
+
136
+ Solid primitive est extrêmement léger et efficace. Je recommande cette solution pour les petits projets, mais elle peut rapidement manquer de fonctionnalités pour des solutions professionnelles incluant la gestion des cookies, la redirection proxy, les formateurs, etc.
137
+ Elle manque également de lazy loading et de découpage des namespaces pour l'optimisation de la taille des pages.
138
+
139
+ **(Paraglide)** (`@inlang/paraglide-js@2.17.0`) :
140
+
141
+ `Paraglide` propose une approche innovante et bien pensée. Pourtant, dans ce benchmark, le tree-shaking dont leur entreprise fait la publicité n'a pas fonctionné pour mon implémentation. Le workflow et la DX sont également plus complexes d'autres options.
142
+ Personnellement, je n'aime pas devoir régénérer des fichiers JS avant chaque push, ce qui crée un risque constant de conflit de fusion via les PRs.
143
+ Enfin, par rapport à d'autres solutions, Paraglide n'utilise pas de store (ex: Solid signal) pour récupérer la locale actuelle afin de rendre le contenu. Pour chaque nœud analysé, il demandera la locale au localStorage / cookie etc. Cela conduit à l'exécution d'une logique inutile qui impacte la réactivité des composants.
144
+
145
+ ### 3 — Recommandations
146
+
147
+ **(Intlayer)** (`solid-intlayer@8.7.12`) :
148
+
149
+ Je ne jugerai pas personnellement `solid-intlayer` par souci d'objectivité, puisqu'il s'agit de ma propre solution.
150
+
151
+ ### Note personnelle
152
+
153
+ Cette note est personnelle et n'affecte pas les résultats du benchmark. Pourtant, dans le monde de l'i18n, on voit souvent un consensus autour d'un pattern comme `const t = useTranslation('xx')` + `<>{t('xx.xx')}</>` pour le contenu traduit.
154
+
155
+ Dans les applications Solid, injecter une fonction en tant que `JSX.Element` est, à mon avis, un anti-pattern. Cela ajoute également une complexité évitable et un surcoût d'exécution JavaScript (même s'il est à peine perceptible).
@@ -0,0 +1,148 @@
1
+ ---
2
+ createdAt: 2026-04-20
3
+ updatedAt: 2026-04-21
4
+ title: La meilleure solution i18n pour Svelte en 2026 - Rapport de Benchmark
5
+ description: Comparez les bibliothèques d'internationalisation (i18n) pour Svelte comme svelte-i18n, Paraglide et Intlayer. Rapport de performance détaillé sur la taille du bundle, les fuites et la réactivité.
6
+ keywords:
7
+ - benchmark
8
+ - i18n
9
+ - intl
10
+ - svelte
11
+ - performance
12
+ - intlayer
13
+ slugs:
14
+ - doc
15
+ - benchmark
16
+ - svelte
17
+ author: Aymeric PINEAU
18
+ applicationTemplate: https://github.com/intlayer-org/benchmark-i18n-svelte-template
19
+ history:
20
+ - version: 8.7.12
21
+ date: 2026-01-06
22
+ changes: "Initialisation du benchmark"
23
+ ---
24
+
25
+ # Bibliothèques i18n Svelte — Rapport de Benchmark 2026
26
+
27
+ Cette page est un rapport de benchmark pour les solutions i18n sur Svelte.
28
+
29
+ ## Table des Matières
30
+
31
+ <Toc/>
32
+
33
+ ## Benchmark Interactif
34
+
35
+ <I18nBenchmark framework="vite-svelte" vertical/>
36
+
37
+ ## Référence des résultats :
38
+
39
+ <iframe
40
+ src="https://intlayer.org/markdown?url=https%3A%2F%2Fraw.githubusercontent.com%2Fintlayer-org%2Fbenchmark-i18n%2Fmain%2Freport%2Fscripts%2Fsummarize-vite_svelte.md"
41
+ width="100%"
42
+ height="600px"
43
+ style="border:none;">
44
+ </iframe>
45
+
46
+ > https://intlayer.org/markdown?url=https%3A%2F%2Fraw.githubusercontent.com%2Fintlayer-org%2Fbenchmark-i18n%2Fmain%2Freport%2Fscripts%2Fsummarize-vite_svelte.md
47
+
48
+ Voir le dépôt complet du benchmark [ici](https://github.com/intlayer-org/benchmark-i18n/tree/main).
49
+
50
+ ## Introduction
51
+
52
+ Les solutions d'internationalisation figurent parmi les dépendances les plus lourdes d'une application Svelte. Le risque principal est d'embarquer du contenu inutile : les traductions d'autres pages et d'autres locales dans le bundle d'une seule route.
53
+
54
+ À mesure que votre application grandit, ce problème peut rapidement faire exploser la quantité de JavaScript envoyée au client et ralentir la navigation.
55
+
56
+ En pratique, pour les implémentations les moins optimisées, une page internationalisée peut finir par être plusieurs fois plus lourde que la version sans i18n.
57
+
58
+ L'autre impact concerne l'expérience développeur (DX) : la façon dont vous déclarez le contenu, les types, l'organisation des namespaces, le chargement dynamique et la réactivité lors du changement de langue.
59
+
60
+ ## TL;DR
61
+
62
+ - **Intlayer** : Le choix le plus performant (v8.7.12) avec l'empreinte la plus faible.
63
+ - **Paraglide** : Candidat sérieux pour le tree-shaking mais possède une expérience développeur plus complexe et un surcoût de réactivité.
64
+ - **svelte-i18n** : Complet et standard pour Svelte, mais transporte un poids de bundle beaucoup plus important (~7× Intlayer).
65
+
66
+ ## Testez votre application
67
+
68
+ Pour repérer rapidement les problèmes de fuite i18n, j'ai mis en place un scanner gratuit disponible [ici](https://intlayer.org/i18n-seo-scanner).
69
+
70
+ <iframe src="https://intlayer.org/i18n-seo-scanner" width="100%" height="600px" style="border:none;"/>
71
+
72
+ ## Le problème
73
+
74
+ Deux leviers sont essentiels pour limiter le coût d'une application multilingue :
75
+
76
+ - Découper le contenu par page / namespace afin de ne pas charger des dictionnaires entiers quand on n'en a pas besoin
77
+ - Charger la bonne locale dynamiquement, uniquement quand nécessaire
78
+
79
+ Comprendre les limitations techniques de ces approches :
80
+
81
+ **Chargement dynamique**
82
+
83
+ Sans chargement dynamique, la plupart des solutions gardent les messages en mémoire dès le premier rendu, ce qui ajoute un surcoût important pour les applications ayant beaucoup de routes et de langues.
84
+
85
+ Avec le chargement dynamique, vous acceptez un compromis : moins de JS initial, mais parfois une requête supplémentaire lors du changement de langue.
86
+
87
+ **Découpage du contenu (Splitting)**
88
+
89
+ Les syntaxes basées sur `t('a.b.c')` sont très pratiques mais encouragent souvent la conservation de gros objets JSON au runtime. Ce modèle rend le tree-shaking difficile à moins que la bibliothèque ne propose une réelle stratégie de découpage par page.
90
+
91
+ ## Méthodologie
92
+
93
+ Pour ce benchmark, nous avons comparé les bibliothèques suivantes :
94
+
95
+ - `Base App` (Pas de bibliothèque i18n)
96
+ - `svelte-intlayer` (v8.7.12)
97
+ - `svelte-i18n` (v4.0.1)
98
+ - `@inlang/paraglide-js` (v2.17.0)
99
+
100
+ Le framework utilisé est `Svelte` avec une application multilingue de **10 pages** et **10 langues**.
101
+
102
+ Nous avons comparé **quatre stratégies de chargement** :
103
+
104
+ | Stratégie | Sans namespaces (global) | Avec namespaces (scoped) |
105
+ | :----------------------- | :------------------------------------------------ | :------------------------------------------------------------------- |
106
+ | **Chargement statique** | **Static** : Tout en mémoire au démarrage. | **Scoped static** : Divisé par namespace ; tout chargé au démarrage. |
107
+ | **Chargement dynamique** | **Dynamic** : Chargement à la demande par locale. | **Scoped dynamic** : Chargement granulaire par namespace et locale. |
108
+
109
+ ## Résumé des stratégies
110
+
111
+ - **Static** : Simple ; pas de latence réseau après le chargement initial. Inconvénient : taille de bundle importante.
112
+ - **Dynamic** : Réduit le poids initial (lazy-loading). Idéal lorsque vous avez de nombreuses locales.
113
+ - **Scoped static** : Organise bien le code (séparation logique) sans requêtes réseau supplémentaires complexes.
114
+ - **Scoped dynamic** : Meilleure approche pour le _code splitting_ et la performance. Minimise la mémoire en ne chargeant que ce dont la vue actuelle et la locale active ont besoin.
115
+
116
+ ## Résultats détaillés
117
+
118
+ ### 1 — Solutions à éviter
119
+
120
+ > Aucune solution claire à éviter dans l'écosystème Svelte.
121
+
122
+ ### 2 — Solutions acceptables
123
+
124
+ **(Paraglide)** (`@inlang/paraglide-js@2.17.0`) :
125
+
126
+ `Paraglide` propose une approche innovante et bien pensée. Dans le contexte d'une application Vite + Svelte, le tree-shaking dont leur entreprise fait la publicité fonctionne comme prévu, ce qui est excellent.
127
+ Mais dans le cas de React + TanStack Start, le tree-shaking n'a pas fonctionné comme prévu, de même pour Next.js. Cela dit, l'usage de Paraglide dans un projet Svelte et TanStack Start mériterait d'être vérifié de près.
128
+ Le workflow et la DX sont également plus complexes qu'avec d'autres options.
129
+ Personnellement, je n'aime pas devoir régénérer des fichiers JS avant chaque push, ce qui crée un risque constant de conflit de fusion via les PRs. L'outil semble également plus axé sur Vite que sur Next.js.
130
+ Enfin, par rapport à d'autres solutions, Paraglide n'utilise pas de store (ex: Svelte store) pour récupérer la locale actuelle afin de rendre le contenu. Pour chaque nœud analysé, il demandera la locale au localStorage / cookie etc. Cela conduit à l'exécution d'une logique inutile qui impacte la réactivité des composants.
131
+
132
+ > Note sur paraglide : cette solution injecte du code dans votre base de code pour les imports, par conséquent, la métrique 'lib size' dans le rapport de benchmark est presque de 0. La génération de code est une bonne chose, car la fonction utilisée n'inclura que la logique nécessaire (préfixe partout vs pas de préfixe, cookie vs stockage, etc.). En comparaison, Intlayer effectue ce filtrage via des injections de variables d'environnement pendant le build pour forcer le bundler à tree-shaker le contenu en fonction de la logique. Grâce à cela, paraglide et intlayer finissent par être des solutions 6 à 10 fois plus légères qu'i18next ou next-intl.
133
+
134
+ **(svelte-i18n)** (`svelte-i18n@3.4.0`) :
135
+
136
+ Cette solution répond à tous les besoins i18n dans un projet Svelte. Mais comme c'est le cas pour i18next ou d'autres solutions majeures, elle est un peu lourde (~15.9 Ko, soit environ 7× `svelte-intlayer`).
137
+
138
+ ### 3 — Recommandations
139
+
140
+ **(Intlayer)** (`svelte-intlayer@8.7.12`) :
141
+
142
+ Je ne jugerai pas personnellement `svelte-intlayer` par souci d'objectivité, puisqu'il s'agit de ma propre solution.
143
+
144
+ ### Note personnelle
145
+
146
+ Cette note est personnelle et n'affecte pas les résultats du benchmark. Pourtant, dans le monde de l'i18n, on voit souvent un consensus autour d'un pattern comme `const t = useTranslation('xx')` + `<>{t('xx.xx')}</>` pour le contenu traduit.
147
+
148
+ Dans les applications Svelte, injecter une fonction en tant que `Slot` est, à mon avis, un anti-pattern. Cela ajoute également une complexité évitable et un surcoût d'exécution JavaScript (même s'il est à peine perceptible).
@@ -57,6 +57,13 @@ En pratique, pour les implémentations les moins optimisées, une page internati
57
57
 
58
58
  L'autre impact concerne l'expérience développeur (DX) : la façon dont vous déclarez le contenu, les types, l'organisation des namespaces, le chargement dynamique et la réactivité lors du changement de langue.
59
59
 
60
+ ## TL;DR
61
+
62
+ - **Intlayer** : Fournit la meilleure performance et la plus petite taille de bundle (v8.7.12) pour TanStack Start.
63
+ - **react-i18next** & **use-intl** : Alternatives matures avec de grands écosystèmes, mais nettement plus lourdes et complexes à optimiser.
64
+ - **Paraglide** : Idée innovante de tree-shaking qui ne fonctionne pas en pratique. DX complexe et surcoût de réactivité dans TanStack Start.
65
+ - **À éviter** : **General Translation (GT)** et **Lingo.dev** en raison de graves problèmes de performance, des limites de quota AI et du verrouillage propriétaire (vendor lock-in).
66
+
60
67
  ## Testez votre application
61
68
 
62
69
  Pour repérer rapidement les problèmes de fuite i18n, j'ai mis en place un scanner gratuit disponible [ici](https://intlayer.org/i18n-seo-scanner).
@@ -87,12 +94,12 @@ Les syntaxes basées sur `const t = useTranslation()` + `t('a.b.c')` sont très
87
94
  Pour ce benchmark, nous avons comparé les bibliothèques suivantes :
88
95
 
89
96
  - `Base App` (Pas de bibliothèque i18n)
90
- - `react-intlayer` (v8.7.5-canary.0)
97
+ - `react-intlayer` (v8.7.12)
91
98
  - `react-i18next` (v17.0.2)
92
99
  - `use-intl` (v4.9.1)
93
100
  - `@lingui/core` (v5.3.0)
94
101
  - `@inlang/paraglide-js` (v2.15.1)
95
- - `tolgee` (v7.0.0)
102
+ - `@tolgee/react` (v7.0.0)
96
103
  - `react-intl` (v10.1.1)
97
104
  - `wuchale` (v0.22.11)
98
105
  - `gt-react` (vlatest)
@@ -150,7 +157,9 @@ L'idée derrière `Wuchale` est intéressante mais ce n'est pas encore une solut
150
157
 
151
158
  `Paraglide` propose une approche innovante et bien pensée. Pourtant, dans ce benchmark, le tree-shaking dont leur entreprise fait la publicité n'a pas fonctionné pour mon implémentation Next.js ou pour TanStack Start. Le workflow et la DX sont également plus complexes d'autres options. Personnellement, je ne suis pas fan de devoir régénérer des fichiers JS avant chaque push, ce qui crée un risque constant de conflit de fusion pour les développeurs via les PRs.
152
159
 
153
- **(Tolgee)** (`tolgee@7.0.0`) :
160
+ > Note sur paraglide : cette solution injecte du code dans votre base de code pour les imports, par conséquent, la métrique 'lib size' dans le rapport de benchmark est presque de 0. La génération de code est une bonne chose, car la fonction utilisée n'inclura que la logique nécessaire (préfixe partout vs pas de préfixe, cookie vs stockage, etc.). En comparaison, Intlayer effectue ce filtrage via des injections de variables d'environnement dans le build pour forcer le bundler à tree-shaker le contenu en fonction de la logique. Grâce à cela, paraglide et intlayer finissent par être des solutions 6 à 10 fois plus légères qu'i18next ou next-intl.
161
+
162
+ **(Tolgee)** (`@tolgee/react@7.0.0`) :
154
163
 
155
164
  `Tolgee` traite bon nombre des problèmes mentionnés plus haut. Je l'ai trouvé plus difficile à prendre en main que d'autres outils aux approches similaires. Il n'offre pas de sécurité de type, ce qui rend également beaucoup plus difficile la détection des clés manquantes à la compilation. J'ai dû wrapper les APIs de Tolgee avec les miennes pour ajouter la détection des clés manquantes.
156
165