@intlayer/docs 8.0.0 → 8.0.1-canary.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/dist/cjs/generated/docs.entry.cjs +160 -0
  2. package/dist/cjs/generated/docs.entry.cjs.map +1 -1
  3. package/dist/esm/generated/docs.entry.mjs +160 -0
  4. package/dist/esm/generated/docs.entry.mjs.map +1 -1
  5. package/dist/types/generated/docs.entry.d.ts +8 -0
  6. package/dist/types/generated/docs.entry.d.ts.map +1 -1
  7. package/docs/ar/intlayer_with_adonisjs.md +394 -0
  8. package/docs/ar/intlayer_with_hono.md +223 -0
  9. package/docs/ar/intlayer_with_vite+preact.md +317 -675
  10. package/docs/ar/packages/adonis-intlayer/exports.md +50 -0
  11. package/docs/ar/packages/adonis-intlayer/intlayer.md +54 -0
  12. package/docs/ar/packages/adonis-intlayer/t.md +149 -0
  13. package/docs/ar/packages/hono-intlayer/exports.md +59 -0
  14. package/docs/ar/packages/hono-intlayer/intlayer.md +60 -0
  15. package/docs/ar/packages/hono-intlayer/t.md +268 -0
  16. package/docs/de/intlayer_with_adonisjs.md +392 -0
  17. package/docs/de/intlayer_with_hono.md +418 -0
  18. package/docs/de/intlayer_with_vite+preact.md +272 -632
  19. package/docs/de/packages/adonis-intlayer/exports.md +50 -0
  20. package/docs/de/packages/adonis-intlayer/intlayer.md +54 -0
  21. package/docs/de/packages/adonis-intlayer/t.md +149 -0
  22. package/docs/de/packages/hono-intlayer/exports.md +59 -0
  23. package/docs/de/packages/hono-intlayer/intlayer.md +59 -0
  24. package/docs/de/packages/hono-intlayer/t.md +316 -0
  25. package/docs/en/index.md +8 -0
  26. package/docs/en/intlayer_with_adonisjs.md +388 -0
  27. package/docs/en/intlayer_with_hono.md +418 -0
  28. package/docs/en/intlayer_with_vite+preact.md +171 -556
  29. package/docs/en/introduction.md +1 -0
  30. package/docs/en/packages/adonis-intlayer/exports.md +50 -0
  31. package/docs/en/packages/adonis-intlayer/intlayer.md +54 -0
  32. package/docs/en/packages/adonis-intlayer/t.md +149 -0
  33. package/docs/en/packages/hono-intlayer/exports.md +59 -0
  34. package/docs/en/packages/hono-intlayer/intlayer.md +59 -0
  35. package/docs/en/packages/hono-intlayer/t.md +316 -0
  36. package/docs/en-GB/intlayer_with_adonisjs.md +394 -0
  37. package/docs/en-GB/intlayer_with_hono.md +418 -0
  38. package/docs/en-GB/intlayer_with_vite+preact.md +236 -583
  39. package/docs/en-GB/packages/adonis-intlayer/exports.md +50 -0
  40. package/docs/en-GB/packages/adonis-intlayer/intlayer.md +54 -0
  41. package/docs/en-GB/packages/adonis-intlayer/t.md +149 -0
  42. package/docs/en-GB/packages/hono-intlayer/exports.md +59 -0
  43. package/docs/en-GB/packages/hono-intlayer/intlayer.md +59 -0
  44. package/docs/en-GB/packages/hono-intlayer/t.md +316 -0
  45. package/docs/es/intlayer_with_adonisjs.md +388 -0
  46. package/docs/es/intlayer_with_hono.md +418 -0
  47. package/docs/es/intlayer_with_vite+preact.md +286 -650
  48. package/docs/es/packages/adonis-intlayer/exports.md +50 -0
  49. package/docs/es/packages/adonis-intlayer/intlayer.md +54 -0
  50. package/docs/es/packages/adonis-intlayer/t.md +149 -0
  51. package/docs/es/packages/hono-intlayer/exports.md +59 -0
  52. package/docs/es/packages/hono-intlayer/intlayer.md +59 -0
  53. package/docs/es/packages/hono-intlayer/t.md +316 -0
  54. package/docs/fr/intlayer_with_adonisjs.md +388 -0
  55. package/docs/fr/intlayer_with_hono.md +418 -0
  56. package/docs/fr/intlayer_with_vite+preact.md +274 -614
  57. package/docs/fr/packages/adonis-intlayer/exports.md +50 -0
  58. package/docs/fr/packages/adonis-intlayer/intlayer.md +54 -0
  59. package/docs/fr/packages/adonis-intlayer/t.md +149 -0
  60. package/docs/fr/packages/hono-intlayer/exports.md +59 -0
  61. package/docs/fr/packages/hono-intlayer/intlayer.md +59 -0
  62. package/docs/fr/packages/hono-intlayer/t.md +316 -0
  63. package/docs/hi/intlayer_with_adonisjs.md +394 -0
  64. package/docs/hi/intlayer_with_hono.md +227 -0
  65. package/docs/hi/intlayer_with_vite+preact.md +304 -680
  66. package/docs/hi/packages/adonis-intlayer/exports.md +50 -0
  67. package/docs/hi/packages/adonis-intlayer/intlayer.md +54 -0
  68. package/docs/hi/packages/adonis-intlayer/t.md +149 -0
  69. package/docs/hi/packages/hono-intlayer/exports.md +59 -0
  70. package/docs/hi/packages/hono-intlayer/intlayer.md +60 -0
  71. package/docs/hi/packages/hono-intlayer/t.md +268 -0
  72. package/docs/id/intlayer_with_adonisjs.md +394 -0
  73. package/docs/id/intlayer_with_hono.md +227 -0
  74. package/docs/id/intlayer_with_vite+preact.md +297 -697
  75. package/docs/id/packages/adonis-intlayer/exports.md +50 -0
  76. package/docs/id/packages/adonis-intlayer/intlayer.md +54 -0
  77. package/docs/id/packages/adonis-intlayer/t.md +149 -0
  78. package/docs/id/packages/hono-intlayer/exports.md +59 -0
  79. package/docs/id/packages/hono-intlayer/intlayer.md +60 -0
  80. package/docs/id/packages/hono-intlayer/t.md +268 -0
  81. package/docs/it/intlayer_with_adonisjs.md +394 -0
  82. package/docs/it/intlayer_with_hono.md +227 -0
  83. package/docs/it/intlayer_with_vite+preact.md +290 -659
  84. package/docs/it/packages/adonis-intlayer/exports.md +50 -0
  85. package/docs/it/packages/adonis-intlayer/intlayer.md +54 -0
  86. package/docs/it/packages/adonis-intlayer/t.md +149 -0
  87. package/docs/it/packages/hono-intlayer/exports.md +59 -0
  88. package/docs/it/packages/hono-intlayer/intlayer.md +60 -0
  89. package/docs/it/packages/hono-intlayer/t.md +268 -0
  90. package/docs/ja/intlayer_with_adonisjs.md +394 -0
  91. package/docs/ja/intlayer_with_hono.md +227 -0
  92. package/docs/ja/intlayer_with_vite+preact.md +307 -662
  93. package/docs/ja/packages/adonis-intlayer/exports.md +50 -0
  94. package/docs/ja/packages/adonis-intlayer/intlayer.md +54 -0
  95. package/docs/ja/packages/adonis-intlayer/t.md +149 -0
  96. package/docs/ja/packages/hono-intlayer/exports.md +59 -0
  97. package/docs/ja/packages/hono-intlayer/intlayer.md +60 -0
  98. package/docs/ja/packages/hono-intlayer/t.md +268 -0
  99. package/docs/ko/intlayer_with_adonisjs.md +394 -0
  100. package/docs/ko/intlayer_with_hono.md +227 -0
  101. package/docs/ko/intlayer_with_vite+preact.md +303 -703
  102. package/docs/ko/packages/adonis-intlayer/exports.md +50 -0
  103. package/docs/ko/packages/adonis-intlayer/intlayer.md +54 -0
  104. package/docs/ko/packages/adonis-intlayer/t.md +149 -0
  105. package/docs/ko/packages/hono-intlayer/exports.md +59 -0
  106. package/docs/ko/packages/hono-intlayer/intlayer.md +60 -0
  107. package/docs/ko/packages/hono-intlayer/t.md +268 -0
  108. package/docs/pl/intlayer_with_adonisjs.md +394 -0
  109. package/docs/pl/intlayer_with_hono.md +227 -0
  110. package/docs/pl/intlayer_with_vite+preact.md +289 -690
  111. package/docs/pl/packages/adonis-intlayer/exports.md +50 -0
  112. package/docs/pl/packages/adonis-intlayer/intlayer.md +54 -0
  113. package/docs/pl/packages/adonis-intlayer/t.md +149 -0
  114. package/docs/pl/packages/hono-intlayer/exports.md +59 -0
  115. package/docs/pl/packages/hono-intlayer/intlayer.md +60 -0
  116. package/docs/pl/packages/hono-intlayer/t.md +268 -0
  117. package/docs/pt/intlayer_with_adonisjs.md +394 -0
  118. package/docs/pt/intlayer_with_hono.md +227 -0
  119. package/docs/pt/intlayer_with_vite+preact.md +275 -637
  120. package/docs/pt/packages/adonis-intlayer/exports.md +50 -0
  121. package/docs/pt/packages/adonis-intlayer/intlayer.md +54 -0
  122. package/docs/pt/packages/adonis-intlayer/t.md +149 -0
  123. package/docs/pt/packages/hono-intlayer/exports.md +59 -0
  124. package/docs/pt/packages/hono-intlayer/intlayer.md +60 -0
  125. package/docs/pt/packages/hono-intlayer/t.md +268 -0
  126. package/docs/ru/intlayer_with_adonisjs.md +393 -0
  127. package/docs/ru/intlayer_with_hono.md +223 -0
  128. package/docs/ru/intlayer_with_vite+preact.md +319 -683
  129. package/docs/ru/packages/adonis-intlayer/exports.md +50 -0
  130. package/docs/ru/packages/adonis-intlayer/intlayer.md +54 -0
  131. package/docs/ru/packages/adonis-intlayer/t.md +149 -0
  132. package/docs/ru/packages/hono-intlayer/exports.md +59 -0
  133. package/docs/ru/packages/hono-intlayer/intlayer.md +60 -0
  134. package/docs/ru/packages/hono-intlayer/t.md +268 -0
  135. package/docs/tr/intlayer_with_adonisjs.md +394 -0
  136. package/docs/tr/intlayer_with_hono.md +227 -0
  137. package/docs/tr/intlayer_with_vite+preact.md +332 -665
  138. package/docs/tr/packages/adonis-intlayer/exports.md +50 -0
  139. package/docs/tr/packages/adonis-intlayer/intlayer.md +54 -0
  140. package/docs/tr/packages/adonis-intlayer/t.md +149 -0
  141. package/docs/tr/packages/hono-intlayer/exports.md +59 -0
  142. package/docs/tr/packages/hono-intlayer/intlayer.md +60 -0
  143. package/docs/tr/packages/hono-intlayer/t.md +268 -0
  144. package/docs/uk/intlayer_with_adonisjs.md +394 -0
  145. package/docs/uk/intlayer_with_hono.md +227 -0
  146. package/docs/uk/intlayer_with_vite+preact.md +228 -626
  147. package/docs/uk/packages/adonis-intlayer/exports.md +50 -0
  148. package/docs/uk/packages/adonis-intlayer/intlayer.md +54 -0
  149. package/docs/uk/packages/adonis-intlayer/t.md +149 -0
  150. package/docs/uk/packages/hono-intlayer/exports.md +59 -0
  151. package/docs/uk/packages/hono-intlayer/intlayer.md +60 -0
  152. package/docs/uk/packages/hono-intlayer/t.md +268 -0
  153. package/docs/vi/intlayer_with_adonisjs.md +394 -0
  154. package/docs/vi/intlayer_with_hono.md +227 -0
  155. package/docs/vi/intlayer_with_vite+preact.md +294 -679
  156. package/docs/vi/packages/adonis-intlayer/exports.md +50 -0
  157. package/docs/vi/packages/adonis-intlayer/intlayer.md +54 -0
  158. package/docs/vi/packages/adonis-intlayer/t.md +149 -0
  159. package/docs/vi/packages/hono-intlayer/exports.md +59 -0
  160. package/docs/vi/packages/hono-intlayer/intlayer.md +60 -0
  161. package/docs/vi/packages/hono-intlayer/t.md +268 -0
  162. package/docs/zh/intlayer_with_adonisjs.md +393 -0
  163. package/docs/zh/intlayer_with_hono.md +418 -0
  164. package/docs/zh/intlayer_with_vite+preact.md +338 -743
  165. package/docs/zh/packages/adonis-intlayer/exports.md +50 -0
  166. package/docs/zh/packages/adonis-intlayer/intlayer.md +54 -0
  167. package/docs/zh/packages/adonis-intlayer/t.md +149 -0
  168. package/docs/zh/packages/hono-intlayer/exports.md +59 -0
  169. package/docs/zh/packages/hono-intlayer/intlayer.md +60 -0
  170. package/docs/zh/packages/hono-intlayer/t.md +294 -0
  171. package/package.json +6 -6
  172. package/src/generated/docs.entry.ts +160 -0
