17370845950

如何在 Next.js 13+ 中根据语言动态生成多语言 SEO 元数据

本文详解如何利用 next.js 的 `generatemetadata` 函数,结合国际化路由参数(如 `/en-us/` 或 `/pt-br/`),为不同语言版本页面动态注入定制化 `

`、`<meta name="description">`、open graph、robots 等 seo 元数据,提升多语言站点的搜索引擎可见性。<p>在 Next.js App Router(v13.4+)中,静态 metadata 对象无法响应路由参数(如语言标识 lang),因此不能直接用于多语言场景。正确方案是使用 <strong>generateMetadata 函数</strong>——它是一个异步、服务端执行的元数据生成器,可访问 params、searchParams 甚至 headers(),天然支持基于语言的条件逻辑。</p> <h3>✅ 正确实现方式:在 page.tsx 中使用 generateMetadata</h3> <p>假设你的国际化路由结构为 app/[lang]/page.tsx(例如 /en-US/ 和 /pt-BR/),请将元数据逻辑从 layout.tsx 移至对应页面文件,并按如下方式编写:</p><pre class="brush:php;toolbar:false;">// app/[lang]/page.tsx import { Metadata } from 'next'; const englishMetadata: Metadata = { title: { default: 'Brand', template: '%s | brand.xyz', }, description: 'Some description', openGraph: { title: 'Brand', description: 'Some description', url: 'https://brand.xyz', siteName: 'Brand', type: 'website', }, robots: { index: true, follow: true, googleBot: { index: true, follow: true, 'max-video-preview': -1, 'max-image-preview': 'large', 'max-snippet': -1, }, }, icons: { shortcut: '/favicon.png', }, keywords: 'events clothing, fashion, online shop', }; const portugueseMetadata: Metadata = { title: { default: 'Brand', template: '%s | brand.xyz', }, description: 'Alguma descrição', openGraph: { title: 'Brand', description: 'Alguma descrição', url: 'https://brand.xyz', siteName: 'Brand', type: 'website', }, robots: { index: true, follow: true, <img src="//public-space.oss-cn-hongkong.aliyucs.com/gz/827.jpg" />googleBot: { index: true, follow: true, 'max-video-preview': -1, 'max-image-preview': 'large', 'max-snippet': -1, }, }, icons: { shortcut: '/favicon.png', }, keywords: 'eventos, vestuário, moda, loja online', }; export async function generateMetadata({ params }: { params: { lang: string } }): Promise<Metadata> { // 注意:确保实际路由参数值与你配置的 locale key 一致(如 en-US / pt-BR) if (params.lang === 'pt-BR' || params.lang === 'pt') { return portugueseMetadata; } return englishMetadata; } export default function HomePage() { return <main>...</main>; }</pre><h3>⚠️ 关键注意事项</h3> <ul> <li> <strong>不要在 layout.tsx 中定义 metadata 或 generateMetadata 来处理语言切换</strong>:layout.tsx 是共享布局,其 params 不包含子路由的语言参数(除非你使用 app/[lang]/layout.tsx 并确保层级匹配);推荐将 generateMetadata 放在具体页面(如 page.tsx)或根布局 app/[lang]/layout.tsx 中,以准确捕获 lang。</li> <li> <strong>语言标识需与 i18n 配置对齐</strong>:检查 next.config.js 中 i18n.locales 是否包含 'en-US' 和 'pt-BR',并确认路由参数名(如 [lang])与实际 URL 一致。</li> <li> <strong>generateMetadata 必须是 async 函数</strong>:即使不执行异步操作,也需声明为 async,否则 Next.js 将忽略该函数。</li> <li> <strong>图标路径建议使用绝对 URL</strong>:/favicon.png 在多语言路径下仍可正常解析,但若需更健壮,可用 new URL('/favicon.png', 'https://brand.xyz')。</li> <li> <strong>SEO 增强建议</strong>:可进一步添加 <link rel="alternate" hreflang="..."> 标签(通过 alternates 字段),例如:<pre class="brush:php;toolbar:false;">alternates: { canonical: `https://brand.xyz/${params.lang}/`, languages: { 'en-US': 'https://brand.xyz/en-US/', 'pt-BR': 'https://brand.xyz/pt-BR/', }, }</pre></li> </ul> <p>通过 generateMetadata,你不仅能实现语言感知的元数据,还可轻松扩展为基于用户地理位置、设备类型甚至 A/B 测试分组的动态 SEO 策略——真正让元数据成为可编程的 SEO 资产。</p>