@intlayer/docs 8.10.1 → 8.11.2

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 (198) hide show
  1. package/blog/en/i18n_using_next-i18next.md +3 -3
  2. package/blog/en/i18n_using_next-intl.md +3 -3
  3. package/blog/en/list_i18n_technologies/frameworks/angular.md +3 -3
  4. package/blog/en/list_i18n_technologies/frameworks/react-native.md +3 -3
  5. package/blog/en/list_i18n_technologies/frameworks/react.md +3 -3
  6. package/blog/en/list_i18n_technologies/frameworks/svelte.md +3 -3
  7. package/blog/en/list_i18n_technologies/frameworks/vue.md +3 -3
  8. package/blog/en/next-i18next_vs_next-intl_vs_intlayer.md +3 -3
  9. package/dist/cjs/common.cjs +3 -1
  10. package/dist/cjs/common.cjs.map +1 -1
  11. package/dist/cjs/generated/blog.entry.cjs +0 -1
  12. package/dist/cjs/generated/blog.entry.cjs.map +1 -1
  13. package/dist/cjs/generated/docs.entry.cjs +39 -20
  14. package/dist/cjs/generated/docs.entry.cjs.map +1 -1
  15. package/dist/cjs/generated/frequentQuestions.entry.cjs +0 -1
  16. package/dist/cjs/generated/frequentQuestions.entry.cjs.map +1 -1
  17. package/dist/cjs/generated/legal.entry.cjs +0 -1
  18. package/dist/cjs/generated/legal.entry.cjs.map +1 -1
  19. package/dist/esm/common.mjs +3 -1
  20. package/dist/esm/common.mjs.map +1 -1
  21. package/dist/esm/generated/docs.entry.mjs +39 -19
  22. package/dist/esm/generated/docs.entry.mjs.map +1 -1
  23. package/dist/types/common.d.ts.map +1 -1
  24. package/dist/types/generated/docs.entry.d.ts +2 -1
  25. package/dist/types/generated/docs.entry.d.ts.map +1 -1
  26. package/docs/ar/benchmark/nextjs.md +1 -1
  27. package/docs/ar/benchmark/solid.md +1 -1
  28. package/docs/ar/benchmark/svelte.md +1 -1
  29. package/docs/ar/benchmark/tanstack.md +1 -1
  30. package/docs/ar/dictionary/markdown.md +165 -7
  31. package/docs/ar/{intlayer_with_angular.md → intlayer_with_angular_19.md} +8 -7
  32. package/docs/ar/intlayer_with_angular_21.md +412 -0
  33. package/docs/bn/intlayer_with_angular_21.md +412 -0
  34. package/docs/cs/intlayer_with_angular_21.md +412 -0
  35. package/docs/de/benchmark/nextjs.md +1 -1
  36. package/docs/de/benchmark/solid.md +1 -1
  37. package/docs/de/benchmark/svelte.md +1 -1
  38. package/docs/de/benchmark/tanstack.md +1 -1
  39. package/docs/de/dictionary/markdown.md +165 -7
  40. package/docs/de/{intlayer_with_angular.md → intlayer_with_angular_19.md} +8 -7
  41. package/docs/de/intlayer_with_angular_21.md +412 -0
  42. package/docs/en/benchmark/nextjs.md +1 -1
  43. package/docs/en/benchmark/solid.md +1 -1
  44. package/docs/en/benchmark/svelte.md +1 -1
  45. package/docs/en/benchmark/tanstack.md +1 -1
  46. package/docs/en/dictionary/markdown.md +167 -7
  47. package/docs/en/intlayer_with_adonisjs.md +3 -3
  48. package/docs/en/intlayer_with_analog.md +3 -3
  49. package/docs/en/{intlayer_with_angular.md → intlayer_with_angular_19.md} +10 -9
  50. package/docs/en/intlayer_with_angular_21.md +412 -0
  51. package/docs/en/intlayer_with_astro.md +3 -3
  52. package/docs/en/intlayer_with_astro_lit.md +3 -3
  53. package/docs/en/intlayer_with_astro_preact.md +3 -3
  54. package/docs/en/intlayer_with_astro_react.md +3 -3
  55. package/docs/en/intlayer_with_astro_solid.md +3 -3
  56. package/docs/en/intlayer_with_astro_svelte.md +3 -3
  57. package/docs/en/intlayer_with_astro_vanilla.md +3 -3
  58. package/docs/en/intlayer_with_astro_vue.md +3 -3
  59. package/docs/en/intlayer_with_create_react_app.md +3 -3
  60. package/docs/en/intlayer_with_express.md +3 -3
  61. package/docs/en/intlayer_with_fastify.md +3 -3
  62. package/docs/en/intlayer_with_hono.md +3 -3
  63. package/docs/en/intlayer_with_lynx+react.md +3 -3
  64. package/docs/en/intlayer_with_nestjs.md +3 -3
  65. package/docs/en/intlayer_with_next-i18next.md +3 -3
  66. package/docs/en/intlayer_with_next-intl.md +3 -3
  67. package/docs/en/intlayer_with_nextjs_14.md +3 -3
  68. package/docs/en/intlayer_with_nextjs_15.md +3 -3
  69. package/docs/en/intlayer_with_nextjs_16.md +3 -3
  70. package/docs/en/intlayer_with_nextjs_compiler.md +3 -3
  71. package/docs/en/intlayer_with_nextjs_no_locale_path.md +3 -3
  72. package/docs/en/intlayer_with_nextjs_page_router.md +3 -3
  73. package/docs/en/intlayer_with_nuxt.md +3 -3
  74. package/docs/en/intlayer_with_react_native+expo.md +3 -3
  75. package/docs/en/intlayer_with_react_router_v7.md +3 -3
  76. package/docs/en/intlayer_with_react_router_v7_fs_routes.md +3 -3
  77. package/docs/en/intlayer_with_svelte_kit.md +3 -3
  78. package/docs/en/intlayer_with_tanstack+solid.md +3 -3
  79. package/docs/en/intlayer_with_tanstack.md +3 -3
  80. package/docs/en/intlayer_with_vanilla.md +3 -3
  81. package/docs/en/intlayer_with_vite+lit.md +3 -3
  82. package/docs/en/intlayer_with_vite+preact.md +3 -3
  83. package/docs/en/intlayer_with_vite+react.md +3 -3
  84. package/docs/en/intlayer_with_vite+react_compiler.md +3 -3
  85. package/docs/en/intlayer_with_vite+solid.md +3 -3
  86. package/docs/en/intlayer_with_vite+svelte.md +3 -3
  87. package/docs/en/intlayer_with_vite+vanilla.md +3 -3
  88. package/docs/en/intlayer_with_vite+vue.md +3 -3
  89. package/docs/en-GB/benchmark/nextjs.md +1 -1
  90. package/docs/en-GB/benchmark/solid.md +1 -1
  91. package/docs/en-GB/benchmark/svelte.md +1 -1
  92. package/docs/en-GB/benchmark/tanstack.md +1 -1
  93. package/docs/en-GB/dictionary/markdown.md +161 -0
  94. package/docs/en-GB/{intlayer_with_angular.md → intlayer_with_angular_19.md} +8 -7
  95. package/docs/en-GB/intlayer_with_angular_21.md +412 -0
  96. package/docs/es/benchmark/nextjs.md +1 -1
  97. package/docs/es/benchmark/solid.md +1 -1
  98. package/docs/es/benchmark/svelte.md +1 -1
  99. package/docs/es/benchmark/tanstack.md +1 -1
  100. package/docs/es/dictionary/markdown.md +165 -7
  101. package/docs/es/{intlayer_with_angular.md → intlayer_with_angular_19.md} +8 -7
  102. package/docs/es/intlayer_with_angular_21.md +412 -0
  103. package/docs/fr/benchmark/nextjs.md +1 -1
  104. package/docs/fr/benchmark/solid.md +1 -1
  105. package/docs/fr/benchmark/svelte.md +1 -1
  106. package/docs/fr/benchmark/tanstack.md +1 -1
  107. package/docs/fr/dictionary/markdown.md +165 -7
  108. package/docs/fr/{intlayer_with_angular.md → intlayer_with_angular_19.md} +8 -7
  109. package/docs/fr/intlayer_with_angular_21.md +412 -0
  110. package/docs/hi/benchmark/nextjs.md +1 -1
  111. package/docs/hi/benchmark/solid.md +1 -1
  112. package/docs/hi/benchmark/svelte.md +1 -1
  113. package/docs/hi/benchmark/tanstack.md +1 -1
  114. package/docs/hi/dictionary/markdown.md +165 -7
  115. package/docs/hi/{intlayer_with_angular.md → intlayer_with_angular_19.md} +8 -7
  116. package/docs/hi/intlayer_with_angular_21.md +412 -0
  117. package/docs/id/benchmark/nextjs.md +1 -1
  118. package/docs/id/benchmark/solid.md +1 -1
  119. package/docs/id/benchmark/svelte.md +1 -1
  120. package/docs/id/benchmark/tanstack.md +1 -1
  121. package/docs/id/dictionary/markdown.md +165 -7
  122. package/docs/id/{intlayer_with_angular.md → intlayer_with_angular_19.md} +8 -7
  123. package/docs/id/intlayer_with_angular_21.md +412 -0
  124. package/docs/it/benchmark/nextjs.md +1 -1
  125. package/docs/it/benchmark/solid.md +1 -1
  126. package/docs/it/benchmark/svelte.md +1 -1
  127. package/docs/it/benchmark/tanstack.md +1 -1
  128. package/docs/it/dictionary/markdown.md +165 -7
  129. package/docs/it/{intlayer_with_angular.md → intlayer_with_angular_19.md} +8 -7
  130. package/docs/it/intlayer_with_angular_21.md +412 -0
  131. package/docs/ja/benchmark/nextjs.md +1 -1
  132. package/docs/ja/benchmark/solid.md +1 -1
  133. package/docs/ja/benchmark/svelte.md +1 -1
  134. package/docs/ja/benchmark/tanstack.md +1 -1
  135. package/docs/ja/{intlayer_with_angular.md → intlayer_with_angular_19.md} +8 -7
  136. package/docs/ja/intlayer_with_angular_21.md +412 -0
  137. package/docs/ko/benchmark/nextjs.md +1 -1
  138. package/docs/ko/benchmark/solid.md +1 -1
  139. package/docs/ko/benchmark/svelte.md +1 -1
  140. package/docs/ko/benchmark/tanstack.md +1 -1
  141. package/docs/ko/dictionary/markdown.md +165 -7
  142. package/docs/ko/{intlayer_with_angular.md → intlayer_with_angular_19.md} +8 -7
  143. package/docs/ko/intlayer_with_angular_21.md +412 -0
  144. package/docs/nl/intlayer_with_angular_21.md +412 -0
  145. package/docs/pl/benchmark/nextjs.md +1 -1
  146. package/docs/pl/benchmark/solid.md +1 -1
  147. package/docs/pl/benchmark/svelte.md +1 -1
  148. package/docs/pl/benchmark/tanstack.md +1 -1
  149. package/docs/pl/dictionary/markdown.md +165 -7
  150. package/docs/pl/{intlayer_with_angular.md → intlayer_with_angular_19.md} +8 -7
  151. package/docs/pl/intlayer_with_angular_21.md +412 -0
  152. package/docs/pt/benchmark/nextjs.md +1 -1
  153. package/docs/pt/benchmark/solid.md +1 -1
  154. package/docs/pt/benchmark/svelte.md +1 -1
  155. package/docs/pt/benchmark/tanstack.md +1 -1
  156. package/docs/pt/dictionary/markdown.md +165 -7
  157. package/docs/pt/{intlayer_with_angular.md → intlayer_with_angular_19.md} +8 -7
  158. package/docs/pt/intlayer_with_angular_21.md +412 -0
  159. package/docs/ru/benchmark/nextjs.md +1 -1
  160. package/docs/ru/benchmark/solid.md +1 -1
  161. package/docs/ru/benchmark/svelte.md +1 -1
  162. package/docs/ru/benchmark/tanstack.md +1 -1
  163. package/docs/ru/dictionary/markdown.md +161 -0
  164. package/docs/ru/{intlayer_with_angular.md → intlayer_with_angular_19.md} +8 -7
  165. package/docs/ru/intlayer_with_angular_21.md +412 -0
  166. package/docs/tr/benchmark/nextjs.md +1 -1
  167. package/docs/tr/benchmark/solid.md +1 -1
  168. package/docs/tr/benchmark/svelte.md +1 -1
  169. package/docs/tr/benchmark/tanstack.md +1 -1
  170. package/docs/tr/dictionary/markdown.md +165 -7
  171. package/docs/tr/{intlayer_with_angular.md → intlayer_with_angular_19.md} +8 -7
  172. package/docs/tr/intlayer_with_angular_21.md +412 -0
  173. package/docs/uk/benchmark/nextjs.md +1 -1
  174. package/docs/uk/benchmark/solid.md +1 -1
  175. package/docs/uk/benchmark/svelte.md +1 -1
  176. package/docs/uk/benchmark/tanstack.md +1 -1
  177. package/docs/uk/dictionary/markdown.md +165 -7
  178. package/docs/uk/{intlayer_with_angular.md → intlayer_with_angular_19.md} +8 -7
  179. package/docs/uk/intlayer_with_angular_21.md +412 -0
  180. package/docs/ur/intlayer_with_angular_21.md +412 -0
  181. package/docs/vi/benchmark/nextjs.md +1 -1
  182. package/docs/vi/benchmark/solid.md +1 -1
  183. package/docs/vi/benchmark/svelte.md +1 -1
  184. package/docs/vi/benchmark/tanstack.md +1 -1
  185. package/docs/vi/dictionary/markdown.md +165 -7
  186. package/docs/vi/{intlayer_with_angular.md → intlayer_with_angular_19.md} +8 -7
  187. package/docs/vi/intlayer_with_angular_21.md +412 -0
  188. package/docs/zh/benchmark/nextjs.md +1 -1
  189. package/docs/zh/benchmark/solid.md +1 -1
  190. package/docs/zh/benchmark/svelte.md +1 -1
  191. package/docs/zh/benchmark/tanstack.md +1 -1
  192. package/docs/zh/dictionary/markdown.md +165 -7
  193. package/docs/zh/{intlayer_with_angular.md → intlayer_with_angular_19.md} +8 -7
  194. package/docs/zh/intlayer_with_angular_21.md +412 -0
  195. package/docs/zh-TW/intlayer_with_angular_21.md +412 -0
  196. package/package.json +7 -7
  197. package/src/common.ts +12 -6
  198. package/src/generated/docs.entry.ts +39 -19