@@ -119,6 +119,10 @@ const config: IntlayerConfig = {
119
119
  ],
120
120
  defaultLocale: Locales.ENGLISH,
121
121
  },
122
+ routing: {
123
+ mode: "prefix-no-default", // Default: prefix all locales except the default locale
124
+ storage: ["cookie", "header"], // Default: store locale in cookie and detect from header
125
+ },
122
126
  };
123
127
 
124
128
  export default config;
@@ -138,6 +142,10 @@ const config = {
138
142
  ],
139
143
  defaultLocale: Locales.ENGLISH,
140
144
  },
145
+ routing: {
146
+ mode: "prefix-no-default", // Default: prefix all locales except the default locale
147
+ storage: ["cookie", "header"], // Default: store locale in cookie and detect from header
148
+ },
141
149
  };
142
150
 
143
151
  export default config;
@@ -157,12 +165,16 @@ const config = {
157
165
  ],
158
166
  defaultLocale: Locales.ENGLISH,
159
167
  },
168
+ routing: {
169
+ mode: "prefix-no-default", // Default: prefix all locales except the default locale
170
+ storage: ["cookie", "header"], // Default: store locale in cookie and detect from header
171
+ },
160
172
  };
161
173
 
162
174
  module.exports = config;
163
175
  ```
164
176
 
165
- > Through this configuration file, you can set up localised 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-GB/configuration.md).
177
+ > Through this configuration file, you can set up localised URLs, routing modes, storage options, 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-GB/configuration.md).
166
178
 
167
179
  ### Step 3: Integrate Intlayer in Your Vite Configuration
168
180
 
@@ -241,7 +253,7 @@ const appContent = {
241
253
  ),
242
254
  fr: (
243
255
  <>
244
- Éditez <code>src/app.tsx</code> et enregistrez pour tester HMR
256
+ Éditez <code>src/app.tsx</code> and enregistrez pour tester HMR
245
257
  </>
246
258
  ),
247
259
  es: (
@@ -296,7 +308,6 @@ const appContent = {
296
308
  }),
297
309
 
298
310
  readTheDocs: t({
299
- "en-GB": "Click on the Vite and Preact logos to learn more",
300
311
  en: "Click on the Vite and Preact logos to learn more",
301
312
  fr: "Cliquez sur les logos Vite et Preact pour en savoir plus",
302
313
  es: "Haga clic en los logotipos de Vite y Preact para obtener más información",
@@ -316,13 +327,11 @@ const appContent = {
316
327
  key: "app",
317
328
  content: {
318
329
  viteLogo: t({
319
- "en-GB": "Vite logo",
320
330
  en: "Vite logo",
321
331
  fr: "Logo Vite",
322
332
  es: "Logo Vite",
323
333
  }),
324
334
  preactLogo: t({
325
- "en-GB": "Preact logo",
326
335
  en: "Preact logo",
327
336
  fr: "Logo Preact",
328
337
  es: "Logo Preact",
@@ -331,24 +340,21 @@ const appContent = {
331
340
  title: "Vite + Preact",
332
341
 
333
342
  count: t({
334
- "en-GB": "count is ",
335
343
  en: "count is ",
336
344
  fr: "le compte est ",
337
345
  es: "el recuento es ",
338
346
  }),
339
347
 
340
348
  edit: t({
341
- "en-GB": "Edit src/app.tsx and save to test HMR",
342
349
  en: "Edit src/app.tsx and save to test HMR",
343
350
  fr: "Éditez src/app.tsx et enregistrez pour tester HMR",
344
351
  es: "Edita src/app.tsx y guarda para probar HMR",
345
352
  }),
346
353
 
347
354
  readTheDocs: t({
348
- "en-GB": "Click on the Vite and Preact logos to learn more",
349
355
  en: "Click on the Vite and Preact logos to learn more",
350
356
  fr: "Cliquez sur les logos Vite et Preact pour en savoir plus",
351
- es: "Haga clic en los logotipos de Vite y Preact para obtener más información",
357
+ es: "Haga clic en los logotipos de Vite et Preact pour obtenir plus d'informations",
352
358
  }),
353
359
  },
354
360
  };
@@ -364,7 +370,6 @@ module.exports = appContent;
364
370
  "viteLogo": {
365
371
  "nodeType": "translation",
366
372
  "translation": {
367
- "en-GB": "Vite logo",
368
373
  "en": "Vite logo",
369
374
  "fr": "Logo Vite",
370
375
  "es": "Logo Vite"
@@ -373,7 +378,6 @@ module.exports = appContent;
373
378
  "preactLogo": {
374
379
  "nodeType": "translation",
375
380
  "translation": {
376
- "en-GB": "Preact logo",
377
381
  "en": "Preact logo",
378
382
  "fr": "Logo Preact",
379
383
  "es": "Logo Preact"
@@ -382,7 +386,6 @@ module.exports = appContent;
382
386
  "title": {
383
387
  "nodeType": "translation",
384
388
  "translation": {
385
- "en-GB": "Vite + Preact",
386
389
  "en": "Vite + Preact",
387
390
  "fr": "Vite + Preact",
388
391
  "es": "Vite + Preact"
@@ -391,7 +394,6 @@ module.exports = appContent;
391
394
  "count": {
392
395
  "nodeType": "translation",
393
396
  "translation": {
394
- "en-GB": "count is ",
395
397
  "en": "count is ",
396
398
  "fr": "le compte est ",
397
399
  "es": "el recuento es "
@@ -400,7 +402,6 @@ module.exports = appContent;
400
402
  "edit": {
401
403
  "nodeType": "translation",
402
404
  "translation": {
403
- "en-GB": "Edit src/app.tsx and save to test HMR",
404
405
  "en": "Edit src/app.tsx and save to test HMR",
405
406
  "fr": "Éditez src/app.tsx et enregistrez pour tester HMR",
406
407
  "es": "Edita src/app.tsx y guarda para probar HMR"
@@ -409,7 +410,6 @@ module.exports = appContent;
409
410
  "readTheDocs": {
410
411
  "nodeType": "translation",
411
412
  "translation": {
412
- "en-GB": "Click on the Vite and Preact logos to learn more",
413
413
  "en": "Click on the Vite and Preact logos to learn more",
414
414
  "fr": "Cliquez sur les logos Vite et Preact pour en savoir plus",
415
415
  "es": "Haga clic en los logotipos de Vite y Preact para obtener más información"
@@ -463,6 +463,12 @@ const AppContent: FunctionalComponent = () => {
463
463
  </button>
464
464
  <p>{content.edit}</p>
465
465
  </div>
466
+ {/* Markdown content */}
467
+ <div>{content.myMarkdownContent}</div>
468
+
469
+ {/* HTML content */}
470
+ <div>{content.myHtmlContent}</div>
471
+
466
472
  <p class="read-the-docs">{content.readTheDocs}</p>
467
473
  </>
468
474
  );
@@ -641,7 +647,7 @@ module.exports = LocaleSwitcher;
641
647
 
642
648
  ### (Optional) Step 7: Add localised Routing to your application
643
649
 
644
- The purpose of this step is to create unique routes for each language. This is useful for SEO and SEO-friendly URLs.
650
+ The purpose of this step is to make unique routes for each language. This is useful for SEO and SEO-friendly URLs.
645
651
  Example:
646
652
 
647
653
  ```plaintext
