@intlayer/docs 8.6.10 → 8.7.0-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/blog/ar/i18n_using_next-i18next.md +1 -1
- package/blog/ar/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
- package/blog/de/i18n_using_next-i18next.md +1 -1
- package/blog/de/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
- package/blog/en/i18n_using_next-i18next.md +1 -1
- package/blog/en/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
- package/blog/en-GB/i18n_using_next-i18next.md +1 -1
- package/blog/en-GB/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/es/i18n_using_next-i18next.md +1 -1
- package/blog/es/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
- package/blog/fr/i18n_using_next-i18next.md +1 -1
- package/blog/fr/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/hi/i18n_using_next-i18next.md +1 -1
- package/blog/id/i18n_using_next-i18next.md +1 -1
- package/blog/id/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
- package/blog/it/i18n_using_next-i18next.md +1 -1
- package/blog/it/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/ja/i18n_using_next-i18next.md +1 -1
- package/blog/ja/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/ko/i18n_using_next-i18next.md +1 -1
- package/blog/ko/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/pl/i18n_using_next-i18next.md +1 -1
- package/blog/pl/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
- package/blog/pt/i18n_using_next-i18next.md +1 -1
- package/blog/pt/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/ru/i18n_using_next-i18next.md +1 -1
- package/blog/ru/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/blog/tr/i18n_using_next-i18next.md +1 -1
- package/blog/uk/i18n_using_next-i18next.md +1 -1
- package/blog/uk/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
- package/blog/vi/i18n_using_next-i18next.md +1 -1
- package/blog/vi/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
- package/blog/zh/i18n_using_next-i18next.md +1 -1
- package/blog/zh/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
- package/docs/ar/bundle_optimization.md +454 -0
- package/docs/ar/intlayer_with_next-i18next.md +1 -1
- package/docs/ar/intlayer_with_next-intl.md +1 -1
- package/docs/ar/intlayer_with_tanstack+solid.md +24 -5
- package/docs/ar/intlayer_with_tanstack.md +45 -68
- package/docs/bn/bundle_optimization.md +454 -0
- package/docs/cs/bundle_optimization.md +454 -0
- package/docs/de/bundle_optimization.md +454 -0
- package/docs/de/intlayer_with_next-i18next.md +1 -1
- package/docs/de/intlayer_with_next-intl.md +1 -1
- package/docs/de/intlayer_with_tanstack+solid.md +24 -5
- package/docs/de/intlayer_with_tanstack.md +45 -68
- package/docs/en/bundle_optimization.md +36 -8
- package/docs/en/intlayer_with_next-i18next.md +1 -1
- package/docs/en/intlayer_with_next-intl.md +1 -1
- package/docs/en/intlayer_with_tanstack+solid.md +24 -5
- package/docs/en/intlayer_with_tanstack.md +45 -68
- package/docs/en-GB/bundle_optimization.md +454 -0
- package/docs/en-GB/intlayer_with_next-i18next.md +1 -1
- package/docs/en-GB/intlayer_with_next-intl.md +1 -1
- package/docs/en-GB/intlayer_with_tanstack+solid.md +24 -5
- package/docs/en-GB/intlayer_with_tanstack.md +47 -70
- package/docs/es/bundle_optimization.md +454 -0
- package/docs/es/intlayer_with_next-i18next.md +1 -1
- package/docs/es/intlayer_with_next-intl.md +1 -1
- package/docs/es/intlayer_with_tanstack+solid.md +24 -5
- package/docs/es/intlayer_with_tanstack.md +45 -68
- package/docs/fr/bundle_optimization.md +454 -0
- package/docs/fr/intlayer_with_next-i18next.md +1 -1
- package/docs/fr/intlayer_with_next-intl.md +1 -1
- package/docs/fr/intlayer_with_tanstack+solid.md +24 -5
- package/docs/fr/intlayer_with_tanstack.md +45 -68
- package/docs/hi/bundle_optimization.md +454 -0
- package/docs/hi/intlayer_with_next-i18next.md +1 -1
- package/docs/hi/intlayer_with_next-intl.md +1 -1
- package/docs/hi/intlayer_with_tanstack+solid.md +24 -5
- package/docs/hi/intlayer_with_tanstack.md +45 -68
- package/docs/id/bundle_optimization.md +454 -0
- package/docs/id/intlayer_with_next-i18next.md +1 -1
- package/docs/id/intlayer_with_next-intl.md +1 -1
- package/docs/id/intlayer_with_tanstack+solid.md +24 -5
- package/docs/id/intlayer_with_tanstack.md +45 -68
- package/docs/it/bundle_optimization.md +454 -0
- package/docs/it/intlayer_with_next-i18next.md +1 -1
- package/docs/it/intlayer_with_next-intl.md +1 -1
- package/docs/it/intlayer_with_tanstack+solid.md +24 -5
- package/docs/it/intlayer_with_tanstack.md +45 -68
- package/docs/ja/bundle_optimization.md +454 -0
- package/docs/ja/intlayer_with_next-i18next.md +1 -1
- package/docs/ja/intlayer_with_next-intl.md +1 -1
- package/docs/ja/intlayer_with_tanstack+solid.md +24 -5
- package/docs/ja/intlayer_with_tanstack.md +45 -36
- package/docs/ko/bundle_optimization.md +454 -0
- package/docs/ko/intlayer_with_next-i18next.md +1 -1
- package/docs/ko/intlayer_with_next-intl.md +1 -1
- package/docs/ko/intlayer_with_tanstack+solid.md +24 -5
- package/docs/ko/intlayer_with_tanstack.md +45 -68
- package/docs/nl/bundle_optimization.md +454 -0
- package/docs/pl/bundle_optimization.md +454 -0
- package/docs/pl/intlayer_with_next-i18next.md +1 -1
- package/docs/pl/intlayer_with_next-intl.md +1 -1
- package/docs/pl/intlayer_with_tanstack+solid.md +24 -5
- package/docs/pl/intlayer_with_tanstack.md +45 -68
- package/docs/pt/bundle_optimization.md +454 -0
- package/docs/pt/intlayer_with_next-i18next.md +1 -1
- package/docs/pt/intlayer_with_next-intl.md +1 -1
- package/docs/pt/intlayer_with_tanstack+solid.md +24 -5
- package/docs/pt/intlayer_with_tanstack.md +45 -68
- package/docs/ru/bundle_optimization.md +454 -0
- package/docs/ru/intlayer_with_next-i18next.md +1 -1
- package/docs/ru/intlayer_with_next-intl.md +1 -1
- package/docs/ru/intlayer_with_tanstack+solid.md +24 -5
- package/docs/ru/intlayer_with_tanstack.md +45 -68
- package/docs/tr/bundle_optimization.md +454 -0
- package/docs/tr/intlayer_with_next-i18next.md +1 -1
- package/docs/tr/intlayer_with_next-intl.md +1 -1
- package/docs/tr/intlayer_with_tanstack+solid.md +24 -5
- package/docs/tr/intlayer_with_tanstack.md +45 -68
- package/docs/uk/bundle_optimization.md +454 -0
- package/docs/uk/intlayer_with_next-i18next.md +1 -1
- package/docs/uk/intlayer_with_next-intl.md +1 -1
- package/docs/uk/intlayer_with_tanstack+solid.md +24 -5
- package/docs/uk/intlayer_with_tanstack.md +45 -68
- package/docs/ur/bundle_optimization.md +454 -0
- package/docs/vi/bundle_optimization.md +454 -0
- package/docs/vi/intlayer_with_next-i18next.md +1 -1
- package/docs/vi/intlayer_with_next-intl.md +1 -1
- package/docs/vi/intlayer_with_tanstack+solid.md +24 -5
- package/docs/vi/intlayer_with_tanstack.md +45 -68
- package/docs/zh/bundle_optimization.md +454 -0
- package/docs/zh/intlayer_with_next-i18next.md +1 -1
- package/docs/zh/intlayer_with_next-intl.md +1 -1
- package/docs/zh/intlayer_with_tanstack+solid.md +24 -5
- package/docs/zh/intlayer_with_tanstack.md +45 -68
- package/package.json +7 -7
|
@@ -239,7 +239,10 @@ bun add -d @intlayer/babel
|
|
|
239
239
|
```
|
|
240
240
|
|
|
241
241
|
```typescript fileName="babel.config.js"
|
|
242
|
-
const {
|
|
242
|
+
const {
|
|
243
|
+
getOptimizePluginOptions,
|
|
244
|
+
intlayerOptimizeBabelPlugin,
|
|
245
|
+
} = require("@intlayer/babel");
|
|
243
246
|
|
|
244
247
|
module.exports = {
|
|
245
248
|
plugins: [[intlayerOptimizeBabelPlugin, getOptimizePluginOptions()]],
|
|
@@ -337,7 +340,9 @@ export default config;
|
|
|
337
340
|
|
|
338
341
|
### Import Mode
|
|
339
342
|
|
|
340
|
-
For large applications, including several pages and locales, your JSON can represent a significant part of your bundle size. Intlayer allows you to control how dictionaries are loaded.
|
|
343
|
+
For large applications, including several pages and locales, your JSON can represent a significant part of your bundle size. Intlayer allows you to control how dictionaries are loaded using the `importMode` option.
|
|
344
|
+
|
|
345
|
+
### Global definition
|
|
341
346
|
|
|
342
347
|
The import mode can be defined by default globally in your `intlayer.config.ts` file.
|
|
343
348
|
|
|
@@ -345,14 +350,16 @@ The import mode can be defined by default globally in your `intlayer.config.ts`
|
|
|
345
350
|
import type { IntlayerConfig } from "intlayer";
|
|
346
351
|
|
|
347
352
|
const config: IntlayerConfig = {
|
|
348
|
-
|
|
349
|
-
|
|
353
|
+
dictionary: {
|
|
354
|
+
importMode: "dynamic", // Default is 'static'
|
|
350
355
|
},
|
|
351
356
|
};
|
|
352
357
|
|
|
353
358
|
export default config;
|
|
354
359
|
```
|
|
355
360
|
|
|
361
|
+
### Per dictionary fine-grained definition
|
|
362
|
+
|
|
356
363
|
As well as for each dictionaries in your `.content.{{ts|tsx|js|jsx|mjs|cjs|json|jsonc|json5}}` files.
|
|
357
364
|
|
|
358
365
|
```ts
|
|
@@ -390,7 +397,8 @@ In static mode, Intlayer replaces `useIntlayer` with `useDictionary` and injects
|
|
|
390
397
|
// Your code
|
|
391
398
|
const content = useIntlayer("my-key");
|
|
392
399
|
|
|
393
|
-
// Optimized code (Static)
|
|
400
|
+
// Optimized code illustration after transformation (Static)
|
|
401
|
+
// This is only for illustration purposes, the actual code will be different for optimization reasons
|
|
394
402
|
const content = useDictionary({
|
|
395
403
|
key: "my-key",
|
|
396
404
|
content: {
|
|
@@ -417,7 +425,8 @@ In dynamic mode, Intlayer replaces `useIntlayer` with `useDictionaryAsync`. This
|
|
|
417
425
|
// Your code
|
|
418
426
|
const content = useIntlayer("my-key");
|
|
419
427
|
|
|
420
|
-
// Optimized code (Dynamic)
|
|
428
|
+
// Optimized code illustration after transformation (Dynamic)
|
|
429
|
+
// This is only for illustration purposes, the actual code will be different for optimization reasons
|
|
421
430
|
const content = useDictionaryAsync({
|
|
422
431
|
en: () =>
|
|
423
432
|
import(".intlayer/dynamic_dictionary/my-key/en.json").then(
|
|
@@ -430,12 +439,31 @@ const content = useDictionaryAsync({
|
|
|
430
439
|
});
|
|
431
440
|
```
|
|
432
441
|
|
|
433
|
-
> When using `importMode: 'dynamic'`, if you have 100 components using `useIntlayer` on a single page, the browser will attempt 100 separate fetches. To avoid this "waterfall" of requests, group content into fewer `.content` files (e.g., one dictionary per page section) rather than one per atom component.
|
|
442
|
+
> When using `importMode: 'dynamic'`, if you have 100 components using `useIntlayer` on a single page, the browser will attempt 100 separate fetches. To avoid this "waterfall" of requests, group content into fewer `.content` files (e.g., one dictionary per page section) rather than one per atom component. You can also use multiple `.content` files using the same key. Intlayer will merge them into a single dictionary.
|
|
434
443
|
|
|
435
444
|
### 3. Fetch Mode
|
|
436
445
|
|
|
437
446
|
Behaves similarly to Dynamic mode but attempts to fetch dictionaries from the Intlayer Live Sync API first. If the API call fails or the content is not marked for live updates, it falls back to the dynamic import.
|
|
438
447
|
|
|
448
|
+
**Transformed Code Example:**
|
|
449
|
+
|
|
450
|
+
```tsx
|
|
451
|
+
// Your code
|
|
452
|
+
const content = useIntlayer("my-key");
|
|
453
|
+
|
|
454
|
+
// Optimized code illustration (Fetch)
|
|
455
|
+
const content = useDictionaryAsync({
|
|
456
|
+
en: () =>
|
|
457
|
+
fetch("https://intlayer.my-domain.com/dictionary/my-key/en").then((res) =>
|
|
458
|
+
res.json()
|
|
459
|
+
),
|
|
460
|
+
fr: () =>
|
|
461
|
+
fetch("https://intlayer.my-domain.com/dictionary/my-key/fr").then((res) =>
|
|
462
|
+
res.json()
|
|
463
|
+
),
|
|
464
|
+
});
|
|
465
|
+
```
|
|
466
|
+
|
|
439
467
|
> See CMS documentation for more details: [CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_CMS.md)
|
|
440
468
|
|
|
441
469
|
> In fetch mode, purge and minification can't be used.
|
|
@@ -446,6 +474,6 @@ Behaves similarly to Dynamic mode but attempts to fetch dictionaries from the In
|
|
|
446
474
|
| :------------------- | :-------------------------------------------- | :----------------------------------- |
|
|
447
475
|
| **JS Bundle Size** | Larger (includes all langs for the component) | Smallest (only code, no content) |
|
|
448
476
|
| **Initial Load** | Instant (Content is in bundle) | Slight delay (Fetches JSON) |
|
|
449
|
-
| **Network Requests** | 0 extra requests | 1 request per dictionary
|
|
477
|
+
| **Network Requests** | 0 extra requests | 1 request per dictionary key |
|
|
450
478
|
| **Tree Shaking** | Component-level | Component-level + Locale-level |
|
|
451
479
|
| **Best Use Case** | UI Components, Small Apps | Pages with much text, Many Languages |
|
|
@@ -256,7 +256,7 @@ export default function LocaleLayout({
|
|
|
256
256
|
params: { locale: string };
|
|
257
257
|
}) {
|
|
258
258
|
const locale: Locale = (locales as readonly string[]).includes(params.locale)
|
|
259
|
-
?
|
|
259
|
+
? params.locale
|
|
260
260
|
: defaultLocale;
|
|
261
261
|
|
|
262
262
|
const dir = isRtl(locale) ? "rtl" : "ltr";
|
|
@@ -103,7 +103,7 @@ async function loadMessages(locale: string) {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
export default getRequestConfig(async ({ locale }) => {
|
|
106
|
-
if (!locales.includes(locale
|
|
106
|
+
if (!locales.includes(locale)) notFound();
|
|
107
107
|
|
|
108
108
|
return {
|
|
109
109
|
messages: await loadMessages(locale),
|
|
@@ -197,9 +197,7 @@ const RootComponent: ParentComponent = (props) => {
|
|
|
197
197
|
</head>
|
|
198
198
|
<body>
|
|
199
199
|
<IntlayerProvider locale={locale}>
|
|
200
|
-
<Suspense>
|
|
201
|
-
{props.children}
|
|
202
|
-
</Suspense>
|
|
200
|
+
<Suspense>{props.children}</Suspense>
|
|
203
201
|
</IntlayerProvider>
|
|
204
202
|
<Scripts />
|
|
205
203
|
</body>
|
|
@@ -509,12 +507,33 @@ export const Route = createFileRoute("/{-$locale}/")({
|
|
|
509
507
|
component: RouteComponent,
|
|
510
508
|
head: ({ params }) => {
|
|
511
509
|
const { locale } = params;
|
|
512
|
-
const
|
|
510
|
+
const path = "/"; // The path for this route
|
|
511
|
+
|
|
512
|
+
const metaContent = getIntlayer("app", locale);
|
|
513
513
|
|
|
514
514
|
return {
|
|
515
|
+
links: [
|
|
516
|
+
// Canonical link: Points to the current localized page
|
|
517
|
+
{ rel: "canonical", href: getLocalizedUrl(path, locale) },
|
|
518
|
+
|
|
519
|
+
// Hreflang: Tell Google about all localized versions
|
|
520
|
+
...localeMap(({ locale: mapLocale }) => ({
|
|
521
|
+
rel: "alternate",
|
|
522
|
+
hrefLang: mapLocale,
|
|
523
|
+
href: getLocalizedUrl(path, mapLocale),
|
|
524
|
+
})),
|
|
525
|
+
|
|
526
|
+
// x-default: For users in unmatched languages
|
|
527
|
+
// Define the default fallback locale (usually your primary language)
|
|
528
|
+
{
|
|
529
|
+
rel: "alternate",
|
|
530
|
+
hrefLang: "x-default",
|
|
531
|
+
href: getLocalizedUrl(path, defaultLocale),
|
|
532
|
+
},
|
|
533
|
+
],
|
|
515
534
|
meta: [
|
|
516
535
|
{ title: metaContent.title },
|
|
517
|
-
{
|
|
536
|
+
{ name: "description", content: metaContent.meta.description },
|
|
518
537
|
],
|
|
519
538
|
};
|
|
520
539
|
},
|
|
@@ -228,9 +228,7 @@ function RootDocument({ children }: { children: ReactNode }) {
|
|
|
228
228
|
<HeadContent />
|
|
229
229
|
</head>
|
|
230
230
|
<body>
|
|
231
|
-
<IntlayerProvider locale={locale}>
|
|
232
|
-
{children}
|
|
233
|
-
</IntlayerProvider>
|
|
231
|
+
<IntlayerProvider locale={locale}>{children}</IntlayerProvider>
|
|
234
232
|
<Scripts />
|
|
235
233
|
</body>
|
|
236
234
|
</html>
|
|
@@ -329,30 +327,20 @@ import { getPrefix } from "intlayer";
|
|
|
329
327
|
|
|
330
328
|
export const LOCALE_ROUTE = "{-$locale}" as const;
|
|
331
329
|
|
|
332
|
-
|
|
333
|
-
export type RemoveLocaleParam<T> = T extends string
|
|
334
|
-
? RemoveLocaleFromString<T>
|
|
335
|
-
: T;
|
|
330
|
+
export type To = StripLocalePrefix<LinkComponentProps["to"]>;
|
|
336
331
|
|
|
337
|
-
export type
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
332
|
+
export type StripLocalePrefix<T extends string | undefined> = T extends
|
|
333
|
+
| `/${typeof LOCALE_ROUTE}/`
|
|
334
|
+
| `/${typeof LOCALE_ROUTE}`
|
|
335
|
+
? "/"
|
|
336
|
+
: T extends `/${typeof LOCALE_ROUTE}/${infer Rest}`
|
|
337
|
+
? `/${Rest}`
|
|
338
|
+
: T;
|
|
341
339
|
|
|
342
340
|
type LocalizedLinkProps = {
|
|
343
341
|
to?: To;
|
|
344
342
|
} & Omit<LinkComponentProps, "to">;
|
|
345
343
|
|
|
346
|
-
// Helpers
|
|
347
|
-
type RemoveAll<
|
|
348
|
-
S extends string,
|
|
349
|
-
Sub extends string,
|
|
350
|
-
> = S extends `${infer H}${Sub}${infer T}` ? RemoveAll<`${H}${T}`, Sub> : S;
|
|
351
|
-
|
|
352
|
-
type RemoveLocaleFromString<S extends string> = CollapseDoubleSlashes<
|
|
353
|
-
RemoveAll<S, typeof LOCALE_ROUTE>
|
|
354
|
-
>;
|
|
355
|
-
|
|
356
344
|
export const LocalizedLink: FC<LocalizedLinkProps> = (props) => {
|
|
357
345
|
const { locale } = useLocale();
|
|
358
346
|
const { localePrefix } = getPrefix(locale);
|
|
@@ -381,26 +369,26 @@ Then we can create a `useLocalizedNavigate` hook for programmatic navigation:
|
|
|
381
369
|
import { useNavigate } from "@tanstack/react-router";
|
|
382
370
|
import { getPrefix } from "intlayer";
|
|
383
371
|
import { useLocale } from "react-intlayer";
|
|
384
|
-
import {
|
|
372
|
+
import type { StripLocalePrefix } from "@/components/localized-link";
|
|
385
373
|
import type { FileRouteTypes } from "@/routeTree.gen";
|
|
386
374
|
|
|
387
|
-
type
|
|
388
|
-
|
|
389
|
-
| `/${typeof LOCALE_ROUTE}/`
|
|
390
|
-
? "/"
|
|
391
|
-
: T extends `/${typeof LOCALE_ROUTE}/${infer Rest}`
|
|
392
|
-
? `/${Rest}`
|
|
393
|
-
: never;
|
|
375
|
+
type NavigateFn = ReturnType<typeof useNavigate>;
|
|
376
|
+
type BaseNavigateOptions = Parameters<NavigateFn>[0];
|
|
394
377
|
|
|
395
378
|
type LocalizedTo = StripLocalePrefix<FileRouteTypes["to"]>;
|
|
396
379
|
|
|
397
|
-
type
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
380
|
+
export type LocalizedNavigateOptions = Omit<
|
|
381
|
+
BaseNavigateOptions,
|
|
382
|
+
"to" | "params"
|
|
383
|
+
> & {
|
|
384
|
+
to: LocalizedTo;
|
|
385
|
+
params?: Omit<NonNullable<BaseNavigateOptions["params"]>, "locale">;
|
|
402
386
|
};
|
|
403
387
|
|
|
388
|
+
type LocalizedNavigate = (
|
|
389
|
+
options: LocalizedNavigateOptions
|
|
390
|
+
) => ReturnType<NavigateFn>;
|
|
391
|
+
|
|
404
392
|
export const useLocalizedNavigate = () => {
|
|
405
393
|
const navigate = useNavigate();
|
|
406
394
|
|
|
@@ -447,38 +435,6 @@ import { useLocalizedNavigate } from "@/hooks/useLocalizedNavigate";
|
|
|
447
435
|
|
|
448
436
|
export const Route = createFileRoute("/{-$locale}/")({
|
|
449
437
|
component: RouteComponent,
|
|
450
|
-
head: ({ params }) => {
|
|
451
|
-
const { locale } = params;
|
|
452
|
-
const path = "/"; // The path for this route
|
|
453
|
-
|
|
454
|
-
const metaContent = getIntlayer("app", locale);
|
|
455
|
-
|
|
456
|
-
return {
|
|
457
|
-
links: [
|
|
458
|
-
// Canonical link: Points to the current localized page
|
|
459
|
-
{ rel: "canonical", href: getLocalizedUrl(path, locale) },
|
|
460
|
-
|
|
461
|
-
// Hreflang: Tell Google about all localized versions
|
|
462
|
-
...localeMap(({ locale: mapLocale }) => ({
|
|
463
|
-
rel: "alternate",
|
|
464
|
-
hrefLang: mapLocale,
|
|
465
|
-
href: getLocalizedUrl(path, mapLocale),
|
|
466
|
-
})),
|
|
467
|
-
|
|
468
|
-
// x-default: For users in unmatched languages
|
|
469
|
-
// Define the default fallback locale (usually your primary language)
|
|
470
|
-
{
|
|
471
|
-
rel: "alternate",
|
|
472
|
-
hrefLang: "x-default",
|
|
473
|
-
href: getLocalizedUrl(path, defaultLocale),
|
|
474
|
-
},
|
|
475
|
-
],
|
|
476
|
-
meta: [
|
|
477
|
-
{ title: metaContent.title },
|
|
478
|
-
{ name: "description", content: metaContent.meta.description },
|
|
479
|
-
],
|
|
480
|
-
};
|
|
481
|
-
},
|
|
482
438
|
});
|
|
483
439
|
|
|
484
440
|
function RouteComponent() {
|
|
@@ -633,12 +589,33 @@ export const Route = createFileRoute("/{-$locale}/")({
|
|
|
633
589
|
component: RouteComponent,
|
|
634
590
|
head: ({ params }) => {
|
|
635
591
|
const { locale } = params;
|
|
636
|
-
const
|
|
592
|
+
const path = "/"; // The path for this route
|
|
593
|
+
|
|
594
|
+
const metaContent = getIntlayer("app", locale);
|
|
637
595
|
|
|
638
596
|
return {
|
|
597
|
+
links: [
|
|
598
|
+
// Canonical link: Points to the current localized page
|
|
599
|
+
{ rel: "canonical", href: getLocalizedUrl(path, locale) },
|
|
600
|
+
|
|
601
|
+
// Hreflang: Tell Google about all localized versions
|
|
602
|
+
...localeMap(({ locale: mapLocale }) => ({
|
|
603
|
+
rel: "alternate",
|
|
604
|
+
hrefLang: mapLocale,
|
|
605
|
+
href: getLocalizedUrl(path, mapLocale),
|
|
606
|
+
})),
|
|
607
|
+
|
|
608
|
+
// x-default: For users in unmatched languages
|
|
609
|
+
// Define the default fallback locale (usually your primary language)
|
|
610
|
+
{
|
|
611
|
+
rel: "alternate",
|
|
612
|
+
hrefLang: "x-default",
|
|
613
|
+
href: getLocalizedUrl(path, defaultLocale),
|
|
614
|
+
},
|
|
615
|
+
],
|
|
639
616
|
meta: [
|
|
640
617
|
{ title: metaContent.title },
|
|
641
|
-
{
|
|
618
|
+
{ name: "description", content: metaContent.meta.description },
|
|
642
619
|
],
|
|
643
620
|
};
|
|
644
621
|
},
|