@intlayer/docs 7.3.11 → 7.3.13

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 (90) hide show
  1. package/dist/cjs/generated/docs.entry.cjs +19 -0
  2. package/dist/cjs/generated/docs.entry.cjs.map +1 -1
  3. package/dist/esm/generated/docs.entry.mjs +19 -0
  4. package/dist/esm/generated/docs.entry.mjs.map +1 -1
  5. package/dist/types/generated/docs.entry.d.ts +1 -0
  6. package/dist/types/generated/docs.entry.d.ts.map +1 -1
  7. package/docs/ar/intlayer_with_nuxt.md +294 -438
  8. package/docs/ar/intlayer_with_react_router_v7.md +33 -4
  9. package/docs/ar/intlayer_with_react_router_v7_fs_routes.md +516 -0
  10. package/docs/ar/intlayer_with_tanstack.md +2 -12
  11. package/docs/ar/intlayer_with_vite+vue.md +1 -0
  12. package/docs/de/intlayer_with_nuxt.md +284 -410
  13. package/docs/de/intlayer_with_react_router_v7.md +33 -4
  14. package/docs/de/intlayer_with_react_router_v7_fs_routes.md +573 -0
  15. package/docs/de/intlayer_with_tanstack.md +1 -0
  16. package/docs/de/intlayer_with_vite+vue.md +1 -0
  17. package/docs/en/intlayer_with_nuxt.md +237 -341
  18. package/docs/en/intlayer_with_react_router_v7.md +24 -0
  19. package/docs/en/intlayer_with_react_router_v7_fs_routes.md +570 -0
  20. package/docs/en/intlayer_with_tanstack.md +2 -12
  21. package/docs/en/intlayer_with_vite+vue.md +49 -48
  22. package/docs/en-GB/intlayer_with_nuxt.md +254 -378
  23. package/docs/en-GB/intlayer_with_react_router_v7.md +33 -4
  24. package/docs/en-GB/intlayer_with_react_router_v7_fs_routes.md +513 -0
  25. package/docs/en-GB/intlayer_with_tanstack.md +2 -12
  26. package/docs/en-GB/intlayer_with_vite+vue.md +1 -0
  27. package/docs/es/intlayer_with_nuxt.md +271 -390
  28. package/docs/es/intlayer_with_react_router_v7.md +33 -4
  29. package/docs/es/intlayer_with_react_router_v7_fs_routes.md +575 -0
  30. package/docs/es/intlayer_with_tanstack.md +1 -0
  31. package/docs/es/intlayer_with_vite+vue.md +1 -2
  32. package/docs/fr/intlayer_with_nuxt.md +278 -405
  33. package/docs/fr/intlayer_with_react_router_v7.md +34 -5
  34. package/docs/fr/intlayer_with_react_router_v7_fs_routes.md +574 -0
  35. package/docs/fr/intlayer_with_tanstack.md +1 -0
  36. package/docs/fr/intlayer_with_vite+vue.md +1 -0
  37. package/docs/hi/intlayer_with_nuxt.md +303 -447
  38. package/docs/hi/intlayer_with_react_router_v7.md +33 -4
  39. package/docs/hi/intlayer_with_react_router_v7_fs_routes.md +518 -0
  40. package/docs/hi/intlayer_with_tanstack.md +2 -12
  41. package/docs/hi/intlayer_with_vite+vue.md +1 -0
  42. package/docs/id/intlayer_with_nuxt.md +266 -395
  43. package/docs/id/intlayer_with_react_router_v7.md +29 -4
  44. package/docs/id/intlayer_with_react_router_v7_fs_routes.md +521 -0
  45. package/docs/id/intlayer_with_tanstack.md +2 -12
  46. package/docs/id/intlayer_with_vite+vue.md +1 -0
  47. package/docs/it/intlayer_with_nuxt.md +299 -423
  48. package/docs/it/intlayer_with_react_router_v7.md +33 -4
  49. package/docs/it/intlayer_with_react_router_v7_fs_routes.md +574 -0
  50. package/docs/it/intlayer_with_tanstack.md +1 -0
  51. package/docs/ja/intlayer_with_nuxt.md +309 -432
  52. package/docs/ja/intlayer_with_react_router_v7.md +33 -4
  53. package/docs/ja/intlayer_with_react_router_v7_fs_routes.md +574 -0
  54. package/docs/ja/intlayer_with_tanstack.md +2 -12
  55. package/docs/ja/intlayer_with_vite+vue.md +1 -0
  56. package/docs/ko/intlayer_with_nuxt.md +295 -422
  57. package/docs/ko/intlayer_with_react_router_v7.md +33 -4
  58. package/docs/ko/intlayer_with_react_router_v7_fs_routes.md +515 -0
  59. package/docs/ko/intlayer_with_tanstack.md +2 -12
  60. package/docs/ko/intlayer_with_vite+vue.md +1 -0
  61. package/docs/pl/intlayer_with_nuxt.md +273 -476
  62. package/docs/pl/intlayer_with_react_router_v7.md +32 -5
  63. package/docs/pl/intlayer_with_react_router_v7_fs_routes.md +615 -0
  64. package/docs/pl/intlayer_with_tanstack.md +2 -12
  65. package/docs/pl/intlayer_with_vite+vue.md +1 -0
  66. package/docs/pt/intlayer_with_nuxt.md +277 -420
  67. package/docs/pt/intlayer_with_react_router_v7.md +28 -0
  68. package/docs/pt/intlayer_with_tanstack.md +1 -0
  69. package/docs/ru/intlayer_with_nuxt.md +287 -425
  70. package/docs/ru/intlayer_with_react_router_v7.md +33 -4
  71. package/docs/ru/intlayer_with_react_router_v7_fs_routes.md +574 -0
  72. package/docs/ru/intlayer_with_tanstack.md +1 -0
  73. package/docs/ru/intlayer_with_vite+vue.md +1 -0
  74. package/docs/tr/intlayer_with_nuxt.md +313 -406
  75. package/docs/tr/intlayer_with_react_router_v7.md +33 -4
  76. package/docs/tr/intlayer_with_react_router_v7_fs_routes.md +572 -0
  77. package/docs/tr/intlayer_with_tanstack.md +2 -12
  78. package/docs/tr/intlayer_with_vite+vue.md +1 -0
  79. package/docs/vi/intlayer_with_nuxt.md +273 -418
  80. package/docs/vi/intlayer_with_react_router_v7.md +29 -4
  81. package/docs/vi/intlayer_with_react_router_v7_fs_routes.md +523 -0
  82. package/docs/vi/intlayer_with_tanstack.md +2 -12
  83. package/docs/vi/intlayer_with_vite+vue.md +1 -0
  84. package/docs/zh/intlayer_with_nuxt.md +300 -461
  85. package/docs/zh/intlayer_with_react_router_v7.md +33 -4
  86. package/docs/zh/intlayer_with_react_router_v7_fs_routes.md +516 -0
  87. package/docs/zh/intlayer_with_tanstack.md +2 -12
  88. package/docs/zh/intlayer_with_vite+vue.md +1 -0
  89. package/package.json +10 -11
  90. package/src/generated/docs.entry.ts +19 -0
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  createdAt: 2025-06-18
3
- updatedAt: 2025-06-29
3
+ updatedAt: 2025-12-07
4
4
  title: How to translate your Nuxt and Vue app – i18n guide 2025