@@ -650,141 +656,15 @@ Example:
650
656
  - https://example.com/fr/about
651
657
  ```
652
658
 
653
- > By default, the routes are not prefixed for the default locale. If you want to prefix the default locale, you can set the `middleware.prefixDefault` option to `true` in your configuration. See the [configuration documentation](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/configuration.md) for more information.
659
+ > By default, the routes are not prefixed for the default locale. If you want to prefix the default locale, you can set the `routing.mode` option to `"prefix-all"` in your configuration. See the [configuration documentation](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/configuration.md) for more information.
654
660
 
655
661
  To add localised routing to your application, you can create a `LocaleRouter` component that wraps your application's routes and handles locale-based routing. Here is an example using [preact-iso](https://github.com/preactjs/preact-iso):
656
662
 
657
- First, install `preact-iso`:
658
-
659
- ```bash packageManager="npm"
660
- npm install preact-iso
661
- npx intlayer init
662
- ```
663
-
664
- ```bash packageManager="pnpm"
665
- pnpm add preact-iso
666
- pnpm intlayer init
667
- ```
668
-
669
- ```bash packageManager="yarn"
670
- yarn add preact-iso
671
- ```
672
-
673
663
  ```tsx fileName="src/components/LocaleRouter.tsx" codeFormat="typescript"
674
- import { type Locales, configuration, getPathWithoutLocale } from "intlayer";
675
- import { ComponentChildren, FunctionalComponent } from "preact";
664
+ import { localeMap } from "intlayer";
676
665
  import { IntlayerProvider } from "preact-intlayer";
677
- import { LocationProvider, useLocation } from "preact-iso";
678
- import { useEffect } from "preact/hooks";
679
-
680
- const { internationalization, middleware } = configuration;
681
- const { locales, defaultLocale } = internationalization;
682
-
683
- const Navigate: FunctionalComponent<{ to: string; replace?: boolean }> = ({
684
- to,
685
- replace,
686
- }) => {
687
- const { route } = useLocation();
688
- useEffect(() => {
689
- route(to, replace);
690
- }, [to, replace, route]);
691
- return null;
692
- };
693
-
694
- /**
695
- * A component that handles localisation and wraps children with the appropriate locale context.
696
- * It manages URL-based locale detection and validation.
697
- */
698
- const AppLocalized: FunctionalComponent<{
699
- children: ComponentChildren;
700
- locale?: Locales;
701
- }> = ({ children, locale }) => {
702
- const { path: pathname, url } = useLocation();
703
-
704
- if (!url) {
705
- return null;
706
- }
707
-
708
- const search = url.substring(pathname.length);
709
-
710
- // Determine the current locale, falling back to the default if not provided
711
- const currentLocale = locale ?? defaultLocale;
712
-
713
- // Remove the locale prefix from the path to construct a base path
714
- const pathWithoutLocale = getPathWithoutLocale(
715
- pathname // Current URL path
716
- );
717
-
718
- /**
719
- * If middleware.prefixDefault is true, the default locale should always be prefixed.
720
- */
721
- if (middleware.prefixDefault) {
722
- // Validate the locale
723
- if (!locale || !locales.includes(locale)) {
724
- // Redirect to the default locale with the updated path
725
- return (
726
- <Navigate
727
- to={`/${defaultLocale}/${pathWithoutLocale}${search}`}
728
- replace // Replace the current history entry with the new one
729
- />
730
- );
731
- }
732
-
733
- // Wrap children with the IntlayerProvider and set the current locale
734
- return (
735
- <IntlayerProvider locale={currentLocale}>{children}</IntlayerProvider>
736
- );
737
- } else {
738
- /**
739
- * When middleware.prefixDefault is false, the default locale is not prefixed.
740
- * Ensure that the current locale is valid and not the default locale.
741
- */
742
- if (
743
- currentLocale.toString() !== defaultLocale.toString() &&
744
- !locales
745
- .filter(
746
- (loc) => loc.toString() !== defaultLocale.toString() // Exclude the default locale
747
- )
748
- .includes(currentLocale) // Check if the current locale is in the list of valid locales
749
- ) {
750
- // Redirect to the path without locale prefix
751
- return <Navigate to={`${pathWithoutLocale}${search}`} replace />;
752
- }
753
-
754
- // Wrap children with the IntlayerProvider and set the current locale
755
- return (
756
- <IntlayerProvider locale={currentLocale}>{children}</IntlayerProvider>
757
- );
758
- }
759
- };
760
-
761
- const RouterContent: FunctionalComponent<{
762
- children: ComponentChildren;
763
- }> = ({ children }) => {
764
- const { path } = useLocation();
765
-
766
- if (!path) {
767
- return null;
768
- }
769
-
770
- const pathLocale = path.split("/")[1] as Locales;
771
-
772
- const isLocaleRoute = locales
773
- .filter((locale) => middleware.prefixDefault || locale !== defaultLocale)
774
- .some((locale) => locale.toString() === pathLocale);
775
-
776
- if (isLocaleRoute) {
777
- return <AppLocalised locale={pathLocale}>{children}</AppLocalised>;
778
- }
779
-
780
- return (
781
- <AppLocalised
782
- locale={!middleware.prefixDefault ? defaultLocale : undefined}
783
- >
784
- {children}
785
- </AppLocalised>
786
- );
787
- };
666
+ import { LocationProvider, Router, Route } from "preact-iso";
667
+ import type { ComponentChildren, FunctionalComponent } from "preact";
788
668
 