@@ -17,6 +17,9 @@ slugs:
17
17
  - content
18
18
  - markdown
19
19
  history:
20
+ - version: 8.11.0
21
+ date: 2026-05-28
22
+ changes: "Automatic decoration of markdown content, MDX and SSR support"
20
23
  - version: 8.10.0
21
24
  date: 2026-05-19
22
25
  changes: "Add `.content.md` files support"
@@ -68,13 +71,10 @@ You can declare Markdown content using the `md` function or simply as a string (
68
71
  Example of file structure:
69
72
 
70
73
  ```text
71
- content/
72
- ├── en/
73
- │ └── markdown-file.en.content.md
74
- ├── fr/
75
- │ └── markdown-file.fr.content.md
76
- └── es/
77
- └── markdown-file.es.content.md
74
+ content
75
+ ├── markdown-file.en.content.md
76
+ ├── markdown-file.fr.content.md
77
+ └── markdown-file.es.content.md
78
78
  ```
79
79
 
80
80
  You can add in front-matter any properties defined in the [Dictionary definition](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/dictionary/content_file.md)
@@ -1171,6 +1171,166 @@ export class MyComponent {
1171
1171
  </Tab>
1172
1172
  </Tabs>
1173
1173
 
1174
+ ---
1175
+
1176
+ ## Server-Side Rendering (SSR) and Hydration
1177
+
1178
+ In comparison of other Markdown parser such as remark / rehype, the Intlayer Markdown is dependency free and run on client as server side.
1179
+
1180
+ But Intlayer optimized the parsing for Server-Side Rendering (SSR) frameworks (such as Next.js App Router, React Router, Nuxt, SvelteKit, etc.).
1181
+
1182
+ Instead of sending raw Markdown strings to the client and parsing them on the browser (which incurs a performance penalty), Intlayer allows you to pre-parse the Markdown into an Abstract Syntax Tree (AST) on the server.
1183
+
1184
+ You can use the `parseMarkdown` function from your framework's Intlayer package on the server side to generate a serializable AST (`ParsedMarkdown` object), and pass it directly to the frontend. All Intlayer rendering utilities (like `<MarkdownRenderer>`, `useMarkdownRenderer`, etc.) automatically accept this AST object and render it seamlessly.
1185
+
1186
+ ### Example in a Server/Client Architecture
1187
+
1188
+ <Tabs group="framework">
1189
+ <Tab label="React Router" value="react">
1190
+
1191
+ ```tsx fileName="server.ts"
1192
+ import { parseMarkdown } from "react-intlayer/markdown";
1193
+
1194
+ // 1. On the server: Parse the markdown into a serializable AST
1195
+ export const loader = async () => {
1196
+ const markdownString = "## My title \n\nLorem Ipsum";
1197
+ const ast = parseMarkdown(markdownString);
1198
+
1199
+ // Return the AST as JSON to the client
1200
+ return Response.json({ content: ast });
1201
+ };
1202
+ ```
1203
+
1204
+ ```tsx fileName="client.tsx"
1205
+ import { useLoaderData } from "react-router";
1206
+ import { MarkdownRenderer } from "react-intlayer/markdown";
1207
+
1208
+ // 2. On the client: Render the AST directly without re-parsing
1209
+ export default function Page() {
1210
+ const { content } = useLoaderData();
1211
+
1212
+ // The renderer accepts either a raw string or the parsed AST
1213
+ return <MarkdownRenderer content={content} />;
1214
+ }
1215
+ ```
1216
+
1217
+ </Tab>
1218
+ <Tab label="Next.js" value="nextjs">
1219
+
1220
+ ```tsx fileName="app/page.tsx"
1221
+ import { parseMarkdown } from "next-intlayer/markdown";
1222
+ import { MarkdownRenderer } from "next-intlayer/markdown";
1223
+
1224
+ export default async function Page() {
1225
+ // 1. Parse the markdown into a serializable AST on the server
1226
+ const markdownString = "## My title \n\nLorem Ipsum";
1227
+ const ast = parseMarkdown(markdownString);
1228
+
1229
+ // 2. Render the AST directly
1230
+ // In a Server Component, this works seamlessly and passes the AST
1231
+ // directly to the underlying client components if needed.
1232
+ return <MarkdownRenderer content={ast} />;
1233
+ }
1234
+ ```
1235
+
1236
+ </Tab>
1237
+ <Tab label="Vue / Nuxt" value="vue">
1238
+
1239
+ ```vue fileName="pages/index.vue"
1240
+ <script setup lang="ts">
1241
+ import { parseMarkdown } from "vue-intlayer/markdown";
1242
+ import { MarkdownRenderer } from "vue-intlayer/markdown";
1243
+
1244
+ // 1. Fetch and parse the markdown into an AST on the server
1245
+ const { data: ast } = await useAsyncData('markdown', () => {
1246
+ const markdownString = "## My title \n\nLorem Ipsum";
1247
+ return parseMarkdown(markdownString);
1248
+ });
1249
+ </script>
1250
+
1251
+ <template>
1252
+ <!-- 2. On the client: Render the AST directly without re-parsing -->
1253
+ <MarkdownRenderer :content="ast" />
1254
+ </template>
1255
+ ```
1256
+
1257
+ </Tab>
1258
+ <Tab label="SvelteKit" value="svelte">
1259
+
1260
+ ```typescript fileName="+page.server.ts"
1261
+ import { parseMarkdown } from "svelte-intlayer/markdown";
1262
+
1263
+ // 1. On the server: Parse the markdown into a serializable AST
1264
+ export const load = async () => {
1265
+ const markdownString = "## My title \n\nLorem Ipsum";
1266
+ const ast = parseMarkdown(markdownString);
1267
+
1268
+ // Return the AST to the client
1269
+ return { content: ast };
1270
+ };
1271
+ ```
1272
+
1273
+ ```svelte fileName="+page.svelte"
1274
+ <script lang="ts">
1275
+ import { MarkdownRenderer } from "svelte-intlayer/markdown";
1276
+ export let data;
1277
+ </script>
1278
+
1279
+ <!-- 2. On the client: Render the AST directly without re-parsing -->
1280
+ <MarkdownRenderer value={data.content} />
1281
+ ```
1282
+
1283
+ </Tab>
1284
+ <Tab label="Angular" value="angular">
1285
+
1286
+ Angular SSR typically resolves the data on the server during the initial load and hydrates on the client. You can use resolvers to pass the AST.
1287
+
1288
+ ```typescript fileName="app.resolver.ts"
1289
+ import { Injectable } from "@angular/core";
1290
+ import { Resolve } from "@angular/router";
1291
+ import { parseMarkdown, type ParsedMarkdown } from "angular-intlayer/markdown";
1292
+
1293
+ @Injectable({ providedIn: "root" })
1294
+ export class MarkdownResolver implements Resolve<ParsedMarkdown> {
1295
+ resolve(): ParsedMarkdown {
1296
+ const markdownString = "## My title \n\nLorem Ipsum";
1297
+ // 1. On the server: Parse the markdown into a serializable AST
1298
+ return parseMarkdown(markdownString);
1299
+ }
1300
+ }
1301
+ ```
1302
+
1303
+ ```typescript fileName="app.component.ts"
1304
+ import { Component } from "@angular/core";
1305
+ import { ActivatedRoute } from "@angular/router";
1306
+ import { IntlayerMarkdownService, type ParsedMarkdown } from "angular-intlayer/markdown";
1307
+
1308
+ @Component({
1309
+ selector: "app-root",
1310
+ template: `<div [innerHTML]="renderedMarkdown"></div>`,
1311
+ })
1312
+ export class AppComponent {
1313
+ renderedMarkdown: string = "";
1314
+
1315
+ constructor(
1316
+ private route: ActivatedRoute,
1317
+ private markdownService: IntlayerMarkdownService
1318
+ ) {
1319
+ // 2. On the client: Render the AST directly without re-parsing
1320
+ this.route.data.subscribe((data) => {
1321
+ this.renderedMarkdown = this.markdownService.renderMarkdown(
1322
+ data.markdownAst
1323
+ ) as string;
1324
+ });
1325
+ }
1326
+ }
1327
+ ```
1328
+
1329
+ </Tab>
1330
+ </Tabs>
1331
+
1332
+ This pattern ensures that the Markdown parsing logic is executed entirely on the server, significantly reducing the client-side execution time and improving the initial hydration speed.
1333
+
1174
1334
  ## Options Reference
1175
1335
 
1176
1336
  These options can be passed to `MarkdownProvider`, `MarkdownRenderer`, `useMarkdownRenderer`, and `renderMarkdown`.
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  createdAt: 2025-08-23
3
- updatedAt: 2026-05-06
4
- title: AdonisJS i18n - How to translate an AdonisJS app in 2026
5
- description: Discover how to make your AdonisJS backend multilingual. Follow the documentation to internationalize (i18n) and translate it.
3
+ updatedAt: 2026-05-31
4
+ title: AdonisJS i18n - Complete guide to translate an AdonisJS app
5
+ description: Optimized solution for bundle size, SEO, performances & maintainability. Make your AdonisJS backend multilingual in 2026, LLM translation, Agent Skills & MCP.
6
6
  keywords:
7
7
  - Internationalization
8
8
  - Documentation
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  createdAt: 2025-04-18
3
- updatedAt: 2026-05-06
4
- title: Analog i18n - How to translate an Analog app in 2026
5
- description: Discover how to make your Analog app multilingual. Follow the documentation to internationalize (i18n) and translate it.
3
+ updatedAt: 2026-05-31
4
+ title: Analog i18n - Complete guide to translate an Analog app
5
+ description: Optimized solution for bundle size, SEO, performances & maintainability. Make your Analog application multilingual in 2026, LLM translation, Agent Skills & MCP.
6
6
  keywords:
7
7
  - Internationalization
8
8
  - Documentation
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  createdAt: 2025-04-18
3
- updatedAt: 2026-05-06
4
- title: Angular i18n - How to translate an Angular app in 2026
5
- description: Discover how to make your Angular website multilingual. Follow the documentation to internationalize (i18n) and translate it.
3
+ updatedAt: 2026-05-31
4
+ title: Angular i18n - Complete guide to translate an Angular 19 app (Webpack)
5
+ description: Optimized solution for bundle size, SEO, performances & maintainability. Make your Angular 19 application multilingual in 2026, LLM translation, Agent Skills & MCP.
6
6
  keywords:
7
7
  - Internationalization
8
8
  - Documentation
@@ -13,8 +13,9 @@ slugs:
13
13
  - doc
14
14
  - environment
15
15
  - angular
16
- applicationTemplate: https://github.com/aymericzip/intlayer-angular-template
17
- applicationShowcase: https://intlayer-angular-template.vercel.app
16
+ - 19
17
+ applicationTemplate: https://github.com/aymericzip/intlayer-angular-19-template
18
+ applicationShowcase: https://intlayer-angular-19-template.vercel.app
18
19
  history:
19
20
  - version: 8.9.0
20
21
  date: 2026-05-04
@@ -30,7 +31,7 @@ history:
30
31
  changes: "Initial history"
31
32
  ---
32
33
 
33
- # Translate your Angular website using Intlayer | Internationalization (i18n)
34
+ # Translate your Angular 19 (Webpack) website using Intlayer | Internationalization (i18n)
34
35
 
35
36
  ## Table of Contents
36
37
 
@@ -55,7 +56,7 @@ With Intlayer, you can:
55
56
  <Tab label="Code" value="code">
56
57
 
57
58
  <iframe
58
- src="https://ide.intlayer.org/aymericzip/intlayer-angular-template?file=intlayer.config.ts"
59
+ src="https://ide.intlayer.org/aymericzip/intlayer-angular-19-template?file=intlayer.config.ts"
59
60
  className="m-auto overflow-hidden rounded-lg border-0 max-md:size-full max-md:h-[700px] md:aspect-16/9 md:w-full"
60
61
  title="Demo CodeSandbox - How to Internationalize your application using Intlayer"
61
62
  sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
@@ -66,7 +67,7 @@ With Intlayer, you can:
66
67
  <Tab label="Demo" value="demo">
67
68
 
68
69
  <iframe
69
- src="https://intlayer-angular-template.vercel.app"
70
+ src="https://intlayer-angular-19-template.vercel.app"
70
71
  className="m-auto overflow-hidden rounded-lg border-0 max-md:size-full max-md:h-[700px] md:aspect-16/9 md:w-full"
71
72
  title="Demo - intlayer-angular-template"
72
73
  sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
@@ -76,7 +77,7 @@ With Intlayer, you can:
76
77
  </Tab>
77
78
  </Tabs>
78
79
 
79
- See [Application Template](https://github.com/aymericzip/intlayer-angular-template) on GitHub.
80
+ See [Application Template](https://github.com/aymericzip/intlayer-angular-19-template) on GitHub.
80
81
 
81
82
  ### Step 1: Install Dependencies
82
83
 
@@ -0,0 +1,412 @@
1
+ ---
2
+ createdAt: 2025-04-18
3
+ updatedAt: 2026-05-31
4
+ title: Angular i18n - Complete guide to translate an Angular 21 app
5
+ description: Optimized solution for bundle size, SEO, performances & maintainability. Make your Angular 21 application multilingual in 2026, LLM translation, Agent Skills & MCP.
6
+ keywords:
7
+ - Internationalization
8
+ - Documentation
9
+ - Intlayer
10
+ - Angular
11
+ - JavaScript
12
+ slugs:
13
+ - doc
14
+ - environment
15
+ - angular
16
+ applicationTemplate: https://github.com/aymericzip/intlayer-angular-21-template
17
+ applicationShowcase: https://intlayer-angular-21-template.vercel.app/
18
+ history:
19
+ - version: 8.9.0
20
+ date: 2026-05-04
21
+ changes: "Update Solid useIntlayer API usage to direct property access"
22
+ - version: 8.0.0
23
+ date: 2026-01-26
24
+ changes: "Release stable version"
25
+ - version: 8.0.0
26
+ date: 2025-12-30
27
+ changes: "Add init command"
28
+ - version: 5.5.10
29
+ date: 2025-06-29
30
+ changes: "Initial history"
31
+ ---
32
+
33
+ # Translate your Angular 21 (Vite) website using Intlayer | Internationalization (i18n)
34
+
35
+ ## Table of Contents
36
+
37
+ <TOC/>
38
+
39
+ ## What is Intlayer?
40
+
41
+ **Intlayer** is an innovative, open-source internationalization (i18n) library designed to simplify multilingual support in modern web applications.
42
+
43
+ With Intlayer, you can:
44
+
45
+ - **Easily manage translations** using declarative dictionaries at the component level.
46
+ - **Dynamically localize metadata**, routes, and content.
47
+ - **Ensure TypeScript support** with autogenerated types, improving autocompletion and error detection.
48
+ - **Benefit from advanced features**, like dynamic locale detection and switching.
49
+
50
+ ---
51
+
52
+ ## Step-by-Step Guide to Set Up Intlayer in an Angular Application
53
+
54
+ <Tabs defaultTab="code">
55
+ <Tab label="Code" value="code">
56
+
57
+ <iframe
58
+ src="https://ide.intlayer.org/aymericzip/intlayer-angular-21-template?file=intlayer.config.ts"
59
+ className="m-auto overflow-hidden rounded-lg border-0 max-md:size-full max-md:h-[700px] md:aspect-16/9 md:w-full"
60
+ title="Demo CodeSandbox - How to Internationalize your application using Intlayer"
61
+ sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
62
+ loading="lazy"
63
+ />
64
+
65
+ </Tab>
66
+ <Tab label="Demo" value="demo">
67
+
68
+ <iframe
69
+ src="https://intlayer-angular-21-template.vercel.app/"
70
+ className="m-auto overflow-hidden rounded-lg border-0 max-md:size-full max-md:h-[700px] md:aspect-16/9 md:w-full"
71
+ title="Demo - intlayer-angular-template"
72
+ sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
73
+ loading="lazy"
74
+ />
75
+
76
+ </Tab>
77
+ </Tabs>
78
+
79
+ See [Application Template](https://github.com/aymericzip/intlayer-angular-21-template) on GitHub.
80
+
81
+ ### Step 1: Install Dependencies
82
+
83
+ Install the necessary packages using npm:
84
+
85
+ ```bash packageManager="npm"
86
+ npm install intlayer angular-intlayer
87
+ npm install @angular-builders/custom-esbuild --save-dev
88
+ npx intlayer init
89
+ ```
90
+
91
+ ```bash packageManager="pnpm"
92
+ pnpm add intlayer angular-intlayer
93
+ pnpm add @angular-builders/custom-esbuild --save-dev
94
+ pnpm intlayer init
95
+ ```
96
+
97
+ ```bash packageManager="yarn"
98
+ yarn add intlayer angular-intlayer
99
+ yarn add @angular-builders/custom-esbuild --save-dev
100
+ yarn intlayer init
101
+ ```
102
+
103
+ ```bash packageManager="bun"
104
+ bun add intlayer angular-intlayer
105
+ bun add @angular-builders/custom-esbuild --dev
106
+ bun x intlayer init
107
+ ```
108
+
109
+ - **intlayer**
110
+
111
+ The core package that provides internationalization tools for configuration management, translation, [content declaration](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/dictionary/content_file.md), transpilation, and [CLI commands](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/cli/index.md).
112
+
113
+ - **angular-intlayer**
114
+ The package that integrates Intlayer with Angular application. It provides context providers and hooks for Angular internationalization.
115
+
116
+ - **@angular-builders/custom-esbuild**
117
+ Required to customize the esbuild configuration of Angular CLI.
118
+
119
+ ### Step 2: Configuration of your project
120
+
121
+ Create a config file to configure the languages of your application:
122
+
123
+ ```typescript fileName="intlayer.config.ts" codeFormat={["typescript", "esm", "commonjs"]}
124
+ import { Locales, type IntlayerConfig } from "intlayer";
125
+
126
+ const config: IntlayerConfig = {
127
+ internationalization: {
128
+ locales: [
129
+ Locales.ENGLISH,
130
+ Locales.FRENCH,
131
+ Locales.SPANISH,
132
+ // Your other locales
133
+ ],
134
+ defaultLocale: Locales.ENGLISH,
135
+ },
136
+ };
137
+
138
+ export default config;
139
+ ```
140
+
141
+ > Through this configuration file, you can set up localized URLs, middleware redirection, cookie names, the location and extension of your content declarations, disable Intlayer logs in the console, and more. For a complete list of available parameters, refer to the [configuration documentation](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/configuration.md).
142
+
143
+ ### Step 3: Integrate Intlayer in Your Angular Configuration
144
+
145
+ To integrate Intlayer with the Angular CLI, you need to use a custom builder. This guide assumes you are using Vite/esbuild (default for Angular 21 projects).
146
+
147
+ First, modify your `angular.json` to use the custom esbuild builder. Update the `build` and `serve` configurations:
148
+
149
+ ```json5 fileName="angular.json"
150
+ {
151
+ "projects": {
152
+ "your-app-name": {
153
+ "architect": {
154
+ "build": {
155
+ "builder": "@angular-builders/custom-esbuild:application", // replace "@angular/build:application"
156
+ "options": {
157
+ "define": {
158
+ "process.env": "{}",
159
+ },
160
+ "plugins": ["./esbuild.plugins.ts"],
161
+ "browser": "src/main.ts",
162
+ // ...
163
+ },
164
+ },
165
+ "serve": {
166
+ "builder": "@angular-builders/custom-esbuild:dev-server", // replace "@angular/build:dev-server"
167
+ "options": {
168
+ "prebundle": {
169
+ "exclude": [
170
+ "intlayer",
171
+ "angular-intlayer",
172
+ "@intlayer/config/built",
173
+ "@intlayer/core"
174
+ ]
175
+ },
176
+ },
177
+ },
178
+ },
179
+ },
180
+ }
181
+ ```
182
+
183
+ > Make sure to replace `your-app-name` with the actual name of your project in `angular.json`.
184
+
185
+ Next, create a `esbuild.plugins.ts` file at the root of your project:
186
+
187
+ ```typescript fileName="esbuild.plugins.ts"
188
+ import { intlayerEsbuildPlugin } from "angular-intlayer/esbuild";
189
+
190
+ export default [intlayerEsbuildPlugin()];
191
+ ```
192
+
193
+ > The `intlayerEsbuildPlugin` function configures esbuild with Intlayer. It injects the plugin to handle content declaration files and sets up configurations for optimal performance.
194
+
195
+ > **NX users**: NX's Angular builders load plugin files via Node's native ESM resolution and do not compile TypeScript plugin files on the fly. Use a `.mjs` file instead and update the `plugins` reference in `angular.json` accordingly:
196
+ >
197
+ > ```javascript fileName="esbuild.plugins.mjs"
198
+ > import { intlayerEsbuildPlugin } from "angular-intlayer/esbuild";
199
+ >
200
+ > export default [intlayerEsbuildPlugin()];
201
+ > ```
202
+ >
203
+ > Then in `angular.json` point to `"./esbuild.plugins.mjs"` instead of `"./esbuild.plugins.ts"`.
204
+
205
+ ### Step 4: Declare Your Content
206
+
207
+ Create and manage your content declarations to store translations:
208
+
209
+ ```tsx fileName="src/app/app.content.ts" contentDeclarationFormat=["typescript", "esm", "cjs"]
210
+ import { t, type Dictionary } from "intlayer";
211
+
212
+ const appContent = {
213
+ key: "app",
214
+ content: {
215
+ title: t({
216
+ en: "Hello",
217
+ fr: "Bonjour",
218
+ es: "Hola",
219
+ }),
220
+ congratulations: t({
221
+ en: "Congratulations! Your app is running. 🎉",
222
+ fr: "Félicitations! Votre application est en cours d'exécution. 🎉",
223
+ es: "¡Felicidades! Tu aplicación está en ejecución. 🎉",
224
+ }),
225
+ exploreDocs: t({
226
+ en: "Explore the Docs",
227
+ fr: "Explorer les Docs",
228
+ es: "Explorar los Docs",
229
+ }),
230
+ learnWithTutorials: t({
231
+ en: "Learn with Tutorials",
232
+ fr: "Apprendre avec les Tutoriels",
233
+ es: "Aprender con los Tutorios",
234
+ }),
235
+ cliDocs: "CLI Docs",
236
+ angularLanguageService: t({
237
+ en: "Angular Language Service",
238
+ fr: "Service de Langage Angular",
239
+ es: "Servicio de Lenguaje Angular",
240
+ }),
241
+ angularDevTools: "Angular DevTools",
242
+ github: "Github",
243
+ twitter: "Twitter",
244
+ youtube: "Youtube",
245
+ },
246
+ } satisfies Dictionary;
247
+
248
+ export default appContent;
249
+ ```
250
+
251
+ > Your content declarations can be defined anywhere in your application as soon they are included into the `contentDir` directory (by default, `./src`). And match the content declaration file extension (by default, `.content.{json,ts,tsx,js,jsx,mjs,cjs}`).
252
+
253
+ > For more details, refer to the [content declaration documentation](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/dictionary/content_file.md).
254
+
255
+ ### Step 5: Utilize Intlayer in Your Code
256
+
257
+ To utilize Intlayer's internationalization features throughout your Angular application, you need to provide Intlayer in your application configuration.
258
+
259
+ ```typescript fileName="src/app/app.config.ts"
260
+ import { ApplicationConfig } from "@angular/core";
261
+ import { provideRouter } from "@angular/router";
262
+ import { provideIntlayer } from "angular-intlayer";
263
+ import { routes } from "./app.routes";
264
+
265
+ export const appConfig: ApplicationConfig = {
266
+ providers: [
267
+ provideRouter(routes),
268
+ provideIntlayer(), // Add the Intlayer provider here
269
+ ],
270
+ };
271
+ ```
272
+
273
+ Then, you can use the `useIntlayer` function within any component.
274
+
275
+ ```typescript fileName="src/app/app.component.ts"
276
+ import { Component } from "@angular/core";
277
+ import { RouterOutlet } from "@angular/router";
278
+ import { useIntlayer } from "angular-intlayer";
279
+
280
+ @Component({
281
+ selector: "app-root",
282
+ standalone: true,
283
+ imports: [RouterOutlet],
284
+ templateUrl: "./app.component.html",
285
+ styleUrl: "./app.component.css",
286
+ })
287
+ export class AppComponent {
288
+ content = useIntlayer("app");
289
+ }
290
+ ```
291
+
292
+ And in your template:
293
+
294
+ ```html fileName="src/app/app.component.html"
295
+ <div class="content">
296
+ <h1>{{ content().title }}</h1>
297
+ <p>{{ content().congratulations }}</p>
298
+ </div>
299
+ ```
300
+
301
+ Intlayer content is returned as a `Signal`, so you access the values by calling the signal: `content().title`.
302
+
303
+ ### (Optional) Step 6: Change the language of your content
304
+
305
+ To change the language of your content, you can use the `setLocale` function provided by the `useLocale` function. This allows you to set the locale of the application and update the content accordingly.
306
+
307
+ Create a component to switch between languages:
308
+
309
+ ```typescript fileName="src/app/locale-switcher.component.ts"
310
+ import { Component } from "@angular/core";
311
+ import { CommonModule } from "@angular/common";
312
+ import { useLocale } from "angular-intlayer";
313
+
314
+ @Component({
315
+ selector: "app-locale-switcher",
316
+ standalone: true,
317
+ imports: [CommonModule],
318
+ template: `
319
+ <div class="locale-switcher">
320
+ <select
321
+ [value]="locale()"
322
+ (change)="setLocale($any($event.target).value)"
323
+ >
324
+ @for (loc of availableLocales; track loc) {
325
+ <option [value]="loc">{{ loc }}</option>
326
+ }
327
+ </select>
328
+ </div>
329
+ `,
330
+ })
331
+ export class LocaleSwitcherComponent {
332
+ localeCtx = useLocale();
333
+
334
+ locale = this.localeCtx.locale;
335
+ availableLocales = this.localeCtx.availableLocales;
336
+ setLocale = this.localeCtx.setLocale;
337
+ }
338
+ ```
339
+
340
+ Then, use this component in your `app.component.ts`:
341
+
342
+ ```typescript fileName="src/app/app.component.ts"
343
+ import { Component } from "@angular/core";
344
+ import { RouterOutlet } from "@angular/router";
345
+ import { useIntlayer } from "angular-intlayer";
346
+ import { LocaleSwitcherComponent } from "./locale-switcher.component";
347
+
348
+ @Component({
349
+ selector: "app-root",
350
+ standalone: true,
351
+ imports: [RouterOutlet, LocaleSwitcherComponent],
352
+ templateUrl: "./app.component.html",
353
+ styleUrl: "./app.component.css",
354
+ })
355
+ export class AppComponent {
356
+ content = useIntlayer("app");
357
+ }
358
+ ```
359
+
360
+ ### Configure TypeScript
361
+
362
+ Intlayer uses module augmentation to get benefits of TypeScript and make your codebase stronger.
363
+
364
+ ![Autocompletion](https://github.com/aymericzip/intlayer/blob/main/docs/assets/autocompletion.png?raw=true)
365
+
366
+ ![Translation error](https://github.com/aymericzip/intlayer/blob/main/docs/assets/translation_error.png?raw=true)
367
+
368
+ Ensure your TypeScript configuration includes the autogenerated types.
369
+
370
+ ```json5 fileName="tsconfig.json"
371
+ {
372
+ // ... Your existing TypeScript configurations
373
+ "include": [
374
+ // ... Your existing TypeScript configurations
375
+ ".intlayer/**/*.ts", // Include the auto-generated types
376
+ ],
377
+ }
378
+ ```
379
+
380
+ ### Git Configuration
381
+
382
+ It is recommended to ignore the files generated by Intlayer. This allows you to avoid committing them to your Git repository.
383
+
384
+ To do this, you can add the following instructions to your `.gitignore` file:
385
+
386
+ ```bash
387
+ # Ignore the files generated by Intlayer
388
+ .intlayer
389
+ ```
390
+
391
+ ### VS Code Extension
392
+
393
+ To improve your development experience with Intlayer, you can install the official **Intlayer VS Code Extension**.
394
+
395
+ [Install from the VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=intlayer.intlayer-vs-code-extension)
396
+
397
+ This extension provides:
398
+
399
+ - **Autocompletion** for translation keys.
400
+ - **Real-time error detection** for missing translations.
401
+ - **Inline previews** of translated content.
402
+ - **Quick actions** to easily create and update translations.
403
+
404
+ For more details on how to use the extension, refer to the [Intlayer VS Code Extension documentation](https://intlayer.org/doc/vs-code-extension).
405
+
406
+ ---
407
+
408
+ ### Go Further
409
+
410
+ To go further, you can implement the [visual editor](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_visual_editor.md) or externalize your content using the [CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_CMS.md).
411
+
412
+ ---