5
5
  description: Discover how to make your Nuxt and Vue website multilingual. Follow the documentation to internationalize (i18n) and translate it.
6
6
  keywords:
@@ -14,8 +14,15 @@ slugs:
14
14
  - doc
15
15
  - environment
16
16
  - nuxt-and-vue
17
- applicationTemplate: https://github.com/aymericzip/intlayer-nuxt-template
17
+ applicationTemplate: https://github.com/aymericzip/intlayer-nuxt-4-template
18
+ youtubeVideo: https://www.youtube.com/watch?v=nhUcUAVQ6eQ
18
19
  history:
20
+ - version: 7.3.13
21
+ date: 2025-12-08
22
+ changes: Unused TypeScript configuration
23
+ - version: 7.3.11
24
+ date: 2025-12-07
25
+ changes: Update LocaleSwitcher, SEO, metadata
19
26
  - version: 5.5.10
20
27
  date: 2025-06-29
21
28
  changes: Init history
@@ -23,8 +30,6 @@ history:
23
30
 
24
31
  # Translate your Nuxt and Vue website using Intlayer | Internationalization (i18n)
25
32
 
26
- See [Application Template](https://github.com/aymericzip/intlayer-nuxt-template) on GitHub.
27
-
28
33
  ## Table of Contents
29
34
 
30
35
  <TOC/>
@@ -44,14 +49,27 @@ With Intlayer, you can:
44
49
 
45
50
  ## Step-by-Step Guide to Set Up Intlayer in a Nuxt Application
46
51
 
52
+ <Tab defaultTab="video">
53
+ <TabItem label="Video" value="video">
54
+
55
+ <iframe title="How to translate your Nuxt and Vue app using Intlayer? Discover Intlayer" class="m-auto aspect-[16/9] w-full overflow-hidden rounded-lg border-0" allow="autoplay; gyroscope;" loading="lazy" width="1080" height="auto" src="https://www.youtube.com/embed/nhUcUAVQ6eQ?autoplay=0&amp;origin=http://intlayer.org&amp;controls=0&amp;rel=1"/>
56
+
57
+ </TabItem>
58
+ <TabItem label="Code" value="code">
59
+
47
60
  <iframe
48
- src="https://stackblitz.com/github/aymericzip/intlayer-nuxt-template?embed=1&ctl=1&file=intlayer.config.ts"
61
+ src="https://stackblitz.com/github/aymericzip/intlayer-nuxt-4-template?embed=1&ctl=1&file=intlayer.config.ts"
49
62
  className="m-auto overflow-hidden rounded-lg border-0 max-md:size-full max-md:h-[700px] md:aspect-16/9 md:w-full"
50
63
  title="Demo CodeSandbox - How to Internationalize your application using Intlayer"
51
64
  sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
52
65
  loading="lazy"
53
66
  />
54
67
 
68
+ </TabItem>
69
+ </Tab>
70
+
71
+ See [Application Template](https://github.com/aymericzip/intlayer-nuxt-4-template) on GitHub.
72
+
55
73
  ### Step 1: Install Dependencies
56
74
 
57
75
  Install the necessary packages using npm:
@@ -98,9 +116,6 @@ const config: IntlayerConfig = {
98
116
  ],
99
117
  defaultLocale: Locales.ENGLISH,
100
118
  },
101
- content: {
102
- contentDir: ["."], // Because by default Intayer will watch content declaration files from the `./src` directory
103
- },
104
119
  };
105
120
 
106
121
  export default config;
@@ -120,9 +135,6 @@ const config = {
120
135
  ],
121
136
  defaultLocale: Locales.ENGLISH,
122
137
  },
123
- content: {
124
- contentDir: ["."],
125
- },
126
138
  };
127
139
 
128
140
  export default config;
@@ -142,9 +154,6 @@ const config = {
142
154
  ],
143
155
  defaultLocale: Locales.ENGLISH,
144
156
  },
145
- content: {
146
- contentDir: ["."],
147
- },
148
157
  };
149
158
 
150
159
  module.exports = config;
@@ -171,188 +180,31 @@ export default defineNuxtConfig({
171
180
 
172
181
  Create and manage your content declarations to store translations:
173
182
 
174
- ```tsx fileName="components/helloWorld.content.ts" contentDeclarationFormat="typescript"
175
- import { t, type Dictionary } from "intlayer";
183
+ ```tsx fileName="content/home-page.content.ts" contentDeclarationFormat="typescript"
184
+ import { type Dictionary, t } from "intlayer";
176
185
 
177
- const helloWorldContent = {
178
- key: "helloworld",
186
+ const content = {
187
+ key: "home-page",
179
188
  content: {
180
- count: t({ en: "count is ", fr: "le compte est ", es: "el recuento es " }),
181
- edit: t({
182
- en: "Edit <code>components/HelloWorld.vue</code> and save to test HMR",
183
- fr: "Éditez <code>components/HelloWorld.vue</code> et enregistrez pour tester HMR",
184
- es: "Edita <code>components/HelloWorld.vue</code> y guarda para probar HMR",
185
- }),
186
- checkOut: t({ en: "Check out ", fr: "Vérifiez ", es: "Compruebe " }),
187
- nuxtIntlayer: t({
188
- en: "Nuxt Intlayer documentation",
189
- fr: "Documentation de Nuxt Intlayer",
190
- es: "Documentación de Nuxt Intlayer",
191
- }),
192
- learnMore: t({
193
- en: "Learn more about Nuxt in the ",
194
- fr: "En savoir plus sur Nuxt dans la ",
195
- es: "Aprenda más sobre Nuxt en la ",
189
+ title: t({
190
+ en: "Hello world",
191
+ fr: "Bonjour le monde",
192
+ es: "Hola mundo",
196
193
  }),
197
- nuxtDocs: t({
198
- en: "Nuxt Documentation",
199
- fr: "Documentation Nuxt",
200
- es: "Documentación de Nuxt",
194
+ metaTitle: t({
195
+ en: "Welcome | My Application",
196
+ fr: "Bienvenue | Mon Application",
197
+ es: "Bienvenido | Mi Aplicación",
201
198
  }),
202
- readTheDocs: t({
203
- en: "Click on the Nuxt logo to learn more",
204
- fr: "Cliquez sur le logo Nuxt pour en savoir plus",
205
- es: "Haga clic en el logotipo de Nuxt para obtener más información",
199
+ metaDescription: t({
200
+ en: "Discover your multilingual Nuxt app homepage powered by Intlayer.",
201
+ fr: "Découvrez la page d'accueil multilingue de votre application Nuxt propulsée par Intlayer.",
202
+ es: "Descubre la página de inicio multilingüe de tu aplicación Nuxt impulsada por Intlayer.",
206
203
  }),
207
204
  },
208
205
  } satisfies Dictionary;
209
206
 
210
- export default helloWorldContent;
211
- ```
212
-
213
- ```javascript fileName="components/helloWorld.content.mjs" contentDeclarationFormat="esm"
214
- import { t } from "intlayer";
215
-
216
- /** @type {import('intlayer').Dictionary} */
217
- const helloWorldContent = {
218
- key: "helloworld",
219
- content: {
220
- count: t({ en: "count is ", fr: "le compte est ", es: "el recuento es " }),
221
- edit: t({
222
- en: "Edit <code>components/HelloWorld.vue</code> and save to test HMR",
223
- fr: "Éditez <code>components/HelloWorld.vue</code> et enregistrez pour tester HMR",
224
- es: "Edita <code>components/HelloWorld.vue</code> y guarda para probar HMR",
225
- }),
226
- checkOut: t({ en: "Check out ", fr: "Vérifiez ", es: "Compruebe " }),
227
- nuxtIntlayer: t({
228
- en: "Nuxt Intlayer documentation",
229
- fr: "Documentation de Nuxt Intlayer",
230
- es: "Documentación de Nuxt Intlayer",
231
- }),
232
- learnMore: t({
233
- en: "Learn more about Nuxt in the ",
234
- fr: "En savoir plus sur Nuxt dans la ",
235
- es: "Aprenda más sobre Nuxt en la ",
236
- }),
237
- nuxtDocs: t({
238
- en: "Nuxt Documentation",
239
- fr: "Documentation Nuxt",
240
- es: "Documentación de Nuxt",
241
- }),
242
- readTheDocs: t({
243
- en: "Click on the Nuxt logo to learn more",
244
- fr: "Cliquez sur le logo Nuxt pour en savoir plus",
245
- es: "Haga clic en el logotipo de Nuxt para obtener más información",
246
- }),
247
- },
248
- };
249
-
250
- export default helloWorldContent;
251
- ```
252
-
253
- ```javascript fileName="components/helloWorld.content.cjs" contentDeclarationFormat="commonjs"
254
- const { t } = require("intlayer");
255
-
256
- /** @type {import('intlayer').Dictionary} */
257
- const helloWorldContent = {
258
- key: "helloworld",
259
- content: {
260
- count: t({ en: "count is ", fr: "le compte est ", es: "el recuento es " }),
261
- edit: t({
262
- en: "Edit <code>components/HelloWorld.vue</code> and save to test HMR",
263
- fr: "Éditez <code>components/HelloWorld.vue</code> et enregistrez pour tester HMR",
264
- es: "Edita <code>components/HelloWorld.vue</code> y guarda para probar HMR",
265
- }),
266
- checkOut: t({ en: "Check out ", fr: "Vérifiez ", es: "Compruebe " }),
267
- nuxtIntlayer: t({
268
- en: "Nuxt Intlayer documentation",
269
- fr: "Documentation de Nuxt Intlayer",
270
- es: "Documentación de Nuxt Intlayer",
271
- }),
272
- learnMore: t({
273
- en: "Learn more about Nuxt in the ",
274
- fr: "En savoir plus sur Nuxt dans la ",
275
- es: "Aprenda más sobre Nuxt en la ",
276
- }),
277
- nuxtDocs: t({
278
- en: "Nuxt Documentation",
279
- fr: "Documentation Nuxt",
280
- es: "Documentación de Nuxt",
281
- }),
282
- readTheDocs: t({
283
- en: "Click on the Nuxt logo to learn more",
284
- fr: "Cliquez sur le logo Nuxt pour en savoir plus",
285
- es: "Haga clic en el logotipo de Nuxt para obtener más información",
286
- }),
287
- },
288
- };
289
-
290
- module.exports = helloWorldContent;
291
- ```
292
-
293
- ```json fileName="components/helloWorld.content.json" contentDeclarationFormat="json"
294
- {
295
- "$schema": "https://intlayer.org/schema.json",
296
- "key": "helloworld",
297
- "content": {
298
- "count": {
299
- "nodeType": "translation",
300
- "translation": {
301
- "en": "count is ",
302
- "fr": "le compte est ",
303
- "es": "el recuento es "
304
- }
305
- },
306
- "edit": {
307
- "nodeType": "translation",
308
- "translation": {
309
- "en": "Edit <code>components/HelloWorld.vue</code> and save to test HMR",
310
- "fr": "Éditez <code>components/HelloWorld.vue</code> et enregistrez pour tester HMR",
311
- "es": "Edita <code>components/HelloWorld.vue</code> y guarda para probar HMR"
312
- }
313
- },
314
- "checkOut": {
315
- "nodeType": "translation",
316
- "translation": {
317
- "en": "Check out ",
318
- "fr": "Vérifiez ",
319
- "es": "Compruebe "
320
- }
321
- },
322
- "nuxtIntlayer": {
323
- "nodeType": "translation",
324
- "translation": {
325
- "en": "Nuxt Intlayer documentation",
326
- "fr": "Documentation de Nuxt Intlayer",
327
- "es": "Documentación de Nuxt Intlayer"
328
- }
329
- },
330
- "learnMore": {
331
- "nodeType": "translation",
332
- "translation": {
333
- "en": "Learn more about Nuxt in the ",
334
- "fr": "En savoir plus sur Nuxt dans la ",
335
- "es": "Aprenda más sobre Nuxt en la "
336
- }
337
- },
338
- "nuxtDocs": {
339
- "nodeType": "translation",
340
- "translation": {
341
- "en": "Nuxt Documentation",
342
- "fr": "Documentation Nuxt",
343
- "es": "Documentación de Nuxt"
344
- }
345
- },
346
- "readTheDocs": {
347
- "nodeType": "translation",
348
- "translation": {
349
- "en": "Click on the Nuxt logo to learn more",
350
- "fr": "Cliquez sur le logo Nuxt pour en savoir plus",
351
- "es": "Haga clic en el logotipo de Nuxt para obtener más información"
352
- }
353
- }
354
- }
355
- }
207
+ export default content;
356
208
  ```
357
209
 
358
210
  > Your content declarations can be defined anywhere in your application as long as they are included in the `contentDir` directory (by default, `./src`). And match the content declaration file extension (by default, `.content.{json,ts,tsx,js,jsx,mjs,mjx,cjs,cjx}`).
@@ -432,64 +284,54 @@ Intlayer offers different APIs to access your content:
432
284
 
433
285
  To change the language of your content, you can use the `setLocale` function provided by the `useLocale` composable. This function allows you to set the locale of the application and update the content accordingly.
434
286
 
435
- Create a component to switch between languages:
287
+ Create a component to switch between languages using `NuxtLink`. **Using links instead of buttons for locale switching is a best practice for SEO and page discoverability**, as it allows search engines to crawl and index all localized versions of your pages:
436
288
 
437
289
  ```vue fileName="components/LocaleSwitcher.vue"
438
- <template>
439
- <div class="locale-switcher">
440
- <select v-model="selectedLocale" @change="changeLocale">
441
- <option v-for="loc in availableLocales" :key="loc" :value="loc">
442
- {{ getLocaleName(loc) }}
443
- </option>
444
- </select>
445
- </div>
446
- </template>
447
-
448
290
  <script setup lang="ts">
449
- import { ref, watch } from "vue";
450
- import { getLocaleName } from "intlayer";
291
+ import { getLocaleName, getLocalizedUrl } from "intlayer";
451
292
  import { useLocale } from "vue-intlayer";
452
293
 
453
- // Get locale information and setLocale function
294
+ // Nuxt auto-imports useRoute
295
+ const route = useRoute();
454
296
  const { locale, availableLocales, setLocale } = useLocale();
455
-
456
- // Track the selected locale with a ref
457
- const selectedLocale = ref(locale.value);
458
-
459
- // Update the locale when the selection changes
460
- const changeLocale = () => setLocale(selectedLocale.value);
461
-
462
- // Keep the selectedLocale in sync with the global locale
463
- watch(
464
- () => locale.value,
465
- (newLocale) => {
466
- selectedLocale.value = newLocale;
467
- }
468
- );
469
297
  </script>
298
+
299
+ <template>
300
+ <nav class="locale-switcher">
301
+ <NuxtLink
302
+ v-for="localeEl in availableLocales"
303
+ :key="localeEl"
304
+ :to="getLocalizedUrl(route.fullPath, localeEl)"
305
+ class="locale-link"
306
+ :class="{ 'active-locale': localeEl === locale }"
307
+ @click="setLocale(localeEl)"
308
+ >
309
+ {{ getLocaleName(localeEl) }}
310
+ </NuxtLink>
311
+ </nav>
470
312
  </template>
313
+ ```
471
314
 
472
- <style scoped>
473
- .locale-switcher {
474
- margin: 1rem 0;
475
- }
315
+ > Using `NuxtLink` with proper `href` attributes (via `getLocalizedUrl`) ensures that search engines can discover all language variants of your pages. This is preferable to JavaScript-only locale switching, which search engine crawlers may not follow.
476
316
 
477
- select {
478
- padding: 0.5rem;
479
- border-radius: 0.25rem;
480
- border: 1px solid #ccc;
481
- }
482
- </style>
317
+ Then, set up your `app.vue` to use layouts:
318
+
319
+ ```vue fileName="app.vue"
320
+ <template>
321
+ <NuxtLayout>
322
+ <NuxtPage />
323
+ </NuxtLayout>
324
+ </template>
483
325
  ```
484
326
 
485
- Then, use this component in your pages or layout:
327
+ ### (Optional) Step 6b: Create a Layout with Navigation
486
328
 
487
- ```vue fileName="app.vue"
329
+ Nuxt layouts allow you to define a common structure for your pages. Create a default layout that includes the locale switcher and navigation:
330
+
331
+ ```vue fileName="layouts/default.vue"
488
332
  <script setup lang="ts">
489
- import { useIntlayer } from "vue-intlayer";
333
+ import Links from "~/components/Links.vue";
490
334
  import LocaleSwitcher from "~/components/LocaleSwitcher.vue";
491
-
492
- const content = useIntlayer("app"); // Create related intlayer declaration file
493
335
  </script>
494
336
 
495
337
  <template>
@@ -498,12 +340,17 @@ const content = useIntlayer("app"); // Create related intlayer declaration file
498
340
  <LocaleSwitcher />
499
341
  </header>
500
342
  <main>
501
- <NuxtPage />
343
+ <slot />
502
344
  </main>
345
+
346
+ <Links href="/">Home</Links>
347
+ <Links href="/about">About</Links>
503
348
  </div>
504
349
  </template>
505
350
  ```
506
351
 
352
+ The `Links` component (shown below) ensures that internal navigation links are automatically localized.
353
+
507
354
  ### (Optional) Step 7: Add localized Routing to your application
508
355
 
509
356
  Nuxt automatically handles localized routing when using the `nuxt-intlayer` module. This creates routes for each language automatically based on your pages directory structure.
@@ -518,23 +365,58 @@ pages/
518
365
  └── index.vue → /contact, /fr/contact, /es/contact
519
366
  ```
520
367
 
521
- To create a localized page, simply create your Vue files in the `pages/` directory:
368
+ To create localized pages, simply create your Vue files in the `pages/` directory. Here are two example pages:
369
+
370
+ **Home page (`pages/index.vue`):**
371
+
372
+ ```vue fileName="pages/index.vue"
373
+ <script setup lang="ts">
374
+ import { useIntlayer } from "vue-intlayer";
375
+
376
+ const content = useIntlayer("home-page");
377
+
378
+ useHead({
379
+ title: content.metaTitle.value,
380
+ meta: [
381
+ {
382
+ name: "description",
383
+ content: content.metaDescription.value,
384
+ },
385
+ ],
386
+ });
387
+ </script>
388
+
389
+ <template>
390
+ <h1><content.title /></h1>
391
+ </template>
392
+ ```
393
+
394
+ **About page (`pages/about.vue`):**
522
395
 
523
396
  ```vue fileName="pages/about.vue"
524
397
  <script setup lang="ts">
525
398
  import { useIntlayer } from "vue-intlayer";
526
399
 
527
- const content = useIntlayer("about");
400
+ const content = useIntlayer("about-page");
401
+
402
+ useHead({
403
+ title: content.metaTitle.raw, // Use .raw for primitive string access
404
+ meta: [
405
+ {
406
+ name: "description",
407
+ content: content.metaDescription.raw, // Use .raw for primitive string access
408
+ },
409
+ ],
410
+ });
528
411
  </script>
529
412
 
530
413
  <template>
531
- <div>
532
- <h1>{{ content.title }}</h1>
533
- <p>{{ content.description }}</p>
534
- </div>
414
+ <h1><content.title /></h1>
535
415
  </template>
536
416
  ```
537
417
 
418
+ > Note: `useHead` is auto-imported in Nuxt. You can access content values using either `.value` (reactive) or `.raw` (primitive string) depending on your needs.
419
+
538
420
  The `nuxt-intlayer` module will automatically:
539
421
 
540
422
  - Detect the user's preferred locale
@@ -545,209 +427,225 @@ The `nuxt-intlayer` module will automatically:
545
427
 
546
428
  ### (Optional) Step 8: Creating a Localized Link Component
547
429
 
548
- To ensure that your application's navigation respects the current locale, you can create a custom `LocalizedLink` component. This component automatically prefixes internal URLs with the current language.
549
-
550
- ```vue fileName="components/LocalizedLink.vue"
551
- <template>
552
- <NuxtLink :to="localizedHref" v-bind="$attrs">
553
- <slot />
554
- </NuxtLink>
555
- </template>
430
+ To ensure that your application's navigation respects the current locale, you can create a custom `Links` component. This component automatically prefixes internal URLs with the current language, which is essential for **SEO and page discoverability**.
556
431
 
432
+ ```vue fileName="components/Links.vue"
557
433
  <script setup lang="ts">
558
- import { computed } from "vue";
559
434
  import { getLocalizedUrl } from "intlayer";
560
435
  import { useLocale } from "vue-intlayer";
561
436
 
562
- const props = defineProps({
563
- to: {
564
- type: String,
565
- required: true,
566
- },
567
- });
437
+ interface Props {
438
+ href: string;
439
+ locale?: string;
440
+ }
568
441
 
569
- const { locale } = useLocale();
442
+ const props = defineProps<Props>();
570
443
 
571
- // Check if the link is external
572
- const isExternalLink = computed(() => /^https?:\/\//.test(props.to || ""));
444
+ const { locale: currentLocale } = useLocale();
573
445
 
574
- // Create a localized href for internal links
575
- const localizedHref = computed(() =>
576
- isExternalLink.value ? props.to : getLocalizedUrl(props.to, locale.value)
577
- );
446
+ // Compute the final path
447
+ const finalPath = computed(() => {
448
+ // 1. Check if the link is external
449
+ const isExternal = /^https?:\/\//.test(props.href || "");
450
+
451
+ // 2. If external, return as is (NuxtLink handles the <a> tag generation)
452
+ if (isExternal) return props.href;
453
+
454
+ // 3. If internal, localize the URL
455
+ const targetLocale = props.locale || currentLocale.value;
456
+ return getLocalizedUrl(props.href, targetLocale);
457
+ });
578
458
  </script>
459
+
460
+ <template>
461
+ <NuxtLink :to="finalPath" v-bind="$attrs">
462
+ <slot />
463
+ </NuxtLink>
464
+ </template>
579
465
  ```
580
466
 
581
467
  Then use this component throughout your application:
582
468
 
583
- ```vue fileName="pages/index.vue"
469
+ ```vue fileName="layouts/default.vue"
470
+ <script setup lang="ts">
471
+ import Links from "~/components/Links.vue";
472
+ import LocaleSwitcher from "~/components/LocaleSwitcher.vue";
473
+ </script>
474
+
584
475
  <template>
585
476
  <div>
586
- <LocalizedLink to="/about">
587
- {{ content.aboutLink }}
588
- </LocalizedLink>
589
- <LocalizedLink to="/contact">
590
- {{ content.contactLink }}
591
- </LocalizedLink>
477
+ <header>
478
+ <LocaleSwitcher />
479
+ </header>
480
+ <main>
481
+ <slot />
482
+ </main>
483
+
484
+ <Links href="/">Home</Links>
485
+ <Links href="/about">About</Links>
592
486
  </div>
593
487
  </template>
594
-
595
- <script setup lang="ts">
596
- import { useIntlayer } from "vue-intlayer";
597
- import LocalizedLink from "~/components/LocalizedLink.vue";
598
-
599
- const content = useIntlayer("home");
600
- </script>
601
488
  ```
602
489
 
490
+ > By using `NuxtLink` with localized paths, you ensure that:
491
+ >
492
+ > - Search engines can crawl and index all language versions of your pages
493
+ > - Users can share localized URLs directly
494
+ > - Browser history works correctly with locale-prefixed URLs
495
+
603
496
  ### (Optional) Step 9: Handle Metadata and SEO
604
497
 
605
- Nuxt provides excellent SEO capabilities. You can use Intlayer to handle localized metadata:
498
+ Nuxt provides excellent SEO capabilities via the `useHead` composable (auto-imported). You can use Intlayer to handle localized metadata using the `.raw` or `.value` accessor to get the primitive string value:
606
499
 
607
500
  ```vue fileName="pages/about.vue"
608
501
  <script setup lang="ts">
609
- import { useSeoMeta } from "nuxt/app";
610
- import { getIntlayer } from "intlayer";
611
- import { useLocale } from "vue-intlayer";
502
+ import { useIntlayer } from "vue-intlayer";
612
503
 
613
- const { locale } = useLocale();
614
- const content = getIntlayer("about-meta", locale.value);
504
+ // useHead is auto-imported in Nuxt
505
+ const content = useIntlayer("about-page");
615
506
 
616
- useSeoMeta({
617
- title: content.title,
618
- description: content.description,
507
+ useHead({
508
+ title: content.metaTitle.raw, // Use .raw for primitive string access
509
+ meta: [
510
+ {
511
+ name: "description",
512
+ content: content.metaDescription.raw, // Use .raw for primitive string access
513
+ },
514
+ ],
619
515
  });
620
516
  </script>
621
517
 
622
518
  <template>
623
- <div>
624
- <h1>{{ content.pageTitle }}</h1>
625
- <p>{{ content.pageContent }}</p>
626
- </div>
519
+ <h1><content.title /></h1>
627
520
  </template>
628
521
  ```
629
522
 
523
+ > Alternatively, you can use the `import { getIntlayer } from "intlayer"` function to get the content without Vue reactivity.
524
+
525
+ > **Accessing content values:**
526
+ >
527
+ > - Use `.raw` to get the primitive string value (non-reactive)
528
+ > - Use `.value` to get the reactive value
529
+ > - Use `<content.key />` component syntax for Visual Editor support
530
+
630
531
  Create the corresponding content declaration:
631
532
 
632
- ```ts fileName="pages/about-meta.content.ts"
533
+ ```ts fileName="pages/about-page.content.ts" contentDeclarationFormat="typescript"
633
534
  import { t, type Dictionary } from "intlayer";
634
- import type { useSeoMeta } from "nuxt/app";
635
535
 
636
- const aboutMetaContent = {
637
- key: "about-meta",
536
+ const aboutPageContent = {
537
+ key: "about-page",
638
538
  content: {
639
- title: t({
539
+ metaTitle: t({
640
540
  en: "About Us - My Company",
641
541
  fr: "À Propos - Ma Société",
642
542
  es: "Acerca de Nosotros - Mi Empresa",
643
543
  }),
644
- description: t({
544
+ metaDescription: t({
645
545
  en: "Learn more about our company and our mission",
646
546
  fr: "En savoir plus sur notre société et notre mission",
647
547
  es: "Conozca más sobre nuestra empresa y nuestra misión",
648
548
  }),
549
+ title: t({
550
+ en: "About Us",
551
+ fr: "À Propos",
552
+ es: "Acerca de Nosotros",
553
+ }),
649
554
  },
650
- } satisfies Dictionary<Parameters<typeof useSeoMeta>[0]>;
555
+ } satisfies Dictionary;
651
556
 
652
- export default aboutMetaContent;
557
+ export default aboutPageContent;
653
558
  ```
654
559
 
655
- ```typescript fileName="pages/about-meta.content.mjs" contentDeclarationFormat="esm"
560
+ ```javascript fileName="pages/about-page.content.mjs" contentDeclarationFormat="esm"
656
561
  import { t } from "intlayer";
657
562
 
658
563
  /** @type {import('intlayer').Dictionary} */
659
- const aboutMetaContent = {
660
- key: "about-meta",
564
+ const aboutPageContent = {
565
+ key: "about-page",
661
566
  content: {
662
- title: t({
663
- zh: "关于我们 - 我的公司",
567
+ metaTitle: t({
664
568
  en: "About Us - My Company",
665
569
  fr: "À Propos - Ma Société",
666
570
  es: "Acerca de Nosotros - Mi Empresa",
667
571
  }),
668
- description: t({
669
- zh: "了解更多关于我们公司和我们的使命",
572
+ metaDescription: t({
670
573
  en: "Learn more about our company and our mission",
671
574
  fr: "En savoir plus sur notre société et notre mission",
672
575
  es: "Conozca más sobre nuestra empresa y nuestra misión",
673
576
  }),
577
+ title: t({
578
+ en: "About Us",
579
+ fr: "À Propos",
580
+ es: "Acerca de Nosotros",
581
+ }),
674
582
  },
675
583
  };
676
584
 
677
- export default aboutMetaContent;
585
+ export default aboutPageContent;
678
586
  ```
679
587
 
680
- ```typescript fileName="pages/about-meta.content.js" contentDeclarationFormat="cjs"
588
+ ```javascript fileName="pages/about-page.content.cjs" contentDeclarationFormat="commonjs"
681
589
  const { t } = require("intlayer");
682
590
 
683
591
  /** @type {import('intlayer').Dictionary} */
684
- const aboutMetaContent = {
685
- key: "about-meta",
592
+ const aboutPageContent = {
593
+ key: "about-page",
686
594
  content: {
687
- title: t({
688
- zh: "关于我们 - 我的公司",
595
+ metaTitle: t({
689
596
  en: "About Us - My Company",
690
597
  fr: "À Propos - Ma Société",
691
598
  es: "Acerca de Nosotros - Mi Empresa",
692
599
  }),
693
- description: t({
694
- zh: "了解更多关于我们公司和我们的使命",
600
+ metaDescription: t({
695
601
  en: "Learn more about our company and our mission",
696
602
  fr: "En savoir plus sur notre société et notre mission",
697
603
  es: "Conozca más sobre nuestra empresa y nuestra misión",
698
604
  }),
605
+ title: t({
606
+ en: "About Us",
607
+ fr: "À Propos",
608
+ es: "Acerca de Nosotros",
609
+ }),
699
610
  },
700
611
  };
701
612
 
702
- module.exports = aboutMetaContent;
613
+ module.exports = aboutPageContent;
703
614
  ```
704
615
 
705
- ```json fileName="pages/about-meta.content.json" contentDeclarationFormat="json"
616
+ ```json fileName="pages/about-page.content.json" contentDeclarationFormat="json"
706
617
  {
707
- "key": "about-meta",
618
+ "$schema": "https://intlayer.org/schema.json",
619
+ "key": "about-page",
708
620
  "content": {
709
- "title": {
621
+ "metaTitle": {
710
622
  "nodeType": "translation",
711
- "translations": {
712
- "zh": "关于我们 - 我的公司",
623
+ "translation": {
713
624
  "en": "About Us - My Company",
714
625
  "fr": "À Propos - Ma Société",
715
626
  "es": "Acerca de Nosotros - Mi Empresa"
716
627
  }
717
628
  },
718
- "description": {
629
+ "metaDescription": {
719
630
  "nodeType": "translation",
720
- "translations": {
721
- "zh": "了解更多关于我们公司和我们的使命",
631
+ "translation": {
722
632
  "en": "Learn more about our company and our mission",
723
633
  "fr": "En savoir plus sur notre société et notre mission",
724
634
  "es": "Conozca más sobre nuestra empresa y nuestra misión"
725
635
  }
636
+ },
637
+ "title": {
638
+ "nodeType": "translation",
639
+ "translation": {
640
+ "en": "About Us",
641
+ "fr": "À Propos",
642
+ "es": "Acerca de Nosotros"
643
+ }
726
644
  }
727
645
  }
728
646
  }
729
647
  ```
730
648
 
731
- ### Configure TypeScript
732
-
733
- Intlayer uses module augmentation to get benefits of TypeScript and make your codebase stronger.
734
-
735
- ![Autocompletion](https://github.com/aymericzip/intlayer/blob/main/docs/assets/autocompletion.png?raw=true)
736
-
737
- ![Translation error](https://github.com/aymericzip/intlayer/blob/main/docs/assets/translation_error.png?raw=true)
738
-
739
- Ensure your TypeScript configuration includes the autogenerated types.
740
-
741
- ```json5 fileName="tsconfig.json"
742
- {
743
- // ... Your existing TypeScript configurations
744
- "include": [
745
- // ... Your existing TypeScript configurations
746
- ".intlayer/**/*.ts", // Include the auto-generated types
747
- ],
748
- }
749
- ```
750
-
751
649
  ### Git Configuration
752
650
 
753
651
  It is recommended to ignore the files generated by Intlayer. This allows you to avoid committing them to your Git repository.
@@ -779,5 +677,3 @@ For more details on how to use the extension, refer to the [Intlayer VS Code Ext
779
677
  ### Go Further
780
678
 
781
679
  To go further, you can implement the [visual editor](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_visual_editor.md) or externalize your content using the [CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_CMS.md).
782
-
783
- ---