789
669
  /**
790
670
  * A router component that sets up locale-specific routes.
@@ -794,120 +674,27 @@ export const LocaleRouter: FunctionalComponent<{
794
674
  children: ComponentChildren;
795
675
  }> = ({ children }) => (
796
676
  <LocationProvider>
797
- <RouterContent>{children}</RouterContent>
677
+ <Router>
678
+ {localeMap(({ locale, urlPrefix }) => ({ locale, urlPrefix }))
679
+ .sort((a, b) => b.urlPrefix.length - a.urlPrefix.length)
680
+ .map(({ locale, urlPrefix }) => (
681
+ <Route
682
+ key={locale}
683
+ path={`${urlPrefix}/:rest*`}
684
+ component={() => (
685
+ <IntlayerProvider locale={locale}>{children}</IntlayerProvider>
686
+ )}
687
+ />
688
+ ))}
689
+ </Router>
798
690
  </LocationProvider>
799
691
  );
800
692
  ```
801
693
 
802
694
  ```jsx fileName="src/components/LocaleRouter.jsx" codeFormat="esm"
803
- // Importing necessary dependencies and functions
804
- import { configuration, getPathWithoutLocale } from "intlayer";
695
+ import { localeMap } from "intlayer";
805
696
  import { IntlayerProvider } from "preact-intlayer";
806
- import { LocationProvider, useLocation } from "preact-iso";
807
- import { useEffect } from "preact/hooks";
808
- import { h } from "preact"; // Required for JSX
809
-
810
- // Destructuring configuration from Intlayer
811
- const { internationalization, middleware } = configuration;
812
- const { locales, defaultLocale } = internationalization;
813
-
814
- const Navigate = ({ to, replace }) => {
815
- const { route } = useLocation();
816
- useEffect(() => {
817
- route(to, replace);
818
- }, [to, replace, route]);
819
- return null;
820
- };
821
-
822
- /**
823
- * A component that handles localisation and wraps children with the appropriate locale context.
824
- * It manages URL-based locale detection and validation.
825
- */
826
- const AppLocalised = ({ children, locale }) => {
827
- const { path: pathname, url } = useLocation();
828
-
829
- if (!url) {
830
- return null;
831
- }
832
-
833
- const search = url.substring(pathname.length);
834
-
835
- // Determine the current locale, falling back to the default if not provided
836
- const currentLocale = locale ?? defaultLocale;
837
-
838
- // Remove the locale prefix from the path to construct a base path
839
- const pathWithoutLocale = getPathWithoutLocale(
840
- pathname // Current URL path
841
- );
842
-
843
- /**
844
- * If middleware.prefixDefault is true, the default locale should always be prefixed.
845
- */
846
- if (middleware.prefixDefault) {
847
- // Validate the locale
848
- if (!locale || !locales.includes(locale)) {
849
- // Redirect to the default locale with the updated path
850
- return (
851
- <Navigate
852
- to={`/${defaultLocale}/${pathWithoutLocale}${search}`}
853
- replace // Replace the current history entry with the new one
854
- />
855
- );
856
- }
857
-
858
- // Wrap children with the IntlayerProvider and set the current locale
859
- return (
860
- <IntlayerProvider locale={currentLocale}>{children}</IntlayerProvider>
861
- );
862
- } else {
863
- /**
864
- * When middleware.prefixDefault is false, the default locale is not prefixed.
865
- * Ensure that the current locale is valid and not the default locale.
866
- */
867
- if (
868
- currentLocale.toString() !== defaultLocale.toString() &&
869
- !locales
870
- .filter(
871
- (loc) => loc.toString() !== defaultLocale.toString() // Exclude the default locale
872
- )
873
- .includes(currentLocale) // Check if the current locale is in the list of valid locales
874
- ) {
875
- // Redirect to the path without locale prefix
876
- return <Navigate to={`${pathWithoutLocale}${search}`} replace />;
877
- }
878
-
879
- // Wrap children with the IntlayerProvider and set the current locale
880
- return (
881
- <IntlayerProvider locale={currentLocale}>{children}</IntlayerProvider>
882
- );
883
- }
884
- };
885
-
886
- const RouterContent = ({ children }) => {
887
- const { path } = useLocation();
888
-
889
- if (!path) {
890
- return null;
891
- }
892
-
893
- const pathLocale = path.split("/")[1];
894
-
895
- const isLocaleRoute = locales
896
- .filter((locale) => middleware.prefixDefault || locale !== defaultLocale)
897
- .some((locale) => locale.toString() === pathLocale);
898
-
899
- if (isLocaleRoute) {
900
- return <AppLocalized locale={pathLocale}>{children}</AppLocalized>;
901
- }
902
-
903
- return (
904
- <AppLocalized
905
- locale={!middleware.prefixDefault ? defaultLocale : undefined}
906
- >
907
- {children}
908
- </AppLocalized>
909
- );
910
- };
697
+ import { LocationProvider, Router, Route } from "preact-iso";
911
698
 
912
699
  /**
913
700
  * A router component that sets up locale-specific routes.
@@ -915,130 +702,50 @@ const RouterContent = ({ children }) => {
915
702
  */
916
703
  export const LocaleRouter = ({ children }) => (
917
704
  <LocationProvider>
918
- <RouterContent>{children}</RouterContent>
705
+ <Router>
706
+ {localeMap(({ locale, urlPrefix }) => ({ locale, urlPrefix }))
707
+ .sort((a, b) => b.urlPrefix.length - a.urlPrefix.length)
708
+ .map(({ locale, urlPrefix }) => (
709
+ <Route
710
+ key={locale}
711
+ path={`${urlPrefix}/:rest*`}
712
+ component={() => (
713
+ <IntlayerProvider locale={locale}>{children}</IntlayerProvider>
714
+ )}
715
+ />
716
+ ))}
717
+ </Router>
919
718
  </LocationProvider>
920
719
  );
921
720
  ```
922
721
 
923
722
  ```jsx fileName="src/components/LocaleRouter.cjsx" codeFormat="commonjs"
924
- // Importing necessary dependencies and functions
925
- const { configuration, getPathWithoutLocale } = require("intlayer");
723
+ const { localeMap } = require("intlayer");
926
724
  const { IntlayerProvider } = require("preact-intlayer");
