The Short Version
If you use @nuxtjs/i18n, hreflang tags can be generated for you — but only when the SEO output is switched on and configured correctly. Set a baseUrl and give each locale a language, and the module can output the <link rel="alternate" hreflang="..."> tags (plus x-default) automatically.
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@nuxtjs/i18n'],
i18n: {
baseUrl: 'https://example.com', // required for absolute hreflang URLs
locales: [
{ code: 'en', language: 'en-US' },
{ code: 'fr', language: 'fr-FR' },
],
defaultLocale: 'en',
},
});
Then emit the SEO tags from your layout using the module's head helper, which injects the hreflang alternates and the canonical for you:
<script setup>
const head = useLocaleHead({ addSeoAttributes: true })
</script>
Common Problems
- Missing
baseUrl— without it the module can't build absolute URLs, so hreflang tags either don't render or use relative paths, which Google treats as invalid. languagenot set on locales — thelanguage(BCP-47, likefr-FR) is what fills thehreflangvalue. Usecodefor routing (/fr) andlanguagefor the tag.- Canonical conflict — if you also hand-write a canonical with
useHead, you can end up with two. Let the i18n helper own the canonical, or set yours consistently per locale. - No
x-default— the module derives it fromdefaultLocale, so make sure that's set.
Verify It
View source on each localized page and confirm every language variant lists a return tag back to the others — hreflang must be reciprocal. Build the tags by hand for a quick sanity check with the hreflang generator.
FAQ
Q: Does @nuxtjs/i18n add hreflang automatically?
Yes, when you set baseUrl and emit the SEO tags via useLocaleHead({ addSeoAttributes: true }). It outputs the alternate hreflang links and x-default for you.
Q: Why are my hreflang URLs relative or missing?
You haven't set baseUrl in the i18n config. It's required to build the absolute URLs hreflang needs.
Q: Do I set the language on each locale?
Yes. code handles routing, while language (for example fr-FR) is the BCP-47 value written into the hreflang attribute.