@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
@@ -0,0 +1,160 @@
1
+ ---
2
+ createdAt: 2026-04-20
3
+ updatedAt: 2026-04-21
4
+ title: Best i18n solution for Vue in 2026 - Benchmark Report
5
+ description: Compare Vue internationalisation (i18n) libraries like vue-i18n, fluent-vue, and Intlayer. Detailed performance report on bundle size, leakage, and reactivity.
6
+ keywords:
7
+ - benchmark
8
+ - i18n
9
+ - intl
10
+ - vue
11
+ - performance
12
+ - intlayer
13
+ slugs:
14
+ - doc
15
+ - benchmark
16
+ - vue
17
+ author: Aymeric PINEAU
18
+ applicationTemplate: https://github.com/intlayer-org/benchmark-i18n-vue-template
19
+ history:
20
+ - version: 8.7.12
21
+ date: 2026-01-06
22
+ changes: "Init benchmark"
23
+ ---
24
+
25
+ # Vue i18n Libraries — 2026 Benchmark Report
26
+
27
+ This page is a benchmark report for i18n solutions on Vue.
28
+
29
+ ## Table of Contents
30
+
31
+ <Toc/>
32
+
33
+ ## Interactive Benchmark
34
+
35
+ <I18nBenchmark framework="vite-vue" vertical/>
36
+
37
+ ## Results reference:
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_vue.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_vue.md
47
+
48
+ See complete benchmark repository [here](https://github.com/intlayer-org/benchmark-i18n/tree/main).
49
+
50
+ ## Introduction
51
+
52
+ Internationalisation solutions are among the heaviest dependencies in a Vue app. The main risk is shipping unnecessary content: translations for other pages and other locales in a single route’s bundle.
53
+
54
+ As your app grows, that problem can quickly blow up the JavaScript sent to the client and slow down navigation.
55
+
56
+ In practice, for the least optimised implementations, an internationalised page can end up several times heavier than the version without i18n.
57
+
58
+ The other impact is on developer experience: how you declare content, types, namespace organisation, dynamic loading, and reactivity when the locale changes.
59
+
60
+ ## TL;DR
61
+
62
+ - **Intlayer**: The lightest solution (v8.7.12) with built-in scoping and dynamic loading.
63
+ - **vue-i18n**: The industry standard with a rich ecosystem, but can become significantly heavier and harder to optimise for code-splitting in large applications.
64
+ - **fluent-vue**: Innovative message organisation but lacks type-safety and turns out to be an extremely heavy solution.
65
+
66
+ ## Test your app
67
+
68
+ To quickly spot i18n leakage issues, I set up a free scanner available [here](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
+ ## The problem
73
+
74
+ Two levers are essential to limit the cost of a multilingual app:
75
+
76
+ - Split content by page / namespace so you do not load whole dictionaries when you do not need them
77
+ - Load the right locale dynamically, only when needed
78
+
79
+ Understanding the technical limitations of these approaches:
80
+
81
+ **Dynamic loading**
82
+
83
+ Without dynamic loading, most solutions keep messages in memory from the first render, which adds significant overhead for apps with many routes and locales.
84
+
85
+ With dynamic loading, you accept a trade-off: less initial JS, but sometimes an extra request when switching language.
86
+
87
+ **Content splitting**
88
+
89
+ Syntaxes built around `const { t } = useI18n()` + `t('a.b.c')` are very convenient but often encourage keeping large JSON objects at runtime. That model makes tree-shaking hard unless the library offers a real per-page split strategy.
90
+
91
+ ## Methodology
92
+
93
+ For this benchmark, we compared the following libraries:
94
+
95
+ - `Base App` (No i18n library)
96
+ - `vue-intlayer` (v8.7.12)
97
+ - `vue-i18n` (v11.4.0)
98
+ - `fluent-vue` (v3.8.2)
99
+
100
+ The framework is `Vue` with a multilingual app of **10 pages** and **10 languages**.
101
+
102
+ We compared **four loading strategies**:
103
+
104
+ | Strategy | No namespaces (global) | With namespaces (scoped) |
105
+ | :------------------ | :------------------------------------------- | :------------------------------------------------------------------- |
106
+ | **Static loading** | **Static**: Everything in memory at startup. | **Scoped static**: Split by namespace; everything loaded at startup. |
107
+ | **Dynamic loading** | **Dynamic**: On-demand loading per locale. | **Scoped dynamic**: Granular loading per namespace and locale. |
108
+
109
+ ## Strategy summary
110
+
111
+ - **Static**: Simple; no network latency after the initial load. Downside: large bundle size.
112
+ - **Dynamic**: Reduces initial weight (lazy-loading). Ideal when you have many locales.
113
+ - **Scoped static**: Keeps code organised (logical separation) without complex extra network requests.
114
+ - **Scoped dynamic**: Best approach for _code splitting_ and performance. Minimises memory by loading only what the current view and active locale need.
115
+
116
+ ### What I measured:
117
+
118
+ I ran the same multilingual app in a real browser for every stack, then wrote down what actually showed up on the wire and how long things took. Sizes are reported **after normal web compression**, because that is closer to what people download than raw source counts.
119
+
120
+ - **Internationalisation library size**: After bundling, tree-shaking and minification, the size of the i18n library is the size of the providers + composables code in an empty component. It does not include the loading of translation files. It answers how expensive the library is before your content enters the picture.
121
+
122
+ - **JavaScript per page**: For each benchmark route, how much script the browser pulls in for that visit, averaged across the pages in the suite (and across locales where the report rolls them up). Heavy pages are slow pages.
123
+
124
+ - **Leakage from other locales**: It's the content of the same page but in another language that would be loaded by mistake in the audited page. This content is unnecessary and should be avoided (e.g. `/fr/about` page content in `/en/about` page bundle).
125
+
126
+ - **Leakage from other routes**: The same idea for **other screens** in the app: whether their copy is riding along when you only opened one page (e.g. `/en/about` page content in `/en/contact` page bundle). A high score hints at weak splitting or over-broad bundles.
127
+
128
+ - **Average component bundle size**: Common UI pieces are measured **one at a time** instead of hiding inside one giant app number. It shows whether internationalisation quietly inflates everyday components. For instance, if your component rerenders, it will load all that data from memory. Attaching a giant JSON to any component is like connecting a big store of unused data that will slow down your components’ performance.
129
+
130
+ - **Language switch responsiveness**: I flip the language using the app’s own control and time how long it takes until the page has clearly switched, what a visitor would notice, not a lab micro-step.
131
+
132
+ - **Rendering work after a language change**: A narrower follow-up: how much effort the interface took to repaint for the new language once the switch is in flight. Useful when the “felt” time and the framework cost diverge.
133
+
134
+ - **Initial page load time**: From navigation to the browser considering the page fully loaded for the scenarios I tested. Good for comparing cold starts.
135
+
136
+ - **Hydration time**: When the app exposes it, how long the client spends turning server HTML into something you can actually click. A dash in the tables means that implementation did not provide a reliable hydration figure in this benchmark.
137
+
138
+ ## Results in detail
139
+
140
+ ### 1 — Solutions to avoid
141
+
142
+ > No clear solution to avoid in vue ecosystem.
143
+
144
+ ### 2 — Acceptable solutions
145
+
146
+ **(vue-i18n)** (`vue-i18n@11.4.0`):
147
+
148
+ - **vue-i18n** is without contestation the most used i18n library for vue, it has a lot of features and a huge ecosystem. But under the hood the solution is quite heavy. Even if vue-i18n integrates lazy loading for messages, it misses a scoping feature. In the case of a classic Vue SPA app there is no issue, but for a nuxt app, using @nuxt/i18n, it leads to including the messages from all pages into a single one. For a big nuxt app including more than 10 pages, it can become really problematic.
149
+
150
+ The package is very heavy (~24.3kb, which is about 9× `vue-intlayer`).
151
+
152
+ **(fluent-vue)** (`fluent-vue@0.5.0`):
153
+
154
+ - **fluent-vue** offer one innovation attempt through the .ftl format. The message organisation is great, easier to get started. But in practice, the lack of typesafety increases the risk of error and can quickly become time consuming to debug. Moreover, that solution load the messages using a vite plugin that force the loading of all the content in all languages into each page. Additionally this is an extremely heavy solution (~92.7kb, which is about 34× `vue-intlayer`).
155
+
156
+ ### 3 — Recommendations
157
+
158
+ **(Intlayer)** (`vue-intlayer@8.7.12`):
159
+
160
+ I will not personally judge `vue-intlayer` for objectivity’s sake, since it is my own solution.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  createdAt: 2024-08-13
3
- updatedAt: 2026-04-08
3
+ updatedAt: 2026-05-12
4
4
  title: Configuration
5
5
  description: Learn how to configure Intlayer for your application. Understand the various settings and options available to customize Intlayer to your needs.
6
6
  keywords:
@@ -14,6 +14,9 @@ slugs:
14
14
  - concept
15
15
  - configuration
16
16
  history:
17
+ - version: 8.9.4
18
+ date: 2026-05-12
19
+ changes: "Add support for LM Studio provider"
17
20
  - version: 8.7.0
18
21
  date: 2026-04-08
19
22
  changes: "Add `prune` and `minify` options to the build configuration"
@@ -350,7 +353,7 @@ const config: IntlayerConfig = {
350
353
  ai: {
351
354
  /**
352
355
  * AI provider to use.
353
- * Options: 'openai', 'anthropic', 'mistral', 'deepseek', 'gemini', 'ollama', 'openrouter', 'alibaba', 'fireworks', 'groq', 'huggingface', 'bedrock', 'googlevertex', 'togetherai'
356
+ * Options: 'openai', 'anthropic', 'mistral', 'deepseek', 'gemini', 'ollama', 'openrouter', 'alibaba', 'fireworks', 'groq', 'huggingface', 'bedrock', 'googlevertex', 'togetherai', 'lmstudio'
354
357
  * Default: 'openai'
355
358
  */
356
359
  provider: "openai",
@@ -937,17 +940,18 @@ Intlayer supports multiple AI providers for enhanced flexibility and choice. Cur
937
940
  - **Groq**
938
941
  - **Amazon Bedrock**
939
942
  - **Together.ai**
943
+ - **LM Studio**
940
944
  - **ollama**
941
945
 
942
- | Field | Description | Type | Default | Example | Note |
943
- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
944
- | `provider` | The provider to use for the AI features of Intlayer. | `'openai'` &#124; <br/> `'anthropic'` &#124; <br/> `'mistral'` &#124; <br/> `'deepseek'` &#124; <br/> `'gemini'` &#124; <br/> `'ollama'` &#124; <br/> `'openrouter'` &#124; <br/> `'alibaba'` &#124; <br/> `'fireworks'` &#124; <br/> `'groq'` &#124; <br/> `'huggingface'` &#124; <br/> `'bedrock'` &#124; <br/> `'googleaistudio'` &#124; <br/> `'googlevertex'` &#124; <br/> `'togetherai'` | `undefined` | `'anthropic'` | Different providers require different API keys and have different pricing. |
945
- | `model` | The model to use for AI features. | `string` | None | `'gpt-4o-2024-11-20'` | Specific model varies by provider. |
946
- | `temperature` | Controls the randomness of AI responses. | `number` | None | `0.1` | Higher temperature = more creative and less predictable. |
947
- | `apiKey` | Your API key for the selected provider. | `string` | None | `process.env.OPENAI_API_KEY` | Keep secret; store in environment variables. |
948
- | `applicationContext` | Additional context about your application to help the AI generate more accurate translations (domain, audience, tone, terminology). | `string` | None | `'My application context'` | Can be used to add rules (e.g. `"You should not transform urls"`). |
949
- | `baseURL` | The base URL for the AI API. | `string` | None | `'https://api.openai.com/v1'` <br/> `'http://localhost:5000'` | Can point to a local or custom AI API endpoint. |
950
- | `dataSerialization` | Data serialization format for AI features. | `'json'` &#124; <br/> `'toon'` | `undefined` | `'toon'` | • `'json'`: standard, reliable; uses more tokens.<br/>• `'toon'`: fewer tokens, less consistent.<br/>• Additional parameters are passed to the AI model as context (reasoning effort, verbosity, etc.). |
946
+ | Field | Description | Type | Default | Example | Note |
947
+ | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
948
+ | `provider` | The provider to use for the AI features of Intlayer. | `'openai'` &#124; <br/> `'anthropic'` &#124; <br/> `'mistral'` &#124; <br/> `'deepseek'` &#124; <br/> `'gemini'` &#124; <br/> `'ollama'` &#124; <br/> `'openrouter'` &#124; <br/> `'alibaba'` &#124; <br/> `'fireworks'` &#124; <br/> `'groq'` &#124; <br/> `'huggingface'` &#124; <br/> `'bedrock'` &#124; <br/> `'googleaistudio'` &#124; <br/> `'googlevertex'` &#124; <br/> `'togetherai'` &#124; <br/> `'lmstudio'` | `undefined` | `'anthropic'` | Different providers require different API keys and have different pricing. |
949
+ | `model` | The model to use for AI features. | `string` | None | `'gpt-4o-2024-11-20'` | Specific model varies by provider. |
950
+ | `temperature` | Controls the randomness of AI responses. | `number` | None | `0.1` | Higher temperature = more creative and less predictable. |
951
+ | `apiKey` | Your API key for the selected provider. | `string` | None | `process.env.OPENAI_API_KEY` | Keep secret; store in environment variables. |
952
+ | `applicationContext` | Additional context about your application to help the AI generate more accurate translations (domain, audience, tone, terminology). | `string` | None | `'My application context'` | Can be used to add rules (e.g. `"You should not transform urls"`). |
953
+ | `baseURL` | The base URL for the AI API. | `string` | None | `'https://api.openai.com/v1'` <br/> `'http://localhost:5000'` | Can point to a local or custom AI API endpoint. |
954
+ | `dataSerialization` | Data serialization format for AI features. | `'json'` &#124; <br/> `'toon'` | `undefined` | `'toon'` | • `'json'`: standard, reliable; uses more tokens.<br/>• `'toon'`: fewer tokens, less consistent.<br/>• Additional parameters are passed to the AI model as context (reasoning effort, verbosity, etc.). |
951
955
 
952
956
  ### Build Configuration
953
957
 
@@ -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: Content File
5
5
  description: Learn how to customise the extensions for your content declaration files. Follow this documentation to implement conditions efficiently in your project.
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: "Add `plural` content node type"
15
18
  - version: 8.0.0
16
19
  date: 2026-01-28
17
20
  changes: "Add `html` content node type"
@@ -63,6 +66,7 @@ import { type ReactNode } from "react";
63
66
  import {
64
67
  t,
65
68
  enu,
69
+ plural,
66
70
  cond,
67
71
  nest,
68
72
  md,
@@ -82,6 +86,7 @@ interface Content {
82
86
  };
83
87
  multilingualContent: string;
84
88
  quantityContent: string;
89
+ pluralContent: string;
85
90
  conditionalContent: string;
86
91
  markdownContent: never;
87
92
  htmlContent: never;
@@ -117,6 +122,10 @@ export default {
117
122
  ">5": "Some cars",
118
123
  ">19": "Many cars",
119
124
  }),
125
+ pluralContent: plural({
126
+ one: "One car",
127
+ other: "{{count}} cars",
128
+ }),
120
129
  conditionalContent: cond({
121
130
  true: "Validation is enabled",
122
131
  false: "Validation is disabled",
@@ -171,6 +180,13 @@ export default {
171
180
  ">5": "Some cars",
172
181
  ">19": "Many cars",
173
182
  },
183
+ "pluralContent": {
184
+ "nodeType": "plural",
185
+ "plural": {
186
+ "one": "One car",
187
+ "other": "{{count}} cars",
188
+ },
189
+ },
174
190
  },
175
191
  "conditionalContent": {
176
192
  "nodeType": "condition",
@@ -218,6 +234,7 @@ Content nodes are the building blocks of dictionary content. They can be:
218
234
  - **Primitive values**: strings, numbers, booleans, null, undefined
219
235
  - **Typed nodes**: Special content types such as translations, conditions, markdown, etc.
220
236
  - **Functions**: Dynamic content that can be evaluated at runtime [see Function Fetching](https://github.com/aymericzip/intlayer/blob/main/docs/docs/{{locale}}/dictionary/function_fetching.md)
237
+ - **Plural Content**: See Plural Content [See Plural Content](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/dictionary/plural.md)
221
238
  - **Nested content**: References to other dictionaries
222
239
 
223
240
  #### Content Types
@@ -543,6 +560,8 @@ multilingualContent: t({
543
560
  });
544
561
  ```
545
562
 
563
+ > See [Translation Content (`t`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/dictionary/translation.md) for more information.
564
+
546
565
  ### Condition Content (`cond`)
547
566
 
548
567
  Content that changes based on boolean conditions:
@@ -556,6 +575,8 @@ conditionalContent: cond({
556
575
  });
557
576
  ```
558
577
 
578
+ > See [Condition Content (`cond`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/dictionary/condition.md) for more information.
579
+
559
580
  ### Enumeration Content (`enu`)
560
581
 
561
582
  Content that varies based on enumerated values:
@@ -570,6 +591,23 @@ statusContent: enu({
570
591
  });
571
592
  ```
572
593
 
594
+ > See [Enumeration Content (`enu`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/dictionary/enumeration.md) for more information.
595
+
596
+ ### Plural Content (`plural`)
597
+
598
+ Content that varies based on plural rules:
599
+
600
+ ```typescript
601
+ import { plural } from "intlayer";
602
+
603
+ pluralContent: plural({
604
+ one: "One car",
605
+ other: "{{count}} cars",
606
+ });
607
+ ```
608
+
609
+ > See [Plural Content Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/dictionary/plural.md) for more information.
610
+
573
611
  ### Insertion Content (`insert`)
574
612
 
575
613
  Content that can be inserted into other content:
@@ -580,6 +618,8 @@ import { insert } from "intlayer";
580
618
  insertionContent: insert("This text can be inserted anywhere");
581
619
  ```
582
620
 
621
+ > See [Insertion Content (`insert`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/dictionary/insertion.md) for more information.
622
+
583
623
  ### Nested Content (`nest`)
584
624
 
585
625
  References to other dictionaries:
@@ -590,6 +630,8 @@ import { nest } from "intlayer";
590
630
  nestedContent: nest("about-page");
591
631
  ```
592
632
 
633
+ > See [Nested Content (`nest`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/dictionary/nesting.md) for more information.
634
+
593
635
  ### Markdown Content (`md`)
594
636
 
595
637
  Rich text content in Markdown format:
@@ -602,6 +644,8 @@ markdownContent: md(
602
644
  );
603
645
  ```
604
646
 
647
+ > See [Markdown Content (`md`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/dictionary/markdown.md) for more information.
648
+
605
649
  ### HTML Content (`html`)
606
650
 
607
651
  Rich HTML content that can use standard tags or custom components:
@@ -619,6 +663,8 @@ localizedHtmlContent: t({
619
663
  });
620
664
  ```
621
665
 
666
+ > See [HTML Content (`html`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/dictionary/html.md) for more information.
667
+
622
668
  ### Gender Content (`gender`)
623
669
 
624
670
  Content that varies based on gender:
@@ -633,6 +679,8 @@ genderContent: gender({
633
679
  });
634
680
  ```
635
681
 
682
+ > See [Gender Content (`gender`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/dictionary/gender.md) for more information.
683
+
636
684
  ### File Content (`file`)
637
685
 
638
686
  References to external files:
@@ -643,6 +691,8 @@ import { file } from "intlayer";
643
691
  fileContent: file("./path/to/content.txt");
644
692
  ```
645
693
 
694
+ > See [File Content (`file`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/dictionary/file.md) for more information.
695
+
646
696
  ## Creating Content Files
647
697
 
648
698
  ### Basic Content File Structure
@@ -160,30 +160,9 @@ syncPO({
160
160
  source: ({ key, locale }) => string, // required
161
161
  location?: string, // optional label, default: "sync-po::path/to/source"
162
162
  priority?: number, // optional priority for conflict resolution, default: 0
163
- format?: 'icu' | 'i18next' | 'vue-i18n', // optional, only needed when your msgstr values use a specific interpolation syntax
164
163
  });
165
164
  ```
166
165
 
167
- #### `format` ('icu' | 'i18next' | 'vue-i18n')
168
-
169
- PO files are always Gettext Portable Object files — that is fixed. This option only describes the **interpolation syntax** used inside the `msgstr` values, so Intlayer can convert them to its own format at parse time (via `formatDictionary`) and back when writing output.
170
-
171
- - `undefined` _(default)_: `msgstr` values are treated as plain strings — no transformation. Use this for most PO files.
172
- - `'icu'`: `msgstr` values use ICU message syntax (e.g. `{count, plural, one {# item} other {# items}}`).
173
- - `'i18next'`: `msgstr` values use i18next interpolation syntax (e.g. `{{variable}}`).
174
- - `'vue-i18n'`: `msgstr` values use Vue I18n syntax.
175
-
176
- > Transformation is applied by `@intlayer/chokidar`'s `formatDictionary` on load, and reversed with `formatDictionaryOutput` on write. For complex rules like ICU plurals, round-trip fidelity is not guaranteed.
177
-
178
- **Example — PO files contain i18next-style interpolation:**
179
-
180
- ```ts
181
- syncPO({
182
- source: ({ key, locale }) => `./locales/${locale}/${key}.po`,
183
- format: "i18next",
184
- }),
185
- ```
186
-
187
166
  ### Multiple PO sources and priority
188
167
 
189
168
  You can add multiple `syncPO` plugins to synchronise different PO sources. This is useful when you have multiple translation sources or different PO structures in your project.
@@ -30,6 +30,3 @@ A continuación encontrarás los informes detallados y la documentación técnic
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 @@ Debido a que el problema es difícil, existen muchas soluciones: algunas enfocad
61
61
 
62
62
  Intlayer intenta optimizar en todas estas dimensiones.
63
63
 
64
+ ## TL;DR
65
+
66
+ - **Intlayer** y **next-translate**: Las mejores opciones para el rendimiento en Next.js, ofreciendo la menor huella y el mejor soporte para renderizado estático.
67
+ - **next-intl**: La opción más de moda pero pesada y compleja de optimizar para aplicaciones grandes.
68
+ - **next-i18next**: Popular y rica en plugins, pero conlleva un peso de bundle significativo (~3× Intlayer).
69
+ - **Evitar**: **gt-next** y **lingo.dev** debido a graves problemas de rendimiento, bloqueo del proveedor (vendor lock-in) y errores que rompen la compilación.
70
+
64
71
  ## Pon a prueba tu aplicación
65
72
 
66
73
  Para sacar a la luz estos problemas, he creado un escáner gratuito que puedes probar [aquí](https://intlayer.org/i18n-seo-scanner).
@@ -99,14 +106,14 @@ Finalmente, `Intlayer` aplica una optimización en tiempo de compilación para q
99
106
  Para este benchmark, comparamos las siguientes librerías:
100
107
 
101
108
  - `Base App` (Sin librería 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 @@ Problemas encontrados:
161
168
 
162
169
  **(General Translation)** (`gt-next@6.16.5`):
163
170
 
164
- - Para una aplicación de 110kb, `gt-react` añade más de 440kb extra.
171
+ - Para una aplicación de 110kb, `gt-next` añade más de 440kb extra.
165
172
  - `Quota Exceeded, please upgrade your plan` en la primerísima compilación con General Translation.
166
173
  - Las traducciones no se renderizan; obtengo el error `Error: <T> used on the client-side outside of <GTProvider>`, lo que parece ser un bug de la librería.
167
- - Mientras implementaba **gt-tanstack-start-react**, también encontré un [problema](https://github.com/generaltranslation/gt/issues/1210#event-24510646961) con la librería: `does not provide an export named 'printAST' - @formatjs/icu-messageformat-parser`, que hacía que la aplicación se rompiera. Tras informar de este problema, el mantenedor lo solucionó en 24 horas.
174
+ - Mientras implementaba **gt-next**, también encontré un [problema](https://github.com/generaltranslation/gt/issues/1210#event-24510646961) con la librería: `does not provide an export named 'printAST' - @formatjs/icu-messageformat-parser`, que hacía que la aplicación se rompiera. Tras informar de este problema, el mantenedor lo solucionó en 24 horas.
168
175
  - La librería bloquea el renderizado estático de las páginas de Next.js.
169
176
 
170
177
  **(Lingo.dev)** (`@lingo.dev/compiler@0.4.0`):
@@ -185,9 +192,11 @@ La idea detrás de `Wuchale` es interesante pero aún no es viable. Experimenté
185
192
  `Paraglide` ofrece un enfoque innovador y bien pensado. Aun así, en este benchmark, el tree-shaking que su empresa anuncia no funcionó para mis configuraciones de Next.js o TanStack Start. El flujo de trabajo y la DX son más complejos que otras opciones. Personalmente, no me gusta tener que regenerar archivos JS antes de cada push, lo que crea un riesgo constante de conflictos de fusión a través de las PR. La herramienta también parece más enfocada en Vite que en Next.js.
186
193
  Finalmente, en comparación con otras soluciones, Paraglide no usa un almacén (ej. contexto de React) para recuperar el idioma actual y renderizar el contenido. Por cada nodo analizado, solicita el idioma al localStorage / cookie, etc. Esto provoca la ejecución de lógica innecesaria que afecta a la reactividad del componente.
187
194
 
195
+ > Nota sobre paraglide: la solución inyecta código en tu base de código para importar, como resultado la métrica 'tamaño de la lib' en el informe del benchmark es casi 0. La generación de código es algo bueno, porque la función utilizada incluirá solo la lógica necesaria (prefijo total vs sin prefijo, cookie vs almacenamiento, etc.). En comparación, Intlayer realiza este filtrado mediante inyecciones de variables de entorno en la compilación para forzar al bundler a aplicar tree-shaking al contenido según la lógica. Gracias a esto, paraglide e intlayer terminan siendo soluciones de 6 a 10 veces más ligeras que i18next o next-intl.
196
+
188
197
  ### 3 — Soluciones aceptables
189
198
 
190
- **(Tolgee)** (`tolgee@7.0.0`):
199
+ **(Tolgee)** (`@tolgee/react@7.0.0`):
191
200
 
192
201
  `Tolgee` aborda muchos de los problemas mencionados anteriormente. Me resultó más difícil de adoptar que herramientas similares. No proporciona seguridad de tipos (type safety), lo que también dificulta detectar claves faltantes en tiempo de compilación. Tuve que envolver las funciones de Tolgee con las mías propias para añadir la detección de claves faltantes.
193
202
 
@@ -215,7 +224,7 @@ A menudo se elogia a `Lingui`. Personalmente, encontré el flujo de trabajo `lin
215
224
 
216
225
  `next-translate` es mi recomendación principal si te gusta una API de estilo `t()`. Es elegante a través de `next-translate-plugin`, cargando namespaces mediante `getStaticProps` con un cargador de Webpack / Turbopack. También es la opción más ligera aquí (~2.5kb). Para la segmentación por espacios de nombres, definirnamespaces por página o ruta en la configuración está bien pensado y es más fácil de mantener que las principales alternativas como **next-intl** o **next-i18next**. En la versión `3.1.2`, noté que el renderizado estático no funcionaba; Next.js recurría al renderizado dinámico.
217
226
 
218
- **(Intlayer)** (`next-intlayer@8.7.5`):
227
+ **(Intlayer)** (`next-intlayer@8.7.12`):
219
228
 
220
229
  No seré yo quien juzgue personalmente a `next-intlayer` por objetividad, ya que es mi propia solución.
221
230