927
- const { LocationProvider, useLocation } = require("preact-iso");
928
- const { useEffect } = require("preact/hooks");
929
- const { h } = require("preact"); // Required for JSX
930
-
931
- // Destructuring configuration from Intlayer
932
- const { internationalization, middleware } = configuration;
933
- const { locales, defaultLocale } = internationalization;
934
-
935
- const Navigate = ({ to, replace }) => {
936
- const { route } = useLocation();
937
- useEffect(() => {
938
- route(to, replace);
939
- }, [to, replace, route]);
940
- return null;
941
- };
942
-
943
- /**
944
- * A component that handles localisation and wraps children with the appropriate locale context.
945
- * It manages URL-based locale detection and validation.
946
- */
947
- const AppLocalized = ({ children, locale }) => {
948
- const { path: pathname, url } = useLocation();
949
-
950
- if (!url) {
951
- return null;
952
- }
953
-
954
- const search = url.substring(pathname.length);
955
-
956
- // Determine the current locale, falling back to the default if not provided
957
- const currentLocale = locale ?? defaultLocale;
958
-
959
- // Remove the locale prefix from the path to construct a base path
960
- const pathWithoutLocale = getPathWithoutLocale(
961
- pathname // Current URL path
962
- );
963
-
964
- /**
965
- * If middleware.prefixDefault is true, the default locale should always be prefixed.
966
- */
967
- if (middleware.prefixDefault) {
968
- // Validate the locale
969
- if (!locale || !locales.includes(locale)) {
970
- // Redirect to the default locale with the updated path
971
- return (
972
- <Navigate
973
- to={`/${defaultLocale}/${pathWithoutLocale}${search}`}
974
- replace // Replace the current history entry with the new one
975
- />
976
- );
977
- }
978
-
979
- // Wrap children with the IntlayerProvider and set the current locale
980
- return (
981
- <IntlayerProvider locale={currentLocale}>{children}</IntlayerProvider>
982
- );
983
- } else {
984
- /**
985
- * When middleware.prefixDefault is false, the default locale is not prefixed.
986
- * Ensure that the current locale is valid and not the default locale.
987
- */
988
- if (
989
- currentLocale.toString() !== defaultLocale.toString() &&
990
- !locales
991
- .filter(
992
- (loc) => loc.toString() !== defaultLocale.toString() // Exclude the default locale
993
- )
994
- .includes(currentLocale) // Check if the current locale is in the list of valid locales
995
- ) {
996
- // Redirect to the path without locale prefix
997
- return <Navigate to={`${pathWithoutLocale}${search}`} replace />;
998
- }
999
-
1000
- // Wrap children with the IntlayerProvider and set the current locale
1001
- return (
1002
- <IntlayerProvider locale={currentLocale}>{children}</IntlayerProvider>
1003
- );
1004
- }
1005
- };
1006
-
1007
- const RouterContent = ({ children }) => {
1008
- const { path } = useLocation();
1009
-
1010
- if (!path) {
1011
- return null;
1012
- }
1013
-
1014
- const pathLocale = path.split("/")[1];
1015
-
1016
- const isLocaleRoute = locales
1017
- .filter((locale) => middleware.prefixDefault || locale !== defaultLocale)
1018
- .some((locale) => locale.toString() === pathLocale);
1019
-
1020
- if (isLocaleRoute) {
1021
- return <AppLocalized locale={pathLocale}>{children}</AppLocalized>;
1022
- }
1023
-
1024
- return (
1025
- <AppLocalized
1026
- locale={!middleware.prefixDefault ? defaultLocale : undefined}
1027
- >
1028
- {children}
1029
- </AppLocalized>
1030
- );
1031
- };
725
+ const { LocationProvider, Router, Route } = require("preact-iso");
1032
726
 
1033
727
  /**
1034
728
  * A router component that sets up locale-specific routes.
1035
729
  * It uses preact-iso to manage navigation and render localised components.
1036
730
  */
1037
- const LocaleRouter = ({ children }) => (
1038
- <LocationProvider>
1039
- <RouterContent>{children}</RouterContent>
1040
- </LocationProvider>
1041
- );
731
+ const LocaleRouter = ({ children }) =>
732
+ h(
733
+ LocationProvider,
734
+ {},
735
+ h(
736
+ Router,
737
+ {},
738
+ localeMap(({ locale, urlPrefix }) => ({ locale, urlPrefix }))
739
+ .sort((a, b) => b.urlPrefix.length - a.urlPrefix.length)
740
+ .map(({ locale, urlPrefix }) =>
741
+ h(Route, {
742
+ key: locale,
743
+ path: `${urlPrefix}/:rest*`,
744
+ component: () => h(IntlayerProvider, { locale }, children),
745
+ })
746
+ )
747
+ )
748
+ );
1042
749
 
1043
750
  module.exports = { LocaleRouter };
1044
751
  ```
@@ -1048,7 +755,8 @@ Then, you can use the `LocaleRouter` component in your application:
1048
755
  ```tsx fileName="src/app.tsx" codeFormat="typescript"
1049
756
  import { LocaleRouter } from "./components/LocaleRouter";
1050
757
  import type { FunctionalComponent } from "preact";
1051
- // ... Your AppContent component (defined in Step 5)
758
+
759
+ // ... Your AppContent component
1052
760
 
1053
761
  const App: FunctionalComponent = () => (
1054
762
  <LocaleRouter>
@@ -1061,7 +769,8 @@ export default App;
1061
769
 
1062
770
  ```jsx fileName="src/app.jsx" codeFormat="esm"
1063
771
  import { LocaleRouter } from "./components/LocaleRouter";
1064
- // ... Your AppContent component (defined in Step 5)
772
+
773
+ // ... Your AppContent component
1065
774
 
1066
775
  const App = () => (
1067
776
  <LocaleRouter>
@@ -1074,7 +783,8 @@ export default App;
1074
783
 
1075
784
  ```jsx fileName="src/app.cjsx" codeFormat="commonjs"
1076
785
  const { LocaleRouter } = require("./components/LocaleRouter");
1077
- // ... Your AppContent component (defined in Step 5)
786
+
787
+ // ... Your AppContent component
1078
788
 
1079
789
  const App = () => (
1080
790
  <LocaleRouter>
@@ -1085,47 +795,12 @@ const App = () => (
1085
795
  module.exports = App;
1086
796
  ```
1087
797
 
1088
- In parallel, you can also use the `intlayerProxy` to add server-side routing to your application. This plugin will automatically detect the current locale based on the URL and set the appropriate locale cookie. If no locale is specified, the plugin will determine the most appropriate locale based on the user's browser language preferences. If no locale is detected, it will redirect to the default locale.
1089
-
1090
- ```typescript {3,7} fileName="vite.config.ts" codeFormat="typescript"
1091
- import { defineConfig } from "vite";
1092
- import preact from "@preact/preset-vite";
1093
- import { intlayer, intlayerProxy } from "vite-intlayer";
1094
-
1095
- // https://vitejs.dev/config/
1096
- export default defineConfig({
1097
- plugins: [preact(), intlayer(), intlayerProxy()],
1098
- });
1099
- ```
1100
-
1101
- ```javascript {3,7} fileName="vite.config.mjs" codeFormat="esm"
1102
- import { defineConfig } from "vite";
1103
- import preact from "@preact/preset-vite";
1104
- import { intlayer, intlayerProxy } from "vite-intlayer";
1105
-
1106
- // https://vitejs.dev/config/
1107
- export default defineConfig({
1108
- plugins: [preact(), intlayer(), intlayerProxy()],
1109
- });
1110
- ```
1111
-
1112
- ```javascript {3,7} fileName="vite.config.cjs" codeFormat="commonjs"
1113
- const { defineConfig } = require("vite");
1114
- const preact = require("@preact/preset-vite");
1115
- const { intlayer, intlayerProxy } = require("vite-intlayer");
1116
-
1117
- // https://vitejs.dev/config/
1118
- module.exports = defineConfig({
1119
- plugins: [preact(), intlayer(), intlayerProxy()],
1120
- });
1121
- ```
1122
-
1123
798
  ### (Optional) Step 8: Change the URL when the locale changes
1124
799
 
1125
- To change the URL when the locale changes, you can use the `onLocaleChange` prop provided by the `useLocale` hook. In parallel, you can use `useLocation` and `route` from `preact-iso` to update the URL path.
800
+ To change the URL when the locale changes, you can use the `onLocaleChange` prop provided by the `useLocale` hook. In parallel, you can use the `route` method from `useLocation` of `preact-iso` to update the URL path.
1126
801
 
1127
802
  ```tsx fileName="src/components/LocaleSwitcher.tsx" codeFormat="typescript"
1128
- import { useLocation, route } from "preact-iso";
803
+ import { useLocation } from "preact-iso";
1129
804
  import {
1130
805
  Locales,
1131
806
  getHTMLTextDir,
@@ -1136,13 +811,12 @@ import { useLocale } from "preact-intlayer";
1136
811
  import type { FunctionalComponent } from "preact";
1137
812
 
1138
813
  const LocaleSwitcher: FunctionalComponent = () => {
1139
- const location = useLocation();
814
+ const { url, route } = useLocation();
1140
815
  const { locale, availableLocales, setLocale } = useLocale({
1141
816
  onLocaleChange: (newLocale) => {
1142
- const currentFullPath = location.url; // preact-iso provides the full url
1143
817
  // Construct the URL with the updated locale
1144
818
  // Example: /es/about?foo=bar
1145
- const pathWithLocale = getLocalizedUrl(currentFullPath, newLocale);
819
+ const pathWithLocale = getLocalizedUrl(url, newLocale);
1146
820
 
1147
821
  // Update the URL path
1148
822
  route(pathWithLocale, true); // true for replace
@@ -1155,7 +829,7 @@ const LocaleSwitcher: FunctionalComponent = () => {
1155
829
  <div id="localePopover" popover="auto">
1156
830
  {availableLocales.map((localeItem) => (
1157
831
  <a
1158
- href={getLocalizedUrl(location.url, localeItem)}
832
+ href={getLocalizedUrl(url, localeItem)}
1159
833
  hreflang={localeItem}
1160
834
  aria-current={locale === localeItem ? "page" : undefined}
1161
835
  onClick={(e) => {
@@ -1192,7 +866,7 @@ export default LocaleSwitcher;
1192
866
  ```
1193
867
 
1194
868
  ```jsx fileName="src/components/LocaleSwitcher.jsx" codeFormat="esm"
1195
- import { useLocation, route } from "preact-iso";
869
+ import { useLocation } from "preact-iso";
1196
870
  import {
1197
871
  Locales,
1198
872
  getHTMLTextDir,
@@ -1200,14 +874,12 @@ import {
1200
874
  getLocalizedUrl,
1201
875
  } from "intlayer";
1202
876
  import { useLocale } from "preact-intlayer";
1203
- import { h } from "preact"; // For JSX
1204
877
 
1205
878
  const LocaleSwitcher = () => {
1206
- const location = useLocation();
879
+ const { url, route } = useLocation();
1207
880
  const { locale, availableLocales, setLocale } = useLocale({
1208
881
  onLocaleChange: (newLocale) => {
1209
- const currentFullPath = location.url;
1210
- const pathWithLocale = getLocalizedUrl(currentFullPath, newLocale);
882
+ const pathWithLocale = getLocalizedUrl(url, newLocale);
1211
883
  route(pathWithLocale, true);
1212
884
  },
1213
885
  });
@@ -1218,7 +890,7 @@ const LocaleSwitcher = () => {
1218
890
  <div id="localePopover" popover="auto">
1219
891
  {availableLocales.map((localeItem) => (
1220
892
  <a
1221
- href={getLocalizedUrl(location.url, localeItem)}
893
+ href={getLocalizedUrl(url, localeItem)}
1222
894
  hreflang={localeItem}
1223
895
  aria-current={locale === localeItem ? "page" : undefined}
1224
896
  onClick={(e) => {
@@ -1246,7 +918,7 @@ export default LocaleSwitcher;
1246
918
  ```
1247
919
 
1248
920
  ```jsx fileName="src/components/LocaleSwitcher.cjsx" codeFormat="commonjs"
1249
- const { useLocation, route } = require("preact-iso");
921
+ const { useLocation } = require("preact-iso");
1250
922
  const {
1251
923
  Locales,
1252
924
  getHTMLTextDir,
@@ -1254,45 +926,51 @@ const {
1254
926
  getLocalizedUrl,
1255
927
  } = require("intlayer");
1256
928
  const { useLocale } = require("preact-intlayer");
1257
- const { h } = require("preact"); // For JSX
1258
929
 
1259
930
  const LocaleSwitcher = () => {
1260
- const location = useLocation();
931
+ const { url, route } = useLocation();
1261
932
  const { locale, availableLocales, setLocale } = useLocale({
1262
933
  onLocaleChange: (newLocale) => {
1263
- const currentFullPath = location.url;
1264
- const pathWithLocale = getLocalizedUrl(currentFullPath, newLocale);
934
+ const pathWithLocale = getLocalizedUrl(url, newLocale);
1265
935
  route(pathWithLocale, true);
1266
936
  },
1267
937
  });
1268
938
 
1269
- return (
1270
- <div>
1271
- <button popovertarget="localePopover">{getLocaleName(locale)}</button>
1272
- <div id="localePopover" popover="auto">
1273
- {availableLocales.map((localeItem) => (
1274
- <a
1275
- href={getLocalizedUrl(location.url, localeItem)}
1276
- hreflang={localeItem}
1277
- aria-current={locale === localeItem ? "page" : undefined}
1278
- onClick={(e) => {
939
+ return h(
940
+ "div",
941
+ {},
942
+ h("button", { popovertarget: "localePopover" }, getLocaleName(locale)),
943
+ h(
944
+ "div",
945
+ { id: "localePopover", popover: "auto" },
946
+ availableLocales.map((localeItem) =>
947
+ h(
948
+ "a",
949
+ {
950
+ href: getLocalizedUrl(url, localeItem),
951
+ hreflang: localeItem,
952
+ "aria-current": locale === localeItem ? "page" : undefined,
953
+ onClick: (e) => {
1279
954
  e.preventDefault();
1280
955
  setLocale(localeItem);
1281
- }}
1282
- key={localeItem}
1283
- >
1284
- <span>{localeItem}</span>
1285
- <span>{getLocaleName(localeItem, localeItem)}</span>
1286
- <span dir={getHTMLTextDir(localeItem)} lang={localeItem}>
1287
- {getLocaleName(localeItem, locale)}
1288
- </span>
1289
- <span dir="ltr" lang={Locales.ENGLISH}>
1290
- {getLocaleName(localeItem, Locales.ENGLISH)}
1291
- </span>
1292
- </a>
1293
- ))}
1294
- </div>
1295
- </div>
956
+ },
957
+ key: localeItem,
958
+ },
959
+ h("span", {}, localeItem),
960
+ h("span", {}, getLocaleName(localeItem, localeItem)),
961
+ h(
962
+ "span",
963
+ { dir: getHTMLTextDir(localeItem), lang: localeItem },
964
+ getLocaleName(localeItem, locale)
965
+ ),
966
+ h(
967
+ "span",
968
+ { dir: "ltr", lang: Locales.ENGLISH },
969
+ getLocaleName(localeItem, Locales.ENGLISH)
970
+ )
971
+ )
972
+ )
973
+ )
1296
974
  );
1297
975
  };
1298
976
 
@@ -1301,21 +979,17 @@ module.exports = LocaleSwitcher;
1301
979
 
1302
980
  > Documentation references:
1303
981
  >
1304
- > > - [`useLocale` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/packages/react-intlayer/useLocale.md) (API is similar for `preact-intlayer`) > - [`getLocaleName` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/packages/intlayer/getLocaleName.md) > - [`getLocalizedUrl` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/packages/intlayer/getLocalizedUrl.md) > - [`getHTMLTextDir` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/packages/intlayer/getHTMLTextDir.md) > - [`hreflang` attribute](https://developers.google.com/search/docs/specialty/international/localized-versions?hl=fr) > - [`lang` attribute](https://developer.mozilla.org/en-GB/docs/Web/HTML/Global_attributes/lang) > - [`dir` attribute](https://developer.mozilla.org/en-GB/docs/Web/HTML/Global_attributes/dir) > - [`aria-current` attribute](https://developer.mozilla.org/en-GB/docs/Web/Accessibility/ARIA/Attributes/aria-current) > - [Popover API](https://developer.mozilla.org/en-GB/docs/Web/API/Popover_API) la.org/en-US/docs/Web/HTML/Global_attributes/dir)> - [`aria-current` attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current)> - [Popover API](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API)
1305
-
1306
- Below is the updated **Step 9** with added explanations and refined code examples:
1307
-
1308
- ---
982
+ > > - [`useLocale` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/packages/react-intlayer/useLocale.md) (API is similar for `preact-intlayer`)> - [`getLocaleName` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/packages/intlayer/getLocaleName.md)> - [`getLocalizedUrl` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/packages/intlayer/getLocalizedUrl.md)> - [`getHTMLTextDir` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/packages/intlayer/getHTMLTextDir.md)> - [`hreflang` attribute](https://developers.google.com/search/docs/specialty/international/localized-versions?hl=fr)> - [`lang` attribute](https://developer.mozilla.org/en-GB/docs/Web/HTML/Global_attributes/lang)> - [`dir` attribute](https://developer.mozilla.org/en-GB/docs/Web/HTML/Global_attributes/dir)> - [`aria-current` attribute](https://developer.mozilla.org/en-GB/docs/Web/Accessibility/ARIA/Attributes/aria-current)> - [Popover API](https://developer.mozilla.org/en-GB/docs/Web/API/Popover_API)
1309
983
 
1310
984
  ### (Optional) Step 9: Switch the HTML Language and Direction Attributes
1311
985
 
1312
- When your application supports multiple languages, it is crucial to update the `<html>` tag's `lang` and `dir` attributes to match the current locale. Doing so ensures:
986
+ When your application supports multiple languages, it's crucial to update the `<html>` tag's `lang` and `dir` attributes to match the current locale. Doing so ensures:
1313
987
 
1314
988
  - **Accessibility**: Screen readers and assistive technologies rely on the correct `lang` attribute to pronounce and interpret content accurately.
1315
989
  - **Text Rendering**: The `dir` (direction) attribute ensures that text is rendered in the proper order (e.g., left-to-right for English, right-to-left for Arabic or Hebrew), which is essential for readability.
1316
- - **SEO**: Search engines use the `lang` attribute to determine the language of your page, helping to serve the correct localised content in search results.
990
+ - **SEO**: Search engines use the `lang` attribute to determine the language of your page, helping to serve the right localised content in search results.
1317
991
 
1318
- By updating these attributes dynamically when the locale changes, you ensure a consistent and accessible experience for users across all supported languages.
992
+ By updating these attributes dynamically when the locale changes, you guarantee a consistent and accessible experience for users across all supported languages.
1319
993
 
1320
994
  #### Implementing the Hook
1321
995
 
@@ -1452,12 +1126,6 @@ const App = () => (
1452
1126
  module.exports = App;
1453
1127
  ```
1454
1128
 
1455
- By applying these changes, your application will:
1456
-
1457
- - Ensure the **language** (`lang`) attribute correctly reflects the current locale, which is important for SEO and browser behaviour.
1458
- - Adjust the **text direction** (`dir`) according to the locale, enhancing readability and usability for languages with different reading orders.
1459
- - Provide a more **accessible** experience, as assistive technologies rely on these attributes to function optimally.
1460
-
1461
1129
  ### (Optional) Step 10: Creating a Localised Link Component
1462
1130
 
1463
1131
  To ensure that your application's navigation respects the current locale, you can create a custom `Link` component. This component automatically prefixes internal URLs with the current language.
@@ -1468,23 +1136,21 @@ This behaviour is useful for several reasons:
1468
1136
  - **Consistency**: By using a localised link throughout your application, you guarantee that navigation stays within the current locale, preventing unexpected language switches.
1469
1137
  - **Maintainability**: Centralising the localisation logic in a single component simplifies the management of URLs.
1470
1138
 
1471
- For Preact with `preact-iso`, standard `<a>` tags are typically used for navigation, and `preact-iso` handles the routing. If you need programmematic navigation on click (e.g., to perform actions before navigating), you can use the `route` function from `useLocation`. Here's how you can create a custom anchor component that localises URLs:
1139
+ Below is the implementation of a localised `Link` component in Preact:
1472
1140
 
1473
- ```tsx fileName="src/components/LocalizedLink.tsx" codeFormat="typescript"
1141
+ ```tsx fileName="src/components/Link.tsx" codeFormat="typescript"
1474
1142
  import { getLocalizedUrl } from "intlayer";
1475
- import { useLocale, useLocation, route } from "preact-intlayer"; // Assuming useLocation and route can be from preact-iso via preact-intlayer if re-exported, or import directly
1476
- // If not re-exported, import directly: import { useLocation, route } from "preact-iso";
1477
- import type { JSX } from "preact"; // For HTMLAttributes
1478
- import { forwardRef } from "preact/compat"; // For forwarding refs
1143
+ import { useLocale } from "preact-intlayer";
1144
+ import { forwardRef } from "preact/compat";
1145
+ import type { JSX } from "preact";
1479
1146
 
1480
- export interface LocalizedLinkProps extends JSX.HTMLAttributes<HTMLAnchorElement> {
1147
+ export interface LinkProps extends JSX.HTMLAttributes<HTMLAnchorElement> {
1481
1148
  href: string;
1482
- replace?: boolean; // Optional: to replace history state
1483
1149
  }
1484
1150
 
1485
1151
  /**
1486
1152
  * Utility function to check whether a given URL is external.
1487
- * If the URL starts with http:// or https://, it is considered external.
1153
+ * If the URL starts with http:// or https://, it's considered external.
1488
1154
  */
1489
1155
  export const checkIsExternalLink = (href?: string): boolean =>
1490
1156
  /^https?:\/\//.test(href ?? "");
@@ -1492,163 +1158,150 @@ export const checkIsExternalLink = (href?: string): boolean =>
1492
1158
  /**
1493
1159
  * A custom Link component that adapts the href attribute based on the current locale.
1494
1160
  * For internal links, it uses `getLocalizedUrl` to prefix the URL with the locale (e.g., /fr/about).
1495
- * This ensures that navigation remains within the same locale context.
1496
- * It uses a standard <a> tag but can trigger client-side navigation using preact-iso's `route`.
1161
+ * This ensures that navigation stays within the same locale context.
1497
1162
  */
1498
- export const LocalizedLink = forwardRef<HTMLAnchorElement, LocalizedLinkProps>(
1499
- ({ href, children, onClick, replace = false, ...props }, ref) => {
1163
+ export const Link = forwardRef<HTMLAnchorElement, LinkProps>(
1164
+ ({ href, children, ...props }, ref) => {
1500
1165
  const { locale } = useLocale();
1501
- const location = useLocation(); // from preact-iso
1502
1166
  const isExternalLink = checkIsExternalLink(href);
1503
1167
 
1168
+ // If the link is internal and a valid href is provided, get the localised URL.
1504
1169
  const hrefI18n =
1505
1170
  href && !isExternalLink ? getLocalizedUrl(href, locale) : href;
1506
1171
 
1507
- const handleClick = (event: JSX.TargetedMouseEvent<HTMLAnchorElement>) => {
1508
- if (onClick) {
1509
- onClick(event);
1510
- }
1511
- if (
1512
- !isExternalLink &&
1513
- href && // Ensure href is defined
1514
- event.button === 0 && // Left click
1515
- !event.metaKey &&
1516
- !event.ctrlKey &&
1517
- !event.shiftKey &&
1518
- !event.altKey && // Standard modifiers check
1519
- !props.target // Not targeting a new tab/window
1520
- ) {
1521
- event.preventDefault();
1522
- if (location.url !== hrefI18n) {
1523
- // Only navigate if the URL is different
1524
- route(hrefI18n, replace); // Use preact-iso's route
1525
- }
1526
- }
1527
- };
1528
-
1529
1172
  return (
1530
- <a href={hrefI18n} ref={ref} onClick={handleClick} {...props}>
1173
+ <a href={hrefI18n} ref={ref} {...props}>
1531
1174
  {children}
1532
1175
  </a>
1533
1176
  );
1534
1177
  }
1535
1178
  );
1179
+
1180
+ Link.displayName = "Link";
1536
1181
  ```
1537
1182
 
1538
- ```jsx fileName="src/components/LocalizedLink.jsx" codeFormat="esm"
1183
+ ```jsx fileName="src/components/Link.jsx" codeFormat="esm"
1539
1184
  import { getLocalizedUrl } from "intlayer";
1540
1185
  import { useLocale } from "preact-intlayer";
1541
- import { useLocation, route } from "preact-iso"; // Import from preact-iso
1542
1186
  import { forwardRef } from "preact/compat";
1543
- import { h } from "preact"; // For JSX
1544
1187
 
1188
+ /**
1189
+ * Utility function to check whether a given URL is external.
1190
+ * If the URL starts with http:// or https://, it's considered external.
1191
+ */
1545
1192
  export const checkIsExternalLink = (href) => /^https?:\/\//.test(href ?? "");
1546
1193
 
1547
- export const LocalizedLink = forwardRef(
1548
- ({ href, children, onClick, replace = false, ...props }, ref) => {
1549
- const { locale } = useLocale();
1550
- const location = useLocation();
1551
- const isExternalLink = checkIsExternalLink(href);
1194
+ /**
1195
+ * A custom Link component that adapts the href attribute based on the current locale.
1196
+ * For internal links, it uses `getLocalizedUrl` to prefix the URL with the locale (e.g., /fr/about).
1197
+ * This ensures that navigation stays within the same locale context.
1198
+ */
1199
+ export const Link = forwardRef(({ href, children, ...props }, ref) => {
1200
+ const { locale } = useLocale();
1201
+ const isExternalLink = checkIsExternalLink(href);
1552
1202
 
1553
- const hrefI18n =
1554
- href && !isExternalLink ? getLocalizedUrl(href, locale) : href;
1203
+ // If the link is internal and a valid href is provided, get the localised URL.
1204
+ const hrefI18n =
1205
+ href && !isExternalLink ? getLocalizedUrl(href, locale) : href;
1555
1206
 
1556
- const handleClick = (event) => {
1557
- if (onClick) {
1558
- onClick(event);
1559
- }
1560
- if (
1561
- !isExternalLink &&
1562
- href &&
1563
- event.button === 0 &&
1564
- !event.metaKey &&
1565
- !event.ctrlKey &&
1566
- !event.shiftKey &&
1567
- !event.altKey &&
1568
- !props.target
1569
- ) {
1570
- event.preventDefault();
1571
- if (location.url !== hrefI18n) {
1572
- route(hrefI18n, replace);
1573
- }
1574
- }
1575
- };
1207
+ return (
1208
+ <a href={hrefI18n} ref={ref} {...props}>
1209
+ {children}
1210
+ </a>
1211
+ );
1212
+ });
1576
1213
 
1577
- return (
1578
- <a href={hrefI18n} ref={ref} onClick={handleClick} {...props}>
1579
- {children}
1580
- </a>
1581
- );
1582
- }
1583
- );
1214
+ Link.displayName = "Link";
1584
1215
  ```
1585
1216
 
1586
- ```jsx fileName="src/components/LocalizedLink.cjsx" codeFormat="commonjs"
1217
+ ```jsx fileName="src/components/Link.cjsx" codeFormat="commonjs"
1587
1218
  const { getLocalizedUrl } = require("intlayer");
1588
1219
  const { useLocale } = require("preact-intlayer");
1589
- const { useLocation, route } = require("preact-iso"); // Import from preact-iso
1590
1220
  const { forwardRef } = require("preact/compat");
1591
- const { h } = require("preact"); // For JSX
1592
1221
 
1222
+ /**
1223
+ * Utility function to check whether a given URL is external.
1224
+ * If the URL starts with http:// or https://, it's considered external.
1225
+ */
1593
1226
  const checkIsExternalLink = (href) => /^https?:\/\//.test(href ?? "");
1594
1227
 
1595
- const LocalizedLink = forwardRef(
1596
- ({ href, children, onClick, replace = false, ...props }, ref) => {
1597
- const { locale } = useLocale();
1598
- const location = useLocation();
1599
- const isExternalLink = checkIsExternalLink(href);
1600
-
1601
- const hrefI18n =
1602
- href && !isExternalLink ? getLocalizedUrl(href, locale) : href;
1228
+ /**
1229
+ * A custom Link component that adapts the href attribute based on the current locale.
1230
+ * For internal links, it uses `getLocalizedUrl` to prefix the URL with the locale (e.g., /fr/about).
1231
+ * This ensures that navigation stays within the same locale context.
1232
+ */
1233
+ const Link = forwardRef(({ href, children, ...props }, ref) => {
1234
+ const { locale } = useLocale();
1235
+ const isExternalLink = checkIsExternalLink(href);
1236
+
1237
+ // If the link is internal and a valid href is provided, get the localised URL.
1238
+ const hrefI18n =
1239
+ href && !isExternalLink ? getLocalizedUrl(href, locale) : href;
1240
+
1241
+ return h(
1242
+ "a",
1243
+ {
1244
+ href: hrefI18n,
1245
+ ref: ref,
1246
+ ...props,
1247
+ },
1248
+ children
1249
+ );
1250
+ });
1603
1251
 
1604
- const handleClick = (event) => {
1605
- if (onClick) {
1606
- onClick(event);
1607
- }
1608
- if (
1609
- !isExternalLink &&
1610
- href &&
1611
- event.button === 0 &&
1612
- !event.metaKey &&
1613
- !event.ctrlKey &&
1614
- !event.shiftKey &&
1615
- !event.altKey &&
1616
- !props.target
1617
- ) {
1618
- event.preventDefault();
1619
- if (location.url !== hrefI18n) {
1620
- route(hrefI18n, replace);
1621
- }
1622
- }
1623
- };
1252
+ Link.displayName = "Link";
1624
1253
 
1625
- return (
1626
- <a href={hrefI18n} ref={ref} onClick={handleClick} {...props}>
1627
- {children}
1628
- </a>
1629
- );
1630
- }
1631
- );
1632
-
1633
- module.exports = { LocalizedLink, checkIsExternalLink };
1254
+ module.exports = { Link, checkIsExternalLink };
1634
1255
  ```
1635
1256
 
1636
1257
  #### How It Works
1637
1258
 
1638
1259
  - **Detecting External Links**:
1639
- The helper function `checkIsExternalLink` determines whether a URL is external. External links are left unchanged.
1260
+ The helper function `checkIsExternalLink` determines whether a URL is external. External links are left unchanged because they do not need localisation.
1640
1261
  - **Retrieving the Current Locale**:
1641
- The `useLocale` hook provides the current locale.
1262
+ The `useLocale` hook provides the current locale (e.g., `fr` for French).
1642
1263
  - **Localising the URL**:
1643
- For internal links, `getLocalizedUrl` prefixes the URL with the current locale.
1644
- - **Client-Side Navigation**:
1645
- The `handleClick` function checks if it is an internal link and if standard navigation should be prevented. If so, it uses `preact-iso`'s `route` function (obtained via `useLocation` or directly imported) to perform client-side navigation. This provides SPA-like behaviour without full page reloads.
1264
+ For internal links (i.e., non-external), `getLocalizedUrl` is used to automatically prefix the URL with the current locale. This means that if your user is in French, passing `/about` as the `href` will transform it to `/fr/about`.
1646
1265
  - **Returning the Link**:
1647
- The component returns an `<a>` element with the localised URL and the custom click handler.
1266
+ The component returns an `<a>` element with the localised URL, ensuring that navigation is consistent with the locale.
1267
+
1268
+ ### (Optional) Step 11: Render Markdown and HTML
1269
+
1270
+ Intlayer supports rendering Markdown and HTML content in Preact.
1271
+
1272
+ You can customise the rendering of Markdown and HTML content by using the `.use()` method. This method allows you to override the default rendering of specific tags.
1273
+
1274
+ ```tsx
1275
+ import { useIntlayer } from "preact-intlayer";
1276
+
1277
+ const { myMarkdownContent, myHtmlContent } = useIntlayer("my-component");
1278
+
1279
+ // ...
1280
+
1281
+ return (
1282
+ <div>
1283
+ {/* Basic rendering */}
1284
+ {myMarkdownContent}
1285
+
1286
+ {/* Custom rendering for Markdown */}
1287
+ {myMarkdownContent.use({
1288
+ h1: (props) => <h1 style={{ color: "red" }} {...props} />,
1289
+ })}
1290
+
1291
+ {/* Basic rendering for HTML */}
1292
+ {myHtmlContent}
1293
+
1294
+ {/* Custom rendering for HTML */}
1295
+ {myHtmlContent.use({
1296
+ b: (props) => <strong style={{ color: "blue" }} {...props} />,
1297
+ })}
1298
+ </div>
1299
+ );
1300
+ ```
1648
1301
 
1649
1302
  ### Configure TypeScript
1650
1303
 
1651
- Intlayer uses module augmentation to gain the benefits of TypeScript and strengthen your codebase.
1304
+ Intlayer uses module augmentation to get the benefits of TypeScript and make your codebase stronger.
1652
1305
 
1653
1306
  ![Autocompletion](https://github.com/aymericzip/intlayer/blob/main/docs/assets/autocompletion.png?raw=true)
1654
1307
 
@@ -1687,7 +1340,7 @@ To do this, you can add the following instructions to your `.gitignore` file:
1687
1340
 
1688
1341
  ### VS Code Extension
1689
1342
 
1690
- To enhance your development experience with Intlayer, you can install the official **Intlayer VS Code Extension**.
1343
+ To improve your development experience with Intlayer, you can install the official **Intlayer VS Code Extension**.
1691
1344
 
1692
1345
  [Install from the VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=intlayer.intlayer-vs-code-extension)
1693
1346