Introduction
@nuxtjs/i18n provides the useLocaleHead composable function. Calling this composable function returns a function which you can use to generate SEO metadata to optimize locale-related aspects of the app for the search engines.
Here are the specific optimizations and features that it enables:
langattribute for the<html>taghreflangalternate link generation- OpenGraph locale tag generation
- canonical link generation
Read more about those features below
Requirements
To leverage the SEO benefits, you must configure the locales option as an array of objects, where each object has an iso option set to the language's ISO code:
export default defineNuxtConfig({ // ... i18n: { locales: [ { code: 'en', iso: 'en-US' }, { code: 'es', iso: 'es-ES' }, { code: 'fr', iso: 'fr-FR' } ] }, // ...})You must also set the baseUrl option to your production domain in order to make alternate URLs fully-qualified:
export default defineNuxtConfig({ // ... i18n: { baseUrl: 'https://my-nuxt-app.com' }, // ...})(Note that baseUrl can also be set to a function. Check baseUrl documentation.)
Setup
The useLocaleHead is a composable function, Calling that composable function returns a function that returns metadata that is handled by Head management that is integrated within Nuxt. That metadata can be specified the setup function in various places within Nuxt:
To enable SEO metadata, declare a setup function in one of the places specified above and make it return the result of a useLocaleHead function call.
To avoid duplicating the code, it's recommended to set globally with Meta Components in layout components and override some values per-page Vue component like definePageMeta, if necessary.
<template> <NuxtLayout> <NuxtPage /> </NuxtLayout></template>Check out the options you can pass to the useLocaleHead in the API documentation
That's it!
If you also want to add your own metadata, you have to call useHead. When you call useHead with the addiotional metadata, useHead will merge it global metadata that has already defined.
<script setup>// define page meta for layouts/default.vuedefinePageMeta({ title: 'pages.title.about'})useHead({ meta: [{ property: "og:title", content: "this is og title for about page" }]})</script><template> <h2>{{ $t('pages.about.description') }}</h2></template>Feature details
langattribute for the<html>tag
Sets the correctlangattribute, equivalent to the current locale's ISO code, in the<html>tag.hreflangalternate link
Generates<link rel="alternate" hreflang="x">tags for every configured locale. The locales' ISO codes are used ashreflangvalues.
A "catchall" locale hreflang link is provided for each locale group (e.g.en-*). By default, it is the first locale provided, but another locale can be selected by settingisCatchallLocaletotrueon that specific locale object in your @nuxtjs/i18n configuration. More on hreflang
An example without selected "catchall" locale:nuxt.config.tsexport default defineNuxtConfig({ // ... i18n: { locales: [ { code: 'en', iso: 'en-US' // Will be used as "catchall" locale by default }, { code: 'gb', iso: 'en-GB' } ] }, // ...})
Here is how you'd useisCatchallLocaleto selected another locale:nuxt.config.tsexport default defineNuxtConfig({ // ... i18n: { locales: [ { code: 'en', iso: 'en-US' }, { code: 'gb', iso: 'en-GB', isCatchallLocale: true // This one will be used as catchall locale } ] }, // ...})
In case you already have anenlocaleisoset, it'll be used as the "catchall" without doing anythingnuxt.config.tsexport default defineNuxtConfig({ // ... i18n: { locales: [ { code: 'gb', iso: 'en-GB' }, { code: 'en', iso: 'en' // will be used as "catchall" locale } ] }, // ...})- OpenGraph Locale tag generation
Generatesog:localeandog:locale:alternatemeta tags as defined in the Open Graph protocol. - Canonical link
Generatesrel="canonical"link on all pages to specify the "main" version of the page that should be indexed by search engines. This is beneficial in various situations:- When using the
prefix_and_defaultstrategy there are technically two sets of pages generated for the default locale -- one prefixed and one unprefixed. The canonical link will be set to the unprefixed version of the page to avoid duplicate indexation. - When the page contains query parameters, the canonical link will not include the query params by default. This is typically the right thing to do as various query params can be inserted by trackers and should not be part of the canonical link. This can be overriden by using the
canonicalQueriesoption. For example:<script setup>const i18nHead = useLocaleHead({ addSeoAttributes: { canonicalQueries: ['foo'] }})useHead({ htmlAttrs: { lang: i18nHead.value.htmlAttrs!.lang }, link: [...(i18nHead.value.link || [])], meta: [...(i18nHead.value.meta || [])]})</script>
More on canonical - When using the