@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.
- package/dist/cjs/generated/docs.entry.cjs +160 -0
- package/dist/cjs/generated/docs.entry.cjs.map +1 -1
- package/dist/esm/generated/docs.entry.mjs +160 -0
- package/dist/esm/generated/docs.entry.mjs.map +1 -1
- package/dist/types/generated/docs.entry.d.ts +8 -0
- package/dist/types/generated/docs.entry.d.ts.map +1 -1
- package/docs/ar/intlayer_with_adonisjs.md +394 -0
- package/docs/ar/intlayer_with_hono.md +223 -0
- package/docs/ar/intlayer_with_vite+preact.md +317 -675
- package/docs/ar/packages/adonis-intlayer/exports.md +50 -0
- package/docs/ar/packages/adonis-intlayer/intlayer.md +54 -0
- package/docs/ar/packages/adonis-intlayer/t.md +149 -0
- package/docs/ar/packages/hono-intlayer/exports.md +59 -0
- package/docs/ar/packages/hono-intlayer/intlayer.md +60 -0
- package/docs/ar/packages/hono-intlayer/t.md +268 -0
- package/docs/de/intlayer_with_adonisjs.md +392 -0
- package/docs/de/intlayer_with_hono.md +418 -0
- package/docs/de/intlayer_with_vite+preact.md +272 -632
- package/docs/de/packages/adonis-intlayer/exports.md +50 -0
- package/docs/de/packages/adonis-intlayer/intlayer.md +54 -0
- package/docs/de/packages/adonis-intlayer/t.md +149 -0
- package/docs/de/packages/hono-intlayer/exports.md +59 -0
- package/docs/de/packages/hono-intlayer/intlayer.md +59 -0
- package/docs/de/packages/hono-intlayer/t.md +316 -0
- package/docs/en/index.md +8 -0
- package/docs/en/intlayer_with_adonisjs.md +388 -0
- package/docs/en/intlayer_with_hono.md +418 -0
- package/docs/en/intlayer_with_vite+preact.md +171 -556
- package/docs/en/introduction.md +1 -0
- package/docs/en/packages/adonis-intlayer/exports.md +50 -0
- package/docs/en/packages/adonis-intlayer/intlayer.md +54 -0
- package/docs/en/packages/adonis-intlayer/t.md +149 -0
- package/docs/en/packages/hono-intlayer/exports.md +59 -0
- package/docs/en/packages/hono-intlayer/intlayer.md +59 -0
- package/docs/en/packages/hono-intlayer/t.md +316 -0
- package/docs/en-GB/intlayer_with_adonisjs.md +394 -0
- package/docs/en-GB/intlayer_with_hono.md +418 -0
- package/docs/en-GB/intlayer_with_vite+preact.md +236 -583
- package/docs/en-GB/packages/adonis-intlayer/exports.md +50 -0
- package/docs/en-GB/packages/adonis-intlayer/intlayer.md +54 -0
- package/docs/en-GB/packages/adonis-intlayer/t.md +149 -0
- package/docs/en-GB/packages/hono-intlayer/exports.md +59 -0
- package/docs/en-GB/packages/hono-intlayer/intlayer.md +59 -0
- package/docs/en-GB/packages/hono-intlayer/t.md +316 -0
- package/docs/es/intlayer_with_adonisjs.md +388 -0
- package/docs/es/intlayer_with_hono.md +418 -0
- package/docs/es/intlayer_with_vite+preact.md +286 -650
- package/docs/es/packages/adonis-intlayer/exports.md +50 -0
- package/docs/es/packages/adonis-intlayer/intlayer.md +54 -0
- package/docs/es/packages/adonis-intlayer/t.md +149 -0
- package/docs/es/packages/hono-intlayer/exports.md +59 -0
- package/docs/es/packages/hono-intlayer/intlayer.md +59 -0
- package/docs/es/packages/hono-intlayer/t.md +316 -0
- package/docs/fr/intlayer_with_adonisjs.md +388 -0
- package/docs/fr/intlayer_with_hono.md +418 -0
- package/docs/fr/intlayer_with_vite+preact.md +274 -614
- package/docs/fr/packages/adonis-intlayer/exports.md +50 -0
- package/docs/fr/packages/adonis-intlayer/intlayer.md +54 -0
- package/docs/fr/packages/adonis-intlayer/t.md +149 -0
- package/docs/fr/packages/hono-intlayer/exports.md +59 -0
- package/docs/fr/packages/hono-intlayer/intlayer.md +59 -0
- package/docs/fr/packages/hono-intlayer/t.md +316 -0
- package/docs/hi/intlayer_with_adonisjs.md +394 -0
- package/docs/hi/intlayer_with_hono.md +227 -0
- package/docs/hi/intlayer_with_vite+preact.md +304 -680
- package/docs/hi/packages/adonis-intlayer/exports.md +50 -0
- package/docs/hi/packages/adonis-intlayer/intlayer.md +54 -0
- package/docs/hi/packages/adonis-intlayer/t.md +149 -0
- package/docs/hi/packages/hono-intlayer/exports.md +59 -0
- package/docs/hi/packages/hono-intlayer/intlayer.md +60 -0
- package/docs/hi/packages/hono-intlayer/t.md +268 -0
- package/docs/id/intlayer_with_adonisjs.md +394 -0
- package/docs/id/intlayer_with_hono.md +227 -0
- package/docs/id/intlayer_with_vite+preact.md +297 -697
- package/docs/id/packages/adonis-intlayer/exports.md +50 -0
- package/docs/id/packages/adonis-intlayer/intlayer.md +54 -0
- package/docs/id/packages/adonis-intlayer/t.md +149 -0
- package/docs/id/packages/hono-intlayer/exports.md +59 -0
- package/docs/id/packages/hono-intlayer/intlayer.md +60 -0
- package/docs/id/packages/hono-intlayer/t.md +268 -0
- package/docs/it/intlayer_with_adonisjs.md +394 -0
- package/docs/it/intlayer_with_hono.md +227 -0
- package/docs/it/intlayer_with_vite+preact.md +290 -659
- package/docs/it/packages/adonis-intlayer/exports.md +50 -0
- package/docs/it/packages/adonis-intlayer/intlayer.md +54 -0
- package/docs/it/packages/adonis-intlayer/t.md +149 -0
- package/docs/it/packages/hono-intlayer/exports.md +59 -0
- package/docs/it/packages/hono-intlayer/intlayer.md +60 -0
- package/docs/it/packages/hono-intlayer/t.md +268 -0
- package/docs/ja/intlayer_with_adonisjs.md +394 -0
- package/docs/ja/intlayer_with_hono.md +227 -0
- package/docs/ja/intlayer_with_vite+preact.md +307 -662
- package/docs/ja/packages/adonis-intlayer/exports.md +50 -0
- package/docs/ja/packages/adonis-intlayer/intlayer.md +54 -0
- package/docs/ja/packages/adonis-intlayer/t.md +149 -0
- package/docs/ja/packages/hono-intlayer/exports.md +59 -0
- package/docs/ja/packages/hono-intlayer/intlayer.md +60 -0
- package/docs/ja/packages/hono-intlayer/t.md +268 -0
- package/docs/ko/intlayer_with_adonisjs.md +394 -0
- package/docs/ko/intlayer_with_hono.md +227 -0
- package/docs/ko/intlayer_with_vite+preact.md +303 -703
- package/docs/ko/packages/adonis-intlayer/exports.md +50 -0
- package/docs/ko/packages/adonis-intlayer/intlayer.md +54 -0
- package/docs/ko/packages/adonis-intlayer/t.md +149 -0
- package/docs/ko/packages/hono-intlayer/exports.md +59 -0
- package/docs/ko/packages/hono-intlayer/intlayer.md +60 -0
- package/docs/ko/packages/hono-intlayer/t.md +268 -0
- package/docs/pl/intlayer_with_adonisjs.md +394 -0
- package/docs/pl/intlayer_with_hono.md +227 -0
- package/docs/pl/intlayer_with_vite+preact.md +289 -690
- package/docs/pl/packages/adonis-intlayer/exports.md +50 -0
- package/docs/pl/packages/adonis-intlayer/intlayer.md +54 -0
- package/docs/pl/packages/adonis-intlayer/t.md +149 -0
- package/docs/pl/packages/hono-intlayer/exports.md +59 -0
- package/docs/pl/packages/hono-intlayer/intlayer.md +60 -0
- package/docs/pl/packages/hono-intlayer/t.md +268 -0
- package/docs/pt/intlayer_with_adonisjs.md +394 -0
- package/docs/pt/intlayer_with_hono.md +227 -0
- package/docs/pt/intlayer_with_vite+preact.md +275 -637
- package/docs/pt/packages/adonis-intlayer/exports.md +50 -0
- package/docs/pt/packages/adonis-intlayer/intlayer.md +54 -0
- package/docs/pt/packages/adonis-intlayer/t.md +149 -0
- package/docs/pt/packages/hono-intlayer/exports.md +59 -0
- package/docs/pt/packages/hono-intlayer/intlayer.md +60 -0
- package/docs/pt/packages/hono-intlayer/t.md +268 -0
- package/docs/ru/intlayer_with_adonisjs.md +393 -0
- package/docs/ru/intlayer_with_hono.md +223 -0
- package/docs/ru/intlayer_with_vite+preact.md +319 -683
- package/docs/ru/packages/adonis-intlayer/exports.md +50 -0
- package/docs/ru/packages/adonis-intlayer/intlayer.md +54 -0
- package/docs/ru/packages/adonis-intlayer/t.md +149 -0
- package/docs/ru/packages/hono-intlayer/exports.md +59 -0
- package/docs/ru/packages/hono-intlayer/intlayer.md +60 -0
- package/docs/ru/packages/hono-intlayer/t.md +268 -0
- package/docs/tr/intlayer_with_adonisjs.md +394 -0
- package/docs/tr/intlayer_with_hono.md +227 -0
- package/docs/tr/intlayer_with_vite+preact.md +332 -665
- package/docs/tr/packages/adonis-intlayer/exports.md +50 -0
- package/docs/tr/packages/adonis-intlayer/intlayer.md +54 -0
- package/docs/tr/packages/adonis-intlayer/t.md +149 -0
- package/docs/tr/packages/hono-intlayer/exports.md +59 -0
- package/docs/tr/packages/hono-intlayer/intlayer.md +60 -0
- package/docs/tr/packages/hono-intlayer/t.md +268 -0
- package/docs/uk/intlayer_with_adonisjs.md +394 -0
- package/docs/uk/intlayer_with_hono.md +227 -0
- package/docs/uk/intlayer_with_vite+preact.md +228 -626
- package/docs/uk/packages/adonis-intlayer/exports.md +50 -0
- package/docs/uk/packages/adonis-intlayer/intlayer.md +54 -0
- package/docs/uk/packages/adonis-intlayer/t.md +149 -0
- package/docs/uk/packages/hono-intlayer/exports.md +59 -0
- package/docs/uk/packages/hono-intlayer/intlayer.md +60 -0
- package/docs/uk/packages/hono-intlayer/t.md +268 -0
- package/docs/vi/intlayer_with_adonisjs.md +394 -0
- package/docs/vi/intlayer_with_hono.md +227 -0
- package/docs/vi/intlayer_with_vite+preact.md +294 -679
- package/docs/vi/packages/adonis-intlayer/exports.md +50 -0
- package/docs/vi/packages/adonis-intlayer/intlayer.md +54 -0
- package/docs/vi/packages/adonis-intlayer/t.md +149 -0
- package/docs/vi/packages/hono-intlayer/exports.md +59 -0
- package/docs/vi/packages/hono-intlayer/intlayer.md +60 -0
- package/docs/vi/packages/hono-intlayer/t.md +268 -0
- package/docs/zh/intlayer_with_adonisjs.md +393 -0
- package/docs/zh/intlayer_with_hono.md +418 -0
- package/docs/zh/intlayer_with_vite+preact.md +338 -743
- package/docs/zh/packages/adonis-intlayer/exports.md +50 -0
- package/docs/zh/packages/adonis-intlayer/intlayer.md +54 -0
- package/docs/zh/packages/adonis-intlayer/t.md +149 -0
- package/docs/zh/packages/hono-intlayer/exports.md +59 -0
- package/docs/zh/packages/hono-intlayer/intlayer.md +60 -0
- package/docs/zh/packages/hono-intlayer/t.md +294 -0
- package/package.json +6 -6
- 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,
|
|
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>
|
|
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
|
|
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
|
|
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 `
|
|
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 {
|
|
675
|
-
import { ComponentChildren, FunctionalComponent } from "preact";
|
|
664
|
+
import { localeMap } from "intlayer";
|
|
676
665
|
import { IntlayerProvider } from "preact-intlayer";
|
|
677
|
-
import { LocationProvider,
|
|
678
|
-
import {
|
|
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
|
-
<
|
|
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
|
-
|
|
804
|
-
import { configuration, getPathWithoutLocale } from "intlayer";
|
|
695
|
+
import { localeMap } from "intlayer";
|
|
805
696
|
import { IntlayerProvider } from "preact-intlayer";
|
|
806
|
-
import { LocationProvider,
|
|
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
|
-
<
|
|
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
|
-
|
|
925
|
-
const { configuration, getPathWithoutLocale } = require("intlayer");
|
|
723
|
+
const { localeMap } = require("intlayer");
|
|
926
724
|
const { IntlayerProvider } = require("preact-intlayer");
|
|
927
|
-
const { LocationProvider,
|
|
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
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 `
|
|
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
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
879
|
+
const { url, route } = useLocation();
|
|
1207
880
|
const { locale, availableLocales, setLocale } = useLocale({
|
|
1208
881
|
onLocaleChange: (newLocale) => {
|
|
1209
|
-
const
|
|
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(
|
|
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
|
|
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
|
|
931
|
+
const { url, route } = useLocation();
|
|
1261
932
|
const { locale, availableLocales, setLocale } = useLocale({
|
|
1262
933
|
onLocaleChange: (newLocale) => {
|
|
1263
|
-
const
|
|
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
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
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
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
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`)
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
1139
|
+
Below is the implementation of a localised `Link` component in Preact:
|
|
1472
1140
|
|
|
1473
|
-
```tsx fileName="src/components/
|
|
1141
|
+
```tsx fileName="src/components/Link.tsx" codeFormat="typescript"
|
|
1474
1142
|
import { getLocalizedUrl } from "intlayer";
|
|
1475
|
-
import { useLocale
|
|
1476
|
-
|
|
1477
|
-
import type { JSX } from "preact";
|
|
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
|
|
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
|
|
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
|
|
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
|
|
1499
|
-
({ href, children,
|
|
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}
|
|
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/
|
|
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
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
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
|
-
|
|
1554
|
-
|
|
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
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
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
|
-
|
|
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/
|
|
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
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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`
|
|
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
|
|
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
|
|
1304
|
+
Intlayer uses module augmentation to get the benefits of TypeScript and make your codebase stronger.
|
|
1652
1305
|
|
|
1653
1306
|

|
|
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
|
|
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
|
|