Come ottimizzare la SEO di un'app Next.js multilingue
Perché la SEO multilingue richiede un'attenzione particolare
La maggior parte degli sviluppatori che aggiunge i18n alla propria app Next.js si concentra sulla traduzione dell'interfaccia utente e considera il lavoro finito. Ma se i motori di ricerca non riescono a trovare, indicizzare e associare correttamente le diverse versioni linguistiche, tutto quel lavoro di traduzione resta invisibile.
Un sito multilingue senza una corretta configurazione SEO presenta questi problemi:
- Google potrebbe indicizzare una sola versione linguistica e ignorare tutte le altre
- Gli utenti che cercano in spagnolo finiscono sulla pagina in inglese
- Penalizzazioni per contenuti duplicati, perché Google vede
/en/aboute/fr/aboutcome la stessa pagina - Visualizzazione della lingua sbagliata negli snippet dei risultati di ricerca
La buona notizia: impostare correttamente la SEO multilingue in Next.js non è complicato. Ci sono sei aspetti da configurare correttamente e questa guida li copre tutti usando gt-next.
1. Routing degli URL basato sull'impostazione regionale
Il fondamento della SEO multilingue è avere URL distinti per ogni lingua. I motori di ricerca hanno bisogno di URL separati ed esplorabili per indicizzare ogni versione linguistica in modo indipendente.
Questo significa impostazione regionale nell'URL — non cookie, non parametri di query, non il solo rilevamento di Accept-Language.
✅ generaltranslation.com/en/about
✅ generaltranslation.com/fr/about
✅ generaltranslation.com/es/about
❌ generaltranslation.com/about?lang=fr
❌ generaltranslation.com/about (con impostazione regionale in un cookie)
Configurare il routing delle impostazioni regionali con gt-next
Per prima cosa, annida le pagine sotto un segmento dinamico [locale]:
app/
└── [locale]/
├── layout.tsx
├── page.tsx
└── about/
└── page.tsx
Quindi crea il middleware nella directory root del progetto (proxy.ts per Next.js 16+ oppure middleware.ts per Next.js 15 e versioni precedenti):
import { createNextMiddleware } from 'gt-next/middleware';
export default createNextMiddleware();
export const config = {
matcher: ['/((?!api|static|.*\\..*|_next).*)'],
};In questo modo ottieni automaticamente URL con il prefisso dell’impostazione regionale.
Per impostazione predefinita, l’impostazione regionale predefinita (ad esempio l’inglese) non ha un prefisso — /about rimane invariato,
mentre gli utenti spagnoli vedono /es/about e quelli francesi vedono /fr/about.
2. Impostare l'attributo HTML lang
L'attributo lang nel tag <html> indica ai browser e ai motori di ricerca in quale lingua è scritta la pagina.
È una delle operazioni più semplici e al tempo stesso più efficaci che puoi fare per l'accessibilità e la SEO.
Senza questo attributo, gli screen reader cercano di indovinare la lingua, spesso sbagliando, e i motori di ricerca sono meno sicuri nel classificarla correttamente.
gt-next fornisce l'Hook useLocale, che rende tutto questo molto semplice nel layout radice:
import { useLocale, GTProvider } from 'gt-next';
export default function RootLayout({ children }: { children: React.ReactNode }) {
const locale = useLocale();
return (
<html lang={locale}>
<body>
<GTProvider>
{children}
</GTProvider>
</body>
</html>
);
}useLocale restituisce il codice locale in formato BCP 47 (ad es. en-US, ar, zh-Hans).
3. URL canoniche
I tag canonici indicano ai motori di ricerca quale URL è la versione "principale" di una pagina. Per i siti multilingue, ogni versione linguistica dovrebbe puntare a sé stessa come URL canonico:
<!-- Su /fr/about -->
<link rel="canonical" href="https://example.com/fr/about" />Questo impedisce ai motori di ricerca di considerare la tua pagina in francese come un duplicato di quella in inglese.
In Next.js, imposti gli URL canonici tramite la Metadata API.
Combinala con getLocale di gt-next per generare l'URL canonico corretto per ogni impostazione regionale:
import { getLocale } from 'gt-next/server';
const BASE_URL = 'https://example.com';
export async function generateMetadata() {
const locale = await getLocale();
return {
alternates: {
canonical: `${BASE_URL}/${locale}/about`,
},
};
}
export default function AboutPage() {
return <h1>About Us</h1>;
}Per l'impostazione regionale predefinita senza prefisso, adatta di conseguenza:
import { getLocale, getDefaultLocale } from 'gt-next/server';
export async function generateMetadata() {
const locale = await getLocale();
const defaultLocale = getDefaultLocale();
const path = '/about';
const prefix = locale === defaultLocale ? '' : `/${locale}`;
return {
alternates: {
canonical: `${BASE_URL}${prefix}${path}`,
},
};
}4. Tag hreflang
I tag hreflang sono il segnale SEO multilingue più importante. Indicano ai motori di ricerca: "questa pagina esiste anche in queste altre lingue e questi sono i relativi URL."
Senza hreflang, Google deve intuire quale versione linguistica mostrare nei risultati di ricerca — e spesso sbaglia.
<link rel="alternate" hreflang="en" href="https://example.com/about" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/about" />
<link rel="alternate" hreflang="es" href="https://example.com/es/about" />
<link rel="alternate" hreflang="x-default" href="https://example.com/about" />Il tag x-default indica ai motori di ricerca quale URL mostrare quando nessuna delle lingue specificate corrisponde alla lingua dell'utente.
In Next.js, puoi aggiungere hreflang tramite la proprietà alternates.languages della Metadata API.
Ecco un helper riutilizzabile che funziona con gt-next:
import { getLocale, getDefaultLocale } from 'gt-next/server';
const BASE_URL = 'https://example.com';
const SUPPORTED_LOCALES = ['en', 'fr', 'es'];
export async function getI18NMetadata(path: string) {
const locale = await getLocale();
const defaultLocale = getDefaultLocale();
const getUrl = (loc: string) => {
const prefix = loc === defaultLocale ? '' : `/${loc}`;
return `${BASE_URL}${prefix}${path}`;
};
const languages: Record<string, string> = {};
for (const loc of SUPPORTED_LOCALES) {
languages[loc] = getUrl(loc);
}
languages['x-default'] = getUrl(defaultLocale);
return {
alternates: {
canonical: getUrl(locale),
languages,
},
};
}Quindi usalo in una pagina qualsiasi:
import { getI18NMetadata } from '@/lib/i18n-metadata';
export async function generateMetadata() {
return await getI18NMetadata('/about');
}Questo genera il tag canonical e tutti i tag hreflang con una sola chiamata.
5. Metadati tradotti
I motori di ricerca mostrano il titolo e la descrizione della pagina nei risultati. Se per una pagina in francese sono in inglese, gli utenti saranno meno propensi a fare clic e Google potrebbe persino penalizzare il risultato.
Usa la funzione getGT di gt-next per tradurre le stringhe dei metadati:
import { getGT } from 'gt-next/server';
import { getI18NMetadata } from '@/lib/i18n-metadata';
export async function generateMetadata() {
const t = await getGT();
const i18nMeta = await getI18NMetadata('/about');
return {
title: t('About Us'),
description: t('Learn about our mission and team.'),
...i18nMeta,
};
}Questo ti offre titoli e descrizioni localizzati nei risultati di ricerca, migliorando significativamente il tasso di clic per le ricerche in lingue diverse dall’inglese.
6. Sitemap multilingue
Una sitemap aiuta i motori di ricerca a individuare tutte le tue pagine, inclusa ogni versione linguistica. Per i siti multilingue, dovresti includere anche le annotazioni hreflang nella sitemap.
Next.js supporta le sitemap generate programmaticamente tramite un file sitemap.ts:
import { MetadataRoute } from 'next';
const BASE_URL = 'https://example.com';
const LOCALES = ['en', 'fr', 'es'];
const DEFAULT_LOCALE = 'en';
const PAGES = ['/', '/about', '/blog', '/contact'];
export default function sitemap(): MetadataRoute.Sitemap {
return PAGES.flatMap((path) => {
const getUrl = (locale: string) => {
const prefix = locale === DEFAULT_LOCALE ? '' : `/${locale}`;
return `${BASE_URL}${prefix}${path === '/' ? '' : path}`;
};
const languages: Record<string, string> = {};
for (const locale of LOCALES) {
languages[locale] = getUrl(locale);
}
return LOCALES.map((locale) => ({
url: getUrl(locale),
lastModified: new Date(),
alternates: { languages },
}));
});
}Questo genera una sitemap con una voce per ogni pagina e per ogni impostazione regionale,
e ogni voce include annotazioni hreflang che rimandano a tutte le versioni linguistiche.
Checklist
Ecco un rapido riepilogo di quanto illustrato:
| Requisito SEO | Implementazione |
|---|---|
| Impostazione regionale nell'URL | createNextMiddleware() con segmento dinamico [locale] |
Attributo HTML lang | useLocale() nel layout radice |
| URL canonici | getLocale() + alternates.canonical della Metadata API di Next.js |
| Tag hreflang | alternates.languages della Metadata API di Next.js con tutte le impostazioni regionali supportate |
| Metadati tradotti | getGT() per i titoli e le descrizioni delle pagine |
| Sitemap multilingue | sitemap.ts con una voce per ogni impostazione regionale e alternative hreflang |
Passaggi successivi
- Quickstart di gt-next per configurare l'intero stack i18n
- Guida al middleware per la configurazione del routing
- Guida a SSG per generare pagine multilingue in modo statico
- Supporto RTL per le lingue da destra a sinistra