@intlayer/docs 7.3.10 → 7.3.12

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 +305 -421
  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 +296 -394
  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 +242 -321
  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 +262 -358
  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 +284 -375
  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 +288 -387
  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 +318 -434
  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 +275 -376
  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 +312 -408
  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 +319 -414
  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 +307 -406
  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 +282 -457
  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 +288 -403
  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 +300 -410
  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 +327 -392
  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 +282 -399
  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 +311 -444
  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 +6 -6
  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,12 @@ 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=IE3XWkZ6a5U
18
19
  history:
20
+ - version: 7.3.11
21
+ date: 2025-12-07
22
+ changes: Update LocaleSwitcher, SEO, metadata
19
23
  - version: 5.5.10
20
24
  date: 2025-06-29
21
25
  changes: Init history
@@ -23,8 +27,6 @@ history:
23
27
 
24
28
  # Translate your Nuxt and Vue website using Intlayer | Internationalization (i18n)
25
29
 
26
- See [Application Template](https://github.com/aymericzip/intlayer-nuxt-template) on GitHub.
27
-
28
30
  ## Table of Contents
29
31
 
30
32
  <TOC/>
@@ -45,7 +47,7 @@ With Intlayer, you can:
45
47
  ## Step-by-Step Guide to Set Up Intlayer in a Nuxt Application
46
48
 
47
49
  <iframe
48
- src="https://stackblitz.com/github/aymericzip/intlayer-nuxt-template?embed=1&ctl=1&file=intlayer.config.ts"
50
+ src="https://stackblitz.com/github/aymericzip/intlayer-nuxt-4-template?embed=1&ctl=1&file=intlayer.config.ts"
49
51
  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
52
  title="Demo CodeSandbox - How to Internationalize your application using Intlayer"
51
53
  sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
@@ -54,6 +56,27 @@ With Intlayer, you can:
54
56
 
55
57
  ### Step 1: Install Dependencies
56
58
 
59
+ <Tab defaultTab="video">
60
+ <TabItem label="Video" value="video">
61
+
62
+ <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/IE3XWkZ6a5U?autoplay=0&amp;origin=http://intlayer.org&amp;controls=0&amp;rel=1"/>
63
+
64
+ </TabItem>
65
+ <TabItem label="Code" value="code">
66
+
67
+ <iframe
68
+ src="https://stackblitz.com/github/aymericzip/intlayer-nuxt-4-template?embed=1&ctl=1&file=intlayer.config.ts"
69
+ className="m-auto overflow-hidden rounded-lg border-0 max-md:size-full max-md:h-[700px] md:aspect-16/9 md:w-full"
70
+ title="Demo CodeSandbox - How to Internationalize your application using Intlayer"
71
+ sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
72
+ loading="lazy"
73
+ />
74
+
75
+ </TabItem>
76
+ </Tab>
77
+
78
+ See [Application Template](https://github.com/aymericzip/intlayer-nuxt-4-template) on GitHub.
79
+
57
80
  Install the necessary packages using npm:
58
81
 
59
82
  ```bash packageManager="npm"
@@ -98,9 +121,6 @@ const config: IntlayerConfig = {
98
121
  ],
99
122
  defaultLocale: Locales.ENGLISH,
100
123
  },
101
- content: {
102
- contentDir: ["."], // Because by default Intayer will watch content declaration files from the `./src` directory
103
- },
104
124
  };
105
125
 
106
126
  export default config;
@@ -120,9 +140,6 @@ const config = {
120
140
  ],
121
141
  defaultLocale: Locales.ENGLISH,
122
142
  },
123
- content: {
124
- contentDir: ["."],
125
- },
126
143
  };
127
144
 
128
145
  export default config;
@@ -142,9 +159,6 @@ const config = {
142
159
  ],
143
160
  defaultLocale: Locales.ENGLISH,
144
161
  },
145
- content: {
146
- contentDir: ["."],
147
- },
148
162
  };
149
163
 
150
164
  module.exports = config;
@@ -171,188 +185,31 @@ export default defineNuxtConfig({
171
185
 
172
186
  Create and manage your content declarations to store translations:
173
187
 
174
- ```tsx fileName="components/helloWorld.content.ts" contentDeclarationFormat="typescript"
175
- import { t, type Dictionary } from "intlayer";
188
+ ```tsx fileName="content/home-page.content.ts" contentDeclarationFormat="typescript"
189
+ import { type Dictionary, t } from "intlayer";
176
190
 
177
- const helloWorldContent = {
178
- key: "helloworld",
191
+ const content = {
192
+ key: "home-page",
179
193
  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 ",
194
+ title: t({
195
+ en: "Hello world",
196
+ fr: "Bonjour le monde",
197
+ es: "Hola mundo",
196
198
  }),
197
- nuxtDocs: t({
198
- en: "Nuxt Documentation",
199
- fr: "Documentation Nuxt",
200
- es: "Documentación de Nuxt",
199
+ metaTitle: t({
200
+ en: "Welcome | My Application",
201
+ fr: "Bienvenue | Mon Application",
202
+ es: "Bienvenido | Mi Aplicación",
201
203
  }),
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",
204
+ metaDescription: t({
205
+ en: "Discover your multilingual Nuxt app homepage powered by Intlayer.",
206
+ fr: "Découvrez la page d'accueil multilingue de votre application Nuxt propulsée par Intlayer.",
207
+ es: "Descubre la página de inicio multilingüe de tu aplicación Nuxt impulsada por Intlayer.",
206
208
  }),
207
209
  },
208
210
  } satisfies Dictionary;
209
211
 
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
- }
212
+ export default content;
356
213
  ```
357
214
 
358
215
  > 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 +289,54 @@ Intlayer offers different APIs to access your content:
432
289
 
433
290
  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
291
 
435
- Create a component to switch between languages:
292
+ 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
293
 
437
294
  ```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
295
  <script setup lang="ts">
449
- import { ref, watch } from "vue";
450
- import { getLocaleName } from "intlayer";
296
+ import { getLocaleName, getLocalizedUrl } from "intlayer";
451
297
  import { useLocale } from "vue-intlayer";
452
298
 
453
- // Get locale information and setLocale function
299
+ // Nuxt auto-imports useRoute
300
+ const route = useRoute();
454
301
  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
302
  </script>
303
+
304
+ <template>
305
+ <nav class="locale-switcher">
306
+ <NuxtLink
307
+ v-for="localeEl in availableLocales"
308
+ :key="localeEl"
309
+ :to="getLocalizedUrl(route.fullPath, localeEl)"
310
+ class="locale-link"
311
+ :class="{ 'active-locale': localeEl === locale }"
312
+ @click="setLocale(localeEl)"
313
+ >
314
+ {{ getLocaleName(localeEl) }}
315
+ </NuxtLink>
316
+ </nav>
470
317
  </template>
318
+ ```
471
319
 
472
- <style scoped>
473
- .locale-switcher {
474
- margin: 1rem 0;
475
- }
320
+ > 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
321
 
477
- select {
478
- padding: 0.5rem;
479
- border-radius: 0.25rem;
480
- border: 1px solid #ccc;
481
- }
482
- </style>
322
+ Then, set up your `app.vue` to use layouts:
323
+
324
+ ```vue fileName="app.vue"
325
+ <template>
326
+ <NuxtLayout>
327
+ <NuxtPage />
328
+ </NuxtLayout>
329
+ </template>
483
330
  ```
484
331
 
485
- Then, use this component in your pages or layout:
332
+ ### (Optional) Step 6b: Create a Layout with Navigation
486
333
 
487
- ```vue fileName="app.vue"
334
+ Nuxt layouts allow you to define a common structure for your pages. Create a default layout that includes the locale switcher and navigation:
335
+
336
+ ```vue fileName="layouts/default.vue"
488
337
  <script setup lang="ts">
489
- import { useIntlayer } from "vue-intlayer";
338
+ import Links from "~/components/Links.vue";
490
339
  import LocaleSwitcher from "~/components/LocaleSwitcher.vue";
491
-
492
- const content = useIntlayer("app"); // Create related intlayer declaration file
493
340
  </script>
494
341
 
495
342
  <template>
@@ -498,12 +345,17 @@ const content = useIntlayer("app"); // Create related intlayer declaration file
498
345
  <LocaleSwitcher />
499
346
  </header>
500
347
  <main>
501
- <NuxtPage />
348
+ <slot />
502
349
  </main>
350
+
351
+ <Links href="/">Home</Links>
352
+ <Links href="/about">About</Links>
503
353
  </div>
504
354
  </template>
505
355
  ```
506
356
 
357
+ The `Links` component (shown below) ensures that internal navigation links are automatically localized.
358
+
507
359
  ### (Optional) Step 7: Add localized Routing to your application
508
360
 
509
361
  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 +370,58 @@ pages/
518
370
  └── index.vue → /contact, /fr/contact, /es/contact
519
371
  ```
520
372
 
521
- To create a localized page, simply create your Vue files in the `pages/` directory:
373
+ To create localized pages, simply create your Vue files in the `pages/` directory. Here are two example pages:
374
+
375
+ **Home page (`pages/index.vue`):**
376
+
377
+ ```vue fileName="pages/index.vue"
378
+ <script setup lang="ts">
379
+ import { useIntlayer } from "vue-intlayer";
380
+
381
+ const content = useIntlayer("home-page");
382
+
383
+ useHead({
384
+ title: content.metaTitle.value,
385
+ meta: [
386
+ {
387
+ name: "description",
388
+ content: content.metaDescription.value,
389
+ },
390
+ ],
391
+ });
392
+ </script>
393
+
394
+ <template>
395
+ <h1><content.title /></h1>
396
+ </template>
397
+ ```
398
+
399
+ **About page (`pages/about.vue`):**
522
400
 
523
401
  ```vue fileName="pages/about.vue"
524
402
  <script setup lang="ts">
525
403
  import { useIntlayer } from "vue-intlayer";
526
404
 
527
- const content = useIntlayer("about");
405
+ const content = useIntlayer("about-page");
406
+
407
+ useHead({
408
+ title: content.metaTitle.raw, // Use .raw for primitive string access
409
+ meta: [
410
+ {
411
+ name: "description",
412
+ content: content.metaDescription.raw, // Use .raw for primitive string access
413
+ },
414
+ ],
415
+ });
528
416
  </script>
529
417
 
530
418
  <template>
531
- <div>
532
- <h1>{{ content.title }}</h1>
533
- <p>{{ content.description }}</p>
534
- </div>
419
+ <h1><content.title /></h1>
535
420
  </template>
536
421
  ```
537
422
 
423
+ > Note: `useHead` is auto-imported in Nuxt. You can access content values using either `.value` (reactive) or `.raw` (primitive string) depending on your needs.
424
+
538
425
  The `nuxt-intlayer` module will automatically:
539
426
 
540
427
  - Detect the user's preferred locale
@@ -545,184 +432,220 @@ The `nuxt-intlayer` module will automatically:
545
432
 
546
433
  ### (Optional) Step 8: Creating a Localized Link Component
547
434
 
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>
435
+ 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
436
 
437
+ ```vue fileName="components/Links.vue"
557
438
  <script setup lang="ts">
558
- import { computed } from "vue";
559
439
  import { getLocalizedUrl } from "intlayer";
560
440
  import { useLocale } from "vue-intlayer";
561
441
 
562
- const props = defineProps({
563
- to: {
564
- type: String,
565
- required: true,
566
- },
567
- });
442
+ interface Props {
443
+ href: string;
444
+ locale?: string;
445
+ }
568
446
 
569
- const { locale } = useLocale();
447
+ const props = defineProps<Props>();
570
448
 
571
- // Check if the link is external
572
- const isExternalLink = computed(() => /^https?:\/\//.test(props.to || ""));
449
+ const { locale: currentLocale } = useLocale();
573
450
 
574
- // Create a localized href for internal links
575
- const localizedHref = computed(() =>
576
- isExternalLink.value ? props.to : getLocalizedUrl(props.to, locale.value)
577
- );
451
+ // Compute the final path
452
+ const finalPath = computed(() => {
453
+ // 1. Check if the link is external
454
+ const isExternal = /^https?:\/\//.test(props.href || "");
455
+
456
+ // 2. If external, return as is (NuxtLink handles the <a> tag generation)
457
+ if (isExternal) return props.href;
458
+
459
+ // 3. If internal, localize the URL
460
+ const targetLocale = props.locale || currentLocale.value;
461
+ return getLocalizedUrl(props.href, targetLocale);
462
+ });
578
463
  </script>
464
+
465
+ <template>
466
+ <NuxtLink :to="finalPath" v-bind="$attrs">
467
+ <slot />
468
+ </NuxtLink>
469
+ </template>
579
470
  ```
580
471
 
581
472
  Then use this component throughout your application:
582
473
 
583
- ```vue fileName="pages/index.vue"
474
+ ```vue fileName="layouts/default.vue"
475
+ <script setup lang="ts">
476
+ import Links from "~/components/Links.vue";
477
+ import LocaleSwitcher from "~/components/LocaleSwitcher.vue";
478
+ </script>
479
+
584
480
  <template>
585
481
  <div>
586
- <LocalizedLink to="/about">
587
- {{ content.aboutLink }}
588
- </LocalizedLink>
589
- <LocalizedLink to="/contact">
590
- {{ content.contactLink }}
591
- </LocalizedLink>
482
+ <header>
483
+ <LocaleSwitcher />
484
+ </header>
485
+ <main>
486
+ <slot />
487
+ </main>
488
+
489
+ <Links href="/">Home</Links>
490
+ <Links href="/about">About</Links>
592
491
  </div>
593
492
  </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
493
  ```
602
494
 
495
+ > By using `NuxtLink` with localized paths, you ensure that:
496
+ >
497
+ > - Search engines can crawl and index all language versions of your pages
498
+ > - Users can share localized URLs directly
499
+ > - Browser history works correctly with locale-prefixed URLs
500
+
603
501
  ### (Optional) Step 9: Handle Metadata and SEO
604
502
 
605
- Nuxt provides excellent SEO capabilities. You can use Intlayer to handle localized metadata:
503
+ 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
504
 
607
505
  ```vue fileName="pages/about.vue"
608
506
  <script setup lang="ts">
609
- import { useSeoMeta } from "nuxt/app";
610
- import { getIntlayer } from "intlayer";
611
- import { useLocale } from "vue-intlayer";
507
+ import { useIntlayer } from "vue-intlayer";
612
508
 
613
- const { locale } = useLocale();
614
- const content = getIntlayer("about-meta", locale.value);
509
+ // useHead is auto-imported in Nuxt
510
+ const content = useIntlayer("about-page");
615
511
 
616
- useSeoMeta({
617
- title: content.title,
618
- description: content.description,
512
+ useHead({
513
+ title: content.metaTitle.raw, // Use .raw for primitive string access
514
+ meta: [
515
+ {
516
+ name: "description",
517
+ content: content.metaDescription.raw, // Use .raw for primitive string access
518
+ },
519
+ ],
619
520
  });
620
521
  </script>
621
522
 
622
523
  <template>
623
- <div>
624
- <h1>{{ content.pageTitle }}</h1>
625
- <p>{{ content.pageContent }}</p>
626
- </div>
524
+ <h1><content.title /></h1>
627
525
  </template>
628
526
  ```
629
527
 
528
+ > Alternatively, you can use the `import { getIntlayer } from "intlayer"` function to get the content without Vue reactivity.
529
+
530
+ > **Accessing content values:**
531
+ >
532
+ > - Use `.raw` to get the primitive string value (non-reactive)
533
+ > - Use `.value` to get the reactive value
534
+ > - Use `<content.key />` component syntax for Visual Editor support
535
+
630
536
  Create the corresponding content declaration:
631
537
 
632
- ```ts fileName="pages/about-meta.content.ts"
538
+ ```ts fileName="pages/about-page.content.ts" contentDeclarationFormat="typescript"
633
539
  import { t, type Dictionary } from "intlayer";
634
- import type { useSeoMeta } from "nuxt/app";
635
540
 
636
- const aboutMetaContent = {
637
- key: "about-meta",
541
+ const aboutPageContent = {
542
+ key: "about-page",
638
543
  content: {
639
- title: t({
544
+ metaTitle: t({
640
545
  en: "About Us - My Company",
641
546
  fr: "À Propos - Ma Société",
642
547
  es: "Acerca de Nosotros - Mi Empresa",
643
548
  }),
644
- description: t({
549
+ metaDescription: t({
645
550
  en: "Learn more about our company and our mission",
646
551
  fr: "En savoir plus sur notre société et notre mission",
647
552
  es: "Conozca más sobre nuestra empresa y nuestra misión",
648
553
  }),
554
+ title: t({
555
+ en: "About Us",
556
+ fr: "À Propos",
557
+ es: "Acerca de Nosotros",
558
+ }),
649
559
  },
650
- } satisfies Dictionary<Parameters<typeof useSeoMeta>[0]>;
560
+ } satisfies Dictionary;
651
561
 
652
- export default aboutMetaContent;
562
+ export default aboutPageContent;
653
563
  ```
654
564
 
655
- ```typescript fileName="pages/about-meta.content.mjs" contentDeclarationFormat="esm"
565
+ ```javascript fileName="pages/about-page.content.mjs" contentDeclarationFormat="esm"
656
566
  import { t } from "intlayer";
657
567
 
658
568
  /** @type {import('intlayer').Dictionary} */
659
- const aboutMetaContent = {
660
- key: "about-meta",
569
+ const aboutPageContent = {
570
+ key: "about-page",
661
571
  content: {
662
- title: t({
663
- zh: "关于我们 - 我的公司",
572
+ metaTitle: t({
664
573
  en: "About Us - My Company",
665
574
  fr: "À Propos - Ma Société",
666
575
  es: "Acerca de Nosotros - Mi Empresa",
667
576
  }),
668
- description: t({
669
- zh: "了解更多关于我们公司和我们的使命",
577
+ metaDescription: t({
670
578
  en: "Learn more about our company and our mission",
671
579
  fr: "En savoir plus sur notre société et notre mission",
672
580
  es: "Conozca más sobre nuestra empresa y nuestra misión",
673
581
  }),
582
+ title: t({
583
+ en: "About Us",
584
+ fr: "À Propos",
585
+ es: "Acerca de Nosotros",
586
+ }),
674
587
  },
675
588
  };
676
589
 
677
- export default aboutMetaContent;
590
+ export default aboutPageContent;
678
591
  ```
679
592
 
680
- ```typescript fileName="pages/about-meta.content.js" contentDeclarationFormat="cjs"
593
+ ```javascript fileName="pages/about-page.content.cjs" contentDeclarationFormat="commonjs"
681
594
  const { t } = require("intlayer");
682
595
 
683
596
  /** @type {import('intlayer').Dictionary} */
684
- const aboutMetaContent = {
685
- key: "about-meta",
597
+ const aboutPageContent = {
598
+ key: "about-page",
686
599
  content: {
687
- title: t({
688
- zh: "关于我们 - 我的公司",
600
+ metaTitle: t({
689
601
  en: "About Us - My Company",
690
602
  fr: "À Propos - Ma Société",
691
603
  es: "Acerca de Nosotros - Mi Empresa",
692
604
  }),
693
- description: t({
694
- zh: "了解更多关于我们公司和我们的使命",
605
+ metaDescription: t({
695
606
  en: "Learn more about our company and our mission",
696
607
  fr: "En savoir plus sur notre société et notre mission",
697
608
  es: "Conozca más sobre nuestra empresa y nuestra misión",
698
609
  }),
610
+ title: t({
611
+ en: "About Us",
612
+ fr: "À Propos",
613
+ es: "Acerca de Nosotros",
614
+ }),
699
615
  },
700
616
  };
701
617
 
702
- module.exports = aboutMetaContent;
618
+ module.exports = aboutPageContent;
703
619
  ```
704
620
 
705
- ```json fileName="pages/about-meta.content.json" contentDeclarationFormat="json"
621
+ ```json fileName="pages/about-page.content.json" contentDeclarationFormat="json"
706
622
  {
707
- "key": "about-meta",
623
+ "$schema": "https://intlayer.org/schema.json",
624
+ "key": "about-page",
708
625
  "content": {
709
- "title": {
626
+ "metaTitle": {
710
627
  "nodeType": "translation",
711
- "translations": {
712
- "zh": "关于我们 - 我的公司",
628
+ "translation": {
713
629
  "en": "About Us - My Company",
714
630
  "fr": "À Propos - Ma Société",
715
631
  "es": "Acerca de Nosotros - Mi Empresa"
716
632
  }
717
633
  },
718
- "description": {
634
+ "metaDescription": {
719
635
  "nodeType": "translation",
720
- "translations": {
721
- "zh": "了解更多关于我们公司和我们的使命",
636
+ "translation": {
722
637
  "en": "Learn more about our company and our mission",
723
638
  "fr": "En savoir plus sur notre société et notre mission",
724
639
  "es": "Conozca más sobre nuestra empresa y nuestra misión"
725
640
  }
641
+ },
642
+ "title": {
643
+ "nodeType": "translation",
644
+ "translation": {
645
+ "en": "About Us",
646
+ "fr": "À Propos",
647
+ "es": "Acerca de Nosotros"
648
+ }
726
649
  }
727
650
  }
728
651
  }
@@ -779,5 +702,3 @@ For more details on how to use the extension, refer to the [Intlayer VS Code Ext
779
702
  ### Go Further
780
703
 
781
704
  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
- ---