@intlayer/docs 8.9.4-canary.0 → 8.9.5

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 (207) hide show
  1. package/dist/cjs/generated/docs.entry.cjs +20 -0
  2. package/dist/cjs/generated/docs.entry.cjs.map +1 -1
  3. package/dist/esm/generated/docs.entry.mjs +20 -0
  4. package/dist/esm/generated/docs.entry.mjs.map +1 -1
  5. package/dist/types/generated/docs.entry.d.ts +1 -0
  6. package/dist/types/generated/docs.entry.d.ts.map +1 -1
  7. package/docs/ar/benchmark/index.md +0 -3
  8. package/docs/ar/benchmark/nextjs.md +15 -6
  9. package/docs/ar/benchmark/solid.md +155 -0
  10. package/docs/ar/benchmark/svelte.md +148 -0
  11. package/docs/ar/benchmark/tanstack.md +12 -3
  12. package/docs/ar/benchmark/vue.md +160 -0
  13. package/docs/ar/configuration.md +16 -12
  14. package/docs/ar/dictionary/content_file.md +51 -1
  15. package/docs/ar/mcp_server.md +30 -17
  16. package/docs/ar/plugins/sync-po.md +333 -0
  17. package/docs/bn/configuration.md +16 -12
  18. package/docs/cs/configuration.md +16 -12
  19. package/docs/de/benchmark/index.md +0 -3
  20. package/docs/de/benchmark/nextjs.md +15 -6
  21. package/docs/de/benchmark/solid.md +155 -0
  22. package/docs/de/benchmark/svelte.md +148 -0
  23. package/docs/de/benchmark/tanstack.md +12 -3
  24. package/docs/de/benchmark/vue.md +160 -0
  25. package/docs/de/configuration.md +16 -12
  26. package/docs/de/dictionary/content_file.md +52 -2
  27. package/docs/de/mcp_server.md +29 -16
  28. package/docs/de/plugins/sync-po.md +332 -0
  29. package/docs/en/benchmark/nextjs.md +11 -2
  30. package/docs/en/benchmark/solid.md +22 -4
  31. package/docs/en/benchmark/svelte.md +17 -5
  32. package/docs/en/benchmark/tanstack.md +18 -3
  33. package/docs/en/benchmark/vue.md +17 -11
  34. package/docs/en/configuration.md +16 -13
  35. package/docs/en/dictionary/content_file.md +51 -1
  36. package/docs/en/mcp_server.md +31 -18
  37. package/docs/en/plugins/sync-po.md +333 -0
  38. package/docs/en-GB/benchmark/index.md +0 -3
  39. package/docs/en-GB/benchmark/nextjs.md +15 -6
  40. package/docs/en-GB/benchmark/solid.md +155 -0
  41. package/docs/en-GB/benchmark/svelte.md +148 -0
  42. package/docs/en-GB/benchmark/tanstack.md +12 -3
  43. package/docs/en-GB/benchmark/vue.md +160 -0
  44. package/docs/en-GB/configuration.md +15 -11
  45. package/docs/en-GB/dictionary/content_file.md +51 -1
  46. package/docs/en-GB/mcp_server.md +31 -18
  47. package/docs/en-GB/plugins/sync-po.md +333 -0
  48. package/docs/es/benchmark/index.md +0 -3
  49. package/docs/es/benchmark/nextjs.md +15 -6
  50. package/docs/es/benchmark/solid.md +155 -0
  51. package/docs/es/benchmark/svelte.md +148 -0
  52. package/docs/es/benchmark/tanstack.md +12 -3
  53. package/docs/es/benchmark/vue.md +160 -0
  54. package/docs/es/configuration.md +16 -12
  55. package/docs/es/dictionary/content_file.md +51 -1
  56. package/docs/es/mcp_server.md +30 -17
  57. package/docs/es/plugins/sync-po.md +333 -0
  58. package/docs/fr/benchmark/index.md +0 -3
  59. package/docs/fr/benchmark/nextjs.md +15 -6
  60. package/docs/fr/benchmark/solid.md +155 -0
  61. package/docs/fr/benchmark/svelte.md +148 -0
  62. package/docs/fr/benchmark/tanstack.md +12 -3
  63. package/docs/fr/benchmark/vue.md +160 -0
  64. package/docs/fr/configuration.md +16 -12
  65. package/docs/fr/dictionary/content_file.md +51 -1
  66. package/docs/fr/mcp_server.md +30 -17
  67. package/docs/fr/plugins/sync-po.md +333 -0
  68. package/docs/hi/benchmark/nextjs.md +15 -6
  69. package/docs/hi/benchmark/solid.md +155 -0
  70. package/docs/hi/benchmark/svelte.md +148 -0
  71. package/docs/hi/benchmark/tanstack.md +12 -3
  72. package/docs/hi/benchmark/vue.md +160 -0
  73. package/docs/hi/configuration.md +16 -12
  74. package/docs/hi/dictionary/content_file.md +51 -1
  75. package/docs/hi/mcp_server.md +31 -18
  76. package/docs/hi/plugins/sync-po.md +333 -0
  77. package/docs/id/benchmark/index.md +0 -3
  78. package/docs/id/benchmark/nextjs.md +15 -6
  79. package/docs/id/benchmark/solid.md +155 -0
  80. package/docs/id/benchmark/svelte.md +148 -0
  81. package/docs/id/benchmark/tanstack.md +12 -3
  82. package/docs/id/benchmark/vue.md +160 -0
  83. package/docs/id/configuration.md +16 -12
  84. package/docs/id/dictionary/content_file.md +51 -1
  85. package/docs/id/mcp_server.md +30 -17
  86. package/docs/id/plugins/sync-po.md +333 -0
  87. package/docs/it/benchmark/index.md +1 -4
  88. package/docs/it/benchmark/nextjs.md +15 -6
  89. package/docs/it/benchmark/solid.md +155 -0
  90. package/docs/it/benchmark/svelte.md +148 -0
  91. package/docs/it/benchmark/tanstack.md +12 -3
  92. package/docs/it/benchmark/vue.md +160 -0
  93. package/docs/it/configuration.md +16 -12
  94. package/docs/it/dictionary/content_file.md +51 -1
  95. package/docs/it/mcp_server.md +30 -17
  96. package/docs/it/plugins/sync-po.md +333 -0
  97. package/docs/ja/benchmark/index.md +5 -5
  98. package/docs/ja/benchmark/nextjs.md +15 -6
  99. package/docs/ja/benchmark/solid.md +155 -0
  100. package/docs/ja/benchmark/svelte.md +148 -0
  101. package/docs/ja/benchmark/tanstack.md +12 -3
  102. package/docs/ja/benchmark/vue.md +160 -0
  103. package/docs/ja/configuration.md +16 -12
  104. package/docs/ja/dictionary/content_file.md +50 -2
  105. package/docs/ja/intlayer_with_nextjs_no_locale_path.md +4 -3
  106. package/docs/ja/mcp_server.md +29 -16
  107. package/docs/ja/plugins/sync-po.md +333 -0
  108. package/docs/ko/benchmark/nextjs.md +15 -6
  109. package/docs/ko/benchmark/solid.md +155 -0
  110. package/docs/ko/benchmark/svelte.md +148 -0
  111. package/docs/ko/benchmark/tanstack.md +12 -3
  112. package/docs/ko/benchmark/vue.md +160 -0
  113. package/docs/ko/configuration.md +16 -12
  114. package/docs/ko/dictionary/content_file.md +51 -1
  115. package/docs/ko/intlayer_with_nextjs_no_locale_path.md +3 -2
  116. package/docs/ko/mcp_server.md +31 -18
  117. package/docs/ko/plugins/sync-po.md +333 -0
  118. package/docs/nl/configuration.md +16 -12
  119. package/docs/pl/benchmark/index.md +0 -3
  120. package/docs/pl/benchmark/nextjs.md +15 -6
  121. package/docs/pl/benchmark/solid.md +155 -0
  122. package/docs/pl/benchmark/svelte.md +148 -0
  123. package/docs/pl/benchmark/tanstack.md +12 -3
  124. package/docs/pl/benchmark/vue.md +160 -0
  125. package/docs/pl/configuration.md +16 -12
  126. package/docs/pl/dictionary/content_file.md +51 -1
  127. package/docs/pl/mcp_server.md +30 -17
  128. package/docs/pl/plugins/sync-po.md +333 -0
  129. package/docs/pt/benchmark/index.md +0 -3
  130. package/docs/pt/benchmark/nextjs.md +16 -7
  131. package/docs/pt/benchmark/solid.md +155 -0
  132. package/docs/pt/benchmark/svelte.md +148 -0
  133. package/docs/pt/benchmark/tanstack.md +13 -4
  134. package/docs/pt/benchmark/vue.md +160 -0
  135. package/docs/pt/configuration.md +16 -12
  136. package/docs/pt/dictionary/content_file.md +51 -1
  137. package/docs/pt/mcp_server.md +30 -17
  138. package/docs/pt/plugins/sync-po.md +333 -0
  139. package/docs/ru/benchmark/nextjs.md +15 -6
  140. package/docs/ru/benchmark/solid.md +155 -0
  141. package/docs/ru/benchmark/svelte.md +148 -0
  142. package/docs/ru/benchmark/tanstack.md +12 -3
  143. package/docs/ru/benchmark/vue.md +160 -0
  144. package/docs/ru/configuration.md +16 -12
  145. package/docs/ru/dictionary/content_file.md +52 -2
  146. package/docs/ru/mcp_server.md +30 -17
  147. package/docs/ru/plugins/sync-po.md +333 -0
  148. package/docs/tr/benchmark/index.md +0 -3
  149. package/docs/tr/benchmark/nextjs.md +15 -6
  150. package/docs/tr/benchmark/solid.md +155 -0
  151. package/docs/tr/benchmark/svelte.md +148 -0
  152. package/docs/tr/benchmark/tanstack.md +12 -3
  153. package/docs/tr/benchmark/vue.md +160 -0
  154. package/docs/tr/configuration.md +16 -12
  155. package/docs/tr/dictionary/content_file.md +51 -1
  156. package/docs/tr/mcp_server.md +31 -18
  157. package/docs/tr/plugins/sync-po.md +333 -0
  158. package/docs/uk/benchmark/nextjs.md +15 -6
  159. package/docs/uk/benchmark/solid.md +155 -0
  160. package/docs/uk/benchmark/svelte.md +148 -0
  161. package/docs/uk/benchmark/tanstack.md +12 -3
  162. package/docs/uk/benchmark/vue.md +160 -0
  163. package/docs/uk/configuration.md +16 -12
  164. package/docs/uk/dictionary/content_file.md +51 -1
  165. package/docs/uk/mcp_server.md +29 -16
  166. package/docs/uk/plugins/sync-po.md +333 -0
  167. package/docs/ur/configuration.md +16 -12
  168. package/docs/vi/benchmark/index.md +0 -3
  169. package/docs/vi/benchmark/nextjs.md +15 -6
  170. package/docs/vi/benchmark/solid.md +155 -0
  171. package/docs/vi/benchmark/svelte.md +148 -0
  172. package/docs/vi/benchmark/tanstack.md +12 -3
  173. package/docs/vi/benchmark/vue.md +160 -0
  174. package/docs/vi/configuration.md +16 -12
  175. package/docs/vi/dictionary/content_file.md +51 -1
  176. package/docs/vi/intlayer_with_nextjs_15.md +10 -57
  177. package/docs/vi/mcp_server.md +30 -17
  178. package/docs/vi/plugins/sync-po.md +333 -0
  179. package/docs/zh/benchmark/nextjs.md +15 -6
  180. package/docs/zh/benchmark/solid.md +155 -0
  181. package/docs/zh/benchmark/svelte.md +148 -0
  182. package/docs/zh/benchmark/tanstack.md +12 -3
  183. package/docs/zh/benchmark/vue.md +160 -0
  184. package/docs/zh/configuration.md +16 -12
  185. package/docs/zh/dictionary/content_file.md +51 -3
  186. package/docs/zh/mcp_server.md +31 -18
  187. package/docs/zh/plugins/sync-po.md +333 -0
  188. package/frequent_questions/ar/intlayerNode.md +3 -3
  189. package/frequent_questions/de/intlayerNode.md +3 -3
  190. package/frequent_questions/en/intlayerNode.md +3 -3
  191. package/frequent_questions/en-GB/intlayerNode.md +3 -3
  192. package/frequent_questions/es/intlayerNode.md +3 -3
  193. package/frequent_questions/fr/intlayerNode.md +3 -3
  194. package/frequent_questions/hi/intlayerNode.md +3 -3
  195. package/frequent_questions/id/intlayerNode.md +3 -3
  196. package/frequent_questions/it/intlayerNode.md +3 -3
  197. package/frequent_questions/ja/intlayerNode.md +3 -3
  198. package/frequent_questions/ko/intlayerNode.md +3 -3
  199. package/frequent_questions/pl/intlayerNode.md +3 -3
  200. package/frequent_questions/pt/intlayerNode.md +3 -3
  201. package/frequent_questions/ru/intlayerNode.md +3 -3
  202. package/frequent_questions/tr/intlayerNode.md +3 -3
  203. package/frequent_questions/uk/intlayerNode.md +3 -3
  204. package/frequent_questions/vi/intlayerNode.md +3 -3
  205. package/frequent_questions/zh/intlayerNode.md +3 -3
  206. package/package.json +8 -8
  207. package/src/generated/docs.entry.ts +20 -0
@@ -0,0 +1,333 @@
1
+ ---
2
+ createdAt: 2026-05-10
3
+ updatedAt: 2026-05-10
4
+ title: Sync PO plugin
5
+ description: Synchronize Intlayer dictionaries with Gettext PO files. Keep your existing i18n while using Intlayer to manage, translate, and test your messages.
6
+ keywords:
7
+ - Intlayer
8
+ - Sync PO
9
+ - Gettext
10
+ - i18n
11
+ - translations
12
+ slugs:
13
+ - doc
14
+ - plugin
15
+ - sync-po
16
+ youtubeVideo: https://www.youtube.com/watch?v=MpGMxniDHNg
17
+ history:
18
+ - version: 8.9.4
19
+ date: 2026-05-10
20
+ changes: "Initial Sync PO plugin documentation"
21
+ ---
22
+
23
+ # Sync PO (i18n bridges) - Sync PO with ICU / i18next support
24
+
25
+ Use Intlayer as an add‑on to your existing i18n stack. This plugin keeps your Gettext PO messages in sync with Intlayer dictionaries so you can:
26
+
27
+ - Keep your existing PO-based translation workflow.
28
+ - Manage and translate your messages with Intlayer (CLI, CI, providers, CMS), without refactoring your app.
29
+ - Ship tutorials and SEO content targeting each ecosystem, while suggesting Intlayer as the PO management layer.
30
+
31
+ Notes and current scope:
32
+
33
+ - Externalization to the CMS works for translations and classic text.
34
+ - No support yet for insertions, plurals/ICU, or advanced runtime features of other libraries within the PO entries themselves.
35
+ - The visual editor is not supported yet for third‑party i18n outputs.
36
+
37
+ ### When to use this plugin
38
+
39
+ - You already use Gettext PO files for your translations.
40
+ - You want AI‑assisted fill, test in CI, and content ops without changing your rendering runtime.
41
+
42
+ ## Installation
43
+
44
+ ```bash
45
+ pnpm add -D @intlayer/sync-po-plugin
46
+ # or
47
+ npm i -D @intlayer/sync-po-plugin
48
+ ```
49
+
50
+ ## Plugins
51
+
52
+ This package provides two plugins:
53
+
54
+ - `loadPO`: Load PO files into Intlayer dictionaries.
55
+ - This plugin is used to load PO files from a source and will be loaded into Intlayer dictionaries. It can scan all the codebase and search for specific PO files.
56
+ This plugin can be used
57
+ - if you use an i18n library that imposes a specific location for your PO files to be loaded, but you want to place your content declaration where you want in your code base.
58
+ - It can also be used if you want to fetch your messages from a remote source (ex: a CMS, an API, etc.) and store your messages in PO files.
59
+
60
+ > Under the hood, this plugin will scan all the codebase and search for specific PO files and load them into Intlayer dictionaries.
61
+ > Note that this plugin will not write the output and translations back to the PO files.
62
+
63
+ - `syncPO`: Synchronize PO files with Intlayer dictionaries.
64
+ - This plugin is used to synchronize PO files with Intlayer dictionaries. It can scan the given location and load the PO that match the pattern for specific PO files. This plugin is useful if you want to get the benefits of Intlayer while using another i18n library.
65
+
66
+ ## Using both plugins
67
+
68
+ ```ts fileName="intlayer.config.ts"
69
+ import { Locales, type IntlayerConfig } from "intlayer";
70
+ import { loadPO, syncPO } from "@intlayer/sync-po-plugin";
71
+
72
+ const config: IntlayerConfig = {
73
+ internationalization: {
74
+ locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
75
+ defaultLocale: Locales.ENGLISH,
76
+ },
77
+
78
+ // Keep your current PO files in sync with Intlayer dictionaries
79
+ plugins: [
80
+ /**
81
+ * Will load all the PO files in the src that match the pattern {key}.i18n.po
82
+ */
83
+ loadPO({
84
+ source: ({ key }) => `./src/**/${key}.i18n.po`,
85
+ locale: Locales.ENGLISH,
86
+ priority: 1, // Ensures these PO files take precedence over files at `./locales/en/${key}.po`
87
+ }),
88
+ /**
89
+ * Will load, and write the output and translations back to the PO files in the locales directory
90
+ */
91
+ syncPO({
92
+ source: ({ key, locale }) => `./locales/${locale}/${key}.po`,
93
+ priority: 0,
94
+ }),
95
+ ],
96
+ };
97
+
98
+ export default config;
99
+ ```
100
+
101
+ ## `syncPO` plugin
102
+
103
+ ### Quick start
104
+
105
+ Add the plugin to your `intlayer.config.ts` and point it at your existing PO structure.
106
+
107
+ ```ts fileName="intlayer.config.ts"
108
+ import { Locales, type IntlayerConfig } from "intlayer";
109
+ import { syncPO } from "@intlayer/sync-po-plugin";
110
+
111
+ const config: IntlayerConfig = {
112
+ internationalization: {
113
+ locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
114
+ defaultLocale: Locales.ENGLISH,
115
+ },
116
+
117
+ // Keep your current PO files in sync with Intlayer dictionaries
118
+ plugins: [
119
+ syncPO({
120
+ // Per-locale, per-namespace layout
121
+ source: ({ key, locale }) => `./locales/${locale}/${key}.po`,
122
+ }),
123
+ ],
124
+ };
125
+
126
+ export default config;
127
+ ```
128
+
129
+ Alternative: single file per locale:
130
+
131
+ ```ts fileName="intlayer.config.ts"
132
+ import { Locales, type IntlayerConfig } from "intlayer";
133
+ import { syncPO } from "@intlayer/sync-po-plugin";
134
+
135
+ const config: IntlayerConfig = {
136
+ internationalization: {
137
+ locales: [Locales.ENGLISH, Locales.FRENCH],
138
+ defaultLocale: Locales.ENGLISH,
139
+ },
140
+ plugins: [
141
+ syncPO({
142
+ source: ({ locale }) => `./locales/${locale}.po`,
143
+ }),
144
+ ],
145
+ };
146
+
147
+ export default config;
148
+ ```
149
+
150
+ #### How it works
151
+
152
+ - Read: the plugin discovers PO files from your `source` builder and loads them as Intlayer dictionaries.
153
+ - Write: after builds and fills, it writes localized PO back to the same paths (with proper Gettext headers).
154
+ - Auto‑fill: the plugin declares an `autoFill` path for each dictionary. Running `intlayer fill` updates only missing translations in your PO files by default.
155
+
156
+ API:
157
+
158
+ ```ts
159
+ syncPO({
160
+ source: ({ key, locale }) => string, // required
161
+ location?: string, // optional label, default: "sync-po::path/to/source"
162
+ priority?: number, // optional priority for conflict resolution, default: 0
163
+ });
164
+ ```
165
+
166
+ ### Multiple PO sources and priority
167
+
168
+ You can add multiple `syncPO` plugins to synchronize different PO sources. This is useful when you have multiple translation sources or different PO structures in your project.
169
+
170
+ #### Priority system
171
+
172
+ When multiple plugins target the same dictionary key, the `priority` parameter determines which plugin takes precedence:
173
+
174
+ - Higher priority numbers win over lower ones
175
+ - Default priority of `.content` files is `0`
176
+ - Default priority of plugins is `0`
177
+ - Plugins with the same priority are processed in the order they appear in the configuration
178
+
179
+ ```ts fileName="intlayer.config.ts"
180
+ import { Locales, type IntlayerConfig } from "intlayer";
181
+ import { syncPO } from "@intlayer/sync-po-plugin";
182
+
183
+ const config: IntlayerConfig = {
184
+ internationalization: {
185
+ locales: [Locales.ENGLISH, Locales.FRENCH],
186
+ defaultLocale: Locales.ENGLISH,
187
+ },
188
+
189
+ plugins: [
190
+ // Primary PO source (highest priority)
191
+ syncPO({
192
+ source: ({ key, locale }) => `./locales/${locale}/${key}.po`,
193
+ location: "main-translations",
194
+ priority: 10,
195
+ }),
196
+
197
+ // Fallback PO source (lower priority)
198
+ syncPO({
199
+ source: ({ locale }) => `./fallback-locales/${locale}.po`,
200
+ location: "fallback-translations",
201
+ priority: 5,
202
+ }),
203
+
204
+ // Legacy PO source (lowest priority)
205
+ syncPO({
206
+ source: ({ locale }) => `/my/other/app/legacy/${locale}/messages.po`,
207
+ location: "legacy-translations",
208
+ priority: 1,
209
+ }),
210
+ ],
211
+ };
212
+
213
+ export default config;
214
+ ```
215
+
216
+ ## Load PO plugin
217
+
218
+ ### Quick start
219
+
220
+ Add the plugin to your `intlayer.config.ts` to ingest existing PO files as Intlayer dictionaries. This plugin is read‑only (no writes to disk):
221
+
222
+ ```ts fileName="intlayer.config.ts"
223
+ import { Locales, type IntlayerConfig } from "intlayer";
224
+ import { loadPO } from "@intlayer/sync-po-plugin";
225
+
226
+ const config: IntlayerConfig = {
227
+ internationalization: {
228
+ locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
229
+ defaultLocale: Locales.ENGLISH,
230
+ },
231
+
232
+ plugins: [
233
+ // Ingest PO messages located anywhere in your source tree
234
+ loadPO({
235
+ source: ({ key }) => `./src/**/${key}.i18n.po`,
236
+ // Load a single locale per plugin instance (defaults to the config defaultLocale)
237
+ locale: Locales.ENGLISH,
238
+ priority: 0,
239
+ }),
240
+ ],
241
+ };
242
+
243
+ export default config;
244
+ ```
245
+
246
+ Alternative: per‑locale layout, still read‑only (only the selected locale is loaded):
247
+
248
+ ```ts fileName="intlayer.config.ts"
249
+ import { Locales, type IntlayerConfig } from "intlayer";
250
+ import { loadPO } from "@intlayer/sync-po-plugin";
251
+
252
+ const config: IntlayerConfig = {
253
+ internationalization: {
254
+ locales: [Locales.ENGLISH, Locales.FRENCH],
255
+ defaultLocale: Locales.ENGLISH,
256
+ },
257
+ plugins: [
258
+ loadPO({
259
+ // Only files for Locales.FRENCH will be loaded from this pattern
260
+ source: ({ key, locale }) => `./locales/${locale}/${key}.po`,
261
+ locale: Locales.FRENCH,
262
+ }),
263
+ ],
264
+ };
265
+
266
+ export default config;
267
+ ```
268
+
269
+ ### How it works
270
+
271
+ - Discover: builds a glob from your `source` builder and collects matching PO files.
272
+ - Ingest: loads each PO file as an Intlayer dictionary with the provided `locale`.
273
+ - Read‑only: does not write or format output files; use `syncPO` if you need round‑trip sync.
274
+ - Auto‑fill ready: defines a `fill` path so `intlayer content fill` can populate missing keys.
275
+
276
+ ### API
277
+
278
+ ```ts
279
+ loadPO({
280
+ // Build paths to your PO. `locale` is optional if your structure has no locale segment
281
+ source: ({ key, locale }) => string,
282
+
283
+ // Target locale for the dictionaries loaded by this plugin instance
284
+ // Defaults to configuration.internationalization.defaultLocale
285
+ locale?: Locale,
286
+
287
+ // Optional label to identify the source
288
+ location?: string, // default: "plugin"
289
+
290
+ // Priority used for conflict resolution against other sources
291
+ priority?: number, // default: 0
292
+ });
293
+ ```
294
+
295
+ ### Behavior and conventions
296
+
297
+ - If your `source` mask includes a locale placeholder, only files for the selected `locale` are ingested.
298
+ - If there is no `{key}` segment in your mask, the dictionary key is "index".
299
+ - Keys are derived from file paths by substituting the `{key}` placeholder in your `source` builder.
300
+ - The plugin only uses discovered files and does not fabricate missing locales or keys.
301
+ - The `fill` path is inferred from your `source` and used to update missing values via CLI when you opt‑in.
302
+
303
+ ## Conflict resolution
304
+
305
+ When the same translation key exists in multiple PO sources:
306
+
307
+ 1. The plugin with the highest priority determines the final value
308
+ 2. Lower priority sources are used as fallbacks for missing keys
309
+ 3. This allows you to maintain legacy translations while gradually migrating to new structures
310
+
311
+ ## CLI
312
+
313
+ The synchronized PO files will be considered as other `.content` files. That means, all intlayer commands will be available for the synchronized PO files. Including:
314
+
315
+ - `intlayer content test` to test if there are missing translations
316
+ - `intlayer content list` to list the synchronized PO files
317
+ - `intlayer content fill` to fill the missing translations
318
+ - `intlayer content push` to push the synchronized PO files
319
+ - `intlayer content pull` to pull the synchronized PO files
320
+
321
+ See [Intlayer CLI](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/cli/index.md) for more details.
322
+
323
+ ## Limitations (current)
324
+
325
+ - No insertions or plurals/ICU support when targeting third‑party libraries.
326
+ - Visual editor is not available for non‑Intlayer runtimes yet.
327
+ - PO synchronization only; non‑PO catalog formats are not supported.
328
+
329
+ ## Why this matters
330
+
331
+ - We can recommend established i18n solutions and position Intlayer as an add‑on.
332
+ - We leverage their SEO/keywords with tutorials that end by suggesting Intlayer to manage PO.
333
+ - Expands the addressable audience from “new projects” to “any team already using i18n”.
@@ -30,6 +30,3 @@ Find the detailed reports and technical documentation for each framework below:
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 @@ Because the problem is hard, many solutions exist—some focused on DX, others o
61
61
 
62
62
  Intlayer tries to optimise across these dimensions.
63
63
 
64
+ ## TL;DR
65
+
66
+ - **Intlayer** & **next-translate**: Best choices for Next.js performance, offering the smallest footprint and best static rendering support.
67
+ - **next-intl**: The trendiest option, but heavy and complex to optimise for large applications.
68
+ - **next-i18next**: Popular and plugin-rich, but carries significant bundle weight (~3× Intlayer).
69
+ - **Avoid**: **gt-next** and **lingo.dev** due to severe performance issues, vendor lock-in, and build-breaking bugs.
70
+
64
71
  ## Test your app
65
72
 
66
73
  To surface these issues, I built a free scanner you can try [here](https://intlayer.org/i18n-seo-scanner).
@@ -99,14 +106,14 @@ Finally, `Intlayer` applies a build-time optimisation so `useIntlayer('my-key')`
99
106
  For this benchmark, we compared the following libraries:
100
107
 
101
108
  - `Base App` (No i18n library)
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 @@ Issues encountered:
161
168
 
162
169
  **(General Translation)** (`gt-next@6.16.5`):
163
170
 
164
- - For a 110kb app, `gt-react` adds more than 440kb extra.
171
+ - For a 110kb app, `gt-next` adds more than 440kb extra.
165
172
  - `Quota Exceeded, please upgrade your plan` on the very first build with General Translation.
166
173
  - Translations are not rendered; I get the error `Error: <T> used on the client-side outside of <GTProvider>`, which seems to be a bug in the library.
167
- - While implementing **gt-tanstack-start-react**, I also came across an [issue](https://github.com/generaltranslation/gt/issues/1210#event-24510646961) with the library: `does not provide an export named 'printAST' - @formatjs/icu-messageformat-parser`, which was making the application break. After reporting this issue, the maintainer fixed it within 24 hours.
174
+ - While implementing **gt-next**, I also came across an [issue](https://github.com/generaltranslation/gt/issues/1210#event-24510646961) with the library: `does not provide an export named 'printAST' - @formatjs/icu-messageformat-parser`, which was making the application break. After reporting this issue, the maintainer fixed it within 24 hours.
168
175
  - The library blocks static rendering of Next.js pages.
169
176
 
170
177
  **(Lingo.dev)** (`@lingo.dev/compiler@0.4.0`):
@@ -187,9 +194,11 @@ Personally I dislike having to regenerate JS files before every push, which crea
187
194
  Even if in theory the tree-shaking strategy works, it does includes all locales in the bundle anyway. Paraglide offers not way to lazy-load the content. That says your page size will grow up correlated to the number of locales you have.
188
195
  Finally, in comparison of other solutions, Paraglide does not use store (e.g. React context) to retrieve the current locale to render the content. For each node parsed, it will request the locale from the localeStorage / cookie etc. It leads to execution of unnecessary logic that impact the component reactivity.
189
196
 
197
+ > Note on paraglide: the solution injects code into your codebase for import, as a result the 'lib size' metric in the benchmark report is nearly 0. Code generation is a good thing, because the function used will include only the necessary logic (all prefixes vs no prefixes, cookies vs storage, etc.). In comparison, Intlayer performs this filtering via environment variable injections in the build to force the bundler to tree-shake content depending on the logic. Thanks to this, paraglide and intlayer end up being 6 to 10 times lighter solutions than i18next or next-intl.
198
+
190
199
  ### 3 — Acceptable solutions
191
200
 
192
- **(Tolgee)** (`tolgee@7.0.0`):
201
+ **(Tolgee)** (`@tolgee/react@7.0.0`):
193
202
 
194
203
  `Tolgee` addresses many of the issues mentioned earlier. I found it harder to adopt than similar tools. It does not provide type safety, which also makes catching missing keys at compile time harder. I had to wrap Tolgee’s functions with my own to add missing-key detection.
195
204
 
@@ -217,7 +226,7 @@ Message formats also differ: `next-intl` uses ICU MessageFormat, while `i18next`
217
226
 
218
227
  `next-translate` is my main recommendation if you like a `t()`-style API. It is elegant via `next-translate-plugin`, loading namespaces through `getStaticProps` with a Webpack / Turbopack loader. It is also the lightest option here (~2.5kb). For namespacing, defining namespaces per page or route in config is well thought out and easier to maintain than main alternatives like **next-intl** or **next-i18next**. In version `3.1.2`, I noted that static rendering did not work; Next.js fell back to dynamic rendering.
219
228
 
220
- **(Intlayer)** (`next-intlayer@8.7.5`):
229
+ **(Intlayer)** (`next-intlayer@8.7.12`):
221
230
 
222
231
  I will not personally judge `next-intlayer` for objectivity’s sake, since it is my own solution.
223
232
 
@@ -0,0 +1,155 @@
1
+ ---
2
+ createdAt: 2026-04-20
3
+ updatedAt: 2026-04-21
4
+ title: Best i18n solution for Solid in 2026 - Benchmark Report
5
+ description: Compare Solid internationalisation (i18n) libraries like solid-primitives, solid-i18next, and Intlayer. Detailed performance report on bundle size, leakage, and reactivity.
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: "Init benchmark"
23
+ ---
24
+
25
+ # Solid i18n Libraries — 2026 Benchmark Report
26
+
27
+ This page is a benchmark report for i18n solutions on Solid.
28
+
29
+ ## Table of Contents
30
+
31
+ <Toc/>
32
+
33
+ ## Interactive Benchmark
34
+
35
+ <I18nBenchmark framework="vite-solid" 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_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
+ 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 Solid 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**: Recommended choice for professional Solid applications needing advanced features and optimisation (v8.7.12).
63
+ - **@solid-primitives/i18n**: Excellent lightweight alternative for simple projects, though lacks advanced features like lazy loading.
64
+ - **solid-i18next**: Standard but heavy option (~4.7× Intlayer) with same downsides as React i18next.
65
+ - **Paraglide**: Innovative approach but complex DX and tree-shaking issues in some setups.
66
+
67
+ ## Test your app
68
+
69
+ To quickly spot i18n leakage issues, I set up a free scanner available [here](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
+ ## The problem
74
+
75
+ Two levers are essential to limit the cost of a multilingual app:
76
+
77
+ - Split content by page / namespace so you do not load whole dictionaries when you do not need them
78
+ - Load the right locale dynamically, only when needed
79
+
80
+ Understanding the technical limitations of these approaches:
81
+
82
+ **Dynamic loading**
83
+
84
+ Without dynamic loading, most solutions keep messages in memory from the first render, which adds significant overhead for apps with many routes and locales.
85
+
86
+ With dynamic loading, you accept a trade-off: less initial JS, but sometimes an extra request when switching language.
87
+
88
+ **Content splitting**
89
+
90
+ Syntaxes built around `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.
91
+
92
+ ## Methodology
93
+
94
+ For this benchmark, we compared the following libraries:
95
+
96
+ - `Base App` (No i18n library)
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
+ The framework is `Solid` with a multilingual app of **10 pages** and **10 languages**.
103
+
104
+ We compared **four loading strategies**:
105
+
106
+ | Strategy | No namespaces (global) | With namespaces (scoped) |
107
+ | :------------------ | :------------------------------------------- | :------------------------------------------------------------------- |
108
+ | **Static loading** | **Static**: Everything in memory at startup. | **Scoped static**: Split by namespace; everything loaded at startup. |
109
+ | **Dynamic loading** | **Dynamic**: On-demand loading per locale. | **Scoped dynamic**: Granular loading per namespace and locale. |
110
+
111
+ ## Strategy summary
112
+
113
+ - **Static**: Simple; no network latency after the initial load. Downside: large bundle size.
114
+ - **Dynamic**: Reduces initial weight (lazy-loading). Ideal when you have many locales.
115
+ - **Scoped static**: Keeps code organised (logical separation) without complex extra network requests.
116
+ - **Scoped dynamic**: Best approach for _code splitting_ and performance. Minimises memory by loading only what the current view and active locale need.
117
+
118
+ ## Results in detail
119
+
120
+ ### 1 — Solutions to avoid
121
+
122
+ > No clear solution to avoid in solid ecosystem.
123
+
124
+ ### 2 — Acceptable solutions
125
+
126
+ **(solid-i18next)** (`solid-i18next@17.0.2`):
127
+
128
+ `solid-i18next` is probably the most popular option because it was among the first to serve JavaScript app i18n needs. It also has a wide set of community plugins for specific problems.
129
+
130
+ The package is heavy (~14.6kb, which is about 4.7× `solid-intlayer`).
131
+
132
+ Still, it shares the same major downsides as stacks built on `t('a.b.c')`: optimisations are possible but very time-consuming, and large projects risk bad practices (namespaces + dynamic loading + types).
133
+
134
+ **(@solid-primitives/i18n)** (`@solid-primitives/i18n@2.2.1`):
135
+
136
+ Solid primitive is extremely light and efficient. I recommend that solution for light projects, but it can quickly become lacking features for professional solutions including cookie management, proxy redirection, formatters etc.
137
+ It also misses lazy loading and scoping namespaces for page size optimisation.
138
+
139
+ **(Paraglide)** (`@inlang/paraglide-js@2.17.0`):
140
+
141
+ `Paraglide` offers an innovative, well-thought-out approach. Even so, in this benchmark the tree-shaking their company advertises did not work for my implementation. The workflow and DX are also more complex than other options.
142
+ Personally I dislike having to regenerate JS files before every push, which creates constant merge conflict risk via PRs.
143
+ Finally, in comparison with other solutions, Paraglide does not use a store (e.g. Solid signal) to retrieve the current locale to render the content. For each node parsed, it will request the locale from the localStorage / cookie etc. It leads to execution of unnecessary logic that impacts the component reactivity.
144
+
145
+ ### 3 — Recommendations
146
+
147
+ **(Intlayer)** (`solid-intlayer@8.7.12`):
148
+
149
+ I will not personally judge `solid-intlayer` for objectivity’s sake, since it is my own solution.
150
+
151
+ ### Personal note
152
+
153
+ This note is personal and does not affect the benchmark results. Still, in the i18n world you often see consensus around a pattern like `const t = useTranslation('xx')` + `<>{t('xx.xx')}</>` for translated content.
154
+
155
+ In Solid apps, injecting a function as a `JSX.Element` is, in my view, an anti-pattern. It also adds avoidable complexity and JavaScript execution overhead (even if it is barely noticeable).