next.js多语言站点 Sitemap 优化:如何避免重定向问题提升 SEO 表现
前言
你是不是也有过这样的烦恼?辛辛苦苦给多语言站点生成了 sitemap.xml,结果丢到 Ahrefs 或者 Google Search Console 一检查,跳出一堆“重定向问题”的警告?尤其是那种不带语言的链接,下面咱们以我的另外一个站点( solomakerstudio.com
),点进去一看,全都 301 重定向到默认语言(比如 solomakerstudio.com/en/
)。这不仅看着烦,还可能让搜索引擎觉得你的站点不够“友好”,SEO 效果打折扣。
别慌!这篇文章就来手把手教你怎么优化多语言站点的 sitemap.xml,彻底解决重定向问题,还能让你的站点在搜索引擎里表现得更出色。咱们会讲得尽量简单、接地气,操作步骤也超级实用,哪怕你是 SEO 小白也能轻松上手!
为什么 sitemap.xml 会有重定向问题?
先来搞清楚问题根源。很多多语言站点(比如用 /en
、/zh
这种子目录结构)都会把不带语言的链接(solomakerstudio.com/
)设置成自动重定向到默认语言(比如 /en/
)。这在用户体验上没啥问题,但到了 sitemap.xml 就容易出幺蛾子:
- 搜索引擎不爱重定向:你把
solomakerstudio.com/
塞进 sitemap.xml,爬虫访问时发现它跳转到/en/
,这多了一步“跳转”,爬虫效率降低,还可能觉得你的 sitemap 不够“直接”。 - SEO 工具报警:像
Ahrefs
、SEMrush
这些工具,看到sitemap
里的链接触发重定向,就会给你标个“问题”,看着就闹心。 - 重复内容风险:如果 sitemap 里同时有
/
和/en/
,搜索引擎可能误以为这是两块内容,影响页面权重。
所以,解决问题的核心思路就是:让 sitemap.xml 里只放最终的、可直接访问的链接,别放那些会跳转的“中间页”。
优化 sitemap.xml 的 4 个实用步骤
好了,废话不多说,咱们直接上干货!以下是优化多语言站点 sitemap.xml
的四个步骤,照着做,保证你的 sitemap
干净又高效。
步骤 1:只放带语言的链接
最重要的一招:sitemap.xml 里不要包含不带语言的链接(比如 solomakerstudio.com/
)。只放那些带语言子目录的最终页面,比如:
1 | <url> |
怎么做?
- 如果你用 CMS(比如 WordPress),检查 sitemap 生成插件(像 Yoast SEO、Rank Math)的设置,确保它只生成带语言子目录的链接。
- 如果是自定义脚本生成 sitemap,改下代码逻辑,过滤掉不带
/en/
、/zh/
的 URL这里咱们以我们的next.js项目为例子,需要在根目录中存放对应的sitemapt.tsx
文件,在对应的代码中编辑如下的脚本:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43import type { MetadataRoute } from 'next';
import type { MetadataRoute } from 'next';
import { appConfig } from '@/lib/appConfig';
// 辅助函数:生成带有语言前缀的URL
const getLocalizedUrl = (baseUrl: string, path: string, locale: string) => {
const localePath = `/${locale}`;
const routePath = path === '' ? '' : `/${path}`;
return `${baseUrl}${localePath}${routePath}`;
};
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
// 定义静态路由
const staticRoutes = [
{
path: '',
changeFrequency: 'daily' as const,
priority: 1,
},
{
path: 'tools',
changeFrequency: 'daily' as const,
priority: 0.9,
},
]
const sitemapData: MetadataRoute.Sitemap = [];
// 获取项目中支持的语言列表
const locales = appConfig.i18n.locales;
// 然后便利对应的语言,来生成目标语言下的页面链接
for (const locale of locales) {
// 1. 处理静态路由
staticRoutes.forEach(route => {
sitemapData.push({
url: getLocalizedUrl(BASE_URL, route.path, locale),
lastModified: new Date(),
changeFrequency: route.changeFrequency,
priority: route.priority,
});
});
}
// 最终生成的链接均带有对应的语言前缀
return sitemapData
}
小贴士:首页也一样!如果 solomakerstudio.com/
会跳转到 solomakerstudio.com/en/
,那 sitemap 里就只放 solomakerstudio.com/en/
。
步骤 2:加个 hreflang 标签,告诉搜索引擎语言关系
多语言站点得让搜索引擎知道哪些页面是同一个内容的“不同语言版本”,这时候 hreflang
标签就派上用场了。你可以在 sitemap.xml 里给每个 URL 加 hreflang
标签,像这样:
1 | <url> |
为什么要加?
- 告诉 Google 哪个页面是英文版、哪个是中文版,避免被误判为重复内容。
- 提高用户体验,搜索引擎会根据用户语言偏好推荐对应版本。
- 搜索引擎爬取我们站点是需要消耗资源的,可以想象一下,整个互联网上有数不尽的站点需要等待搜索引擎来抓取,如果我们的程序不提供对应的“舒服”的方式来让搜索引擎快速抓取,我们的站点就不能很好的暴露给到搜索引擎了!
怎么加?
- 如果用 WordPress,Yoast SEO 或者 Polylang 插件可以自动生成带
hreflang
的 sitemap。 - 如果是手动写 sitemap,确保 XML 里包含
xmlns:xhtml="http://www.w3.org/1999/xhtml"
命名空间。如下所示:
步骤 3:检查重定向用的是 301
不带语言的链接(比如 solomakerstudio.com/
)既然会跳转,那得确保它用的是 301 永久重定向,而不是 302 临时重定向。为什么?301 告诉搜索引擎“这个页面永远搬到新地址了”,SEO 权重传递更顺畅。
怎么查?
- 用浏览器的开发者工具(F12 -> 网络),访问
solomakerstudio.com/
,看状态码是不是 301。 - 或者用在线工具(比如 redirect-checker.org)测试一下。
怎么改?
如果你在 Nginx/Apache 服务器上配置重定向,检查配置代码,确保是 301。
比如 Nginx 配置:1
rewrite ^/$ /en/ permanent;
如果用 CMS,检查语言切换插件的设置,确保重定向类型是 301。\
这里咱们以
solomakerstudio.com
为例子(部署在vercel
上的,通过自定义的middleware.ts
中间件来实现的)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41import { NextRequest, NextResponse } from 'next/server';
import { verifyToken } from './lib/auth';
import createMiddleware from 'next-intl/middleware';
import { appConfig } from './lib/appConfig';
const intlMiddleware = createMiddleware({
locales: appConfig.i18n.locales,
defaultLocale: appConfig.i18n.defaultLocale,
localePrefix: 'always',
});
export function middleware(request: NextRequest) {
const { pathname, locale } = request.nextUrl;
// Handle root path (/) for 301 redirect based on Accept-Language
if (pathname === '/') {
const acceptLanguage = request.headers.get('accept-language') || '';
let targetLocale = ''; // Fallback to default locale
// Match language based on Accept-Language header
if (acceptLanguage.includes('zh')) {
targetLocale = 'zh';
} else if (acceptLanguage.includes('en')) {
targetLocale = 'en';
}else{
targetLocale = appConfig.i18n.defaultLocale;
}
// Perform 301 redirect to the target locale
const redirectUrl = new URL(`/${targetLocale}`, request.url);
return NextResponse.redirect(redirectUrl, 301);
}
return intlMiddleware(request);
}
export const config = {
matcher: [
'/((?!api|_next|.*\\..*).*)',
'/rss.xml',
'/:locale/rss.xml',
'/admin/:path*',
],
};
步骤 4:验证你的 sitemap.xml
优化完 sitemap.xml,别急着提交,先验证一下,确保没问题。
怎么验证?
- 用 Google Search Console 的“站点地图”功能,提交你的 sitemap.xml,过几天看“覆盖率”报告,有没有错误。
- 用 Ahrefs 的 Site Audit 功能,检查 sitemap 里的链接有没有重定向警告。
- 本地测试:用 XML 验证工具(比如 xmlvalidation.com)检查 sitemap 文件格式是否正确。
小贴士:提交到 Google Search Console 后,记得点“重新提交”,让爬虫尽快抓取新版本。下面是咱们调整之后,丢到ahrefs
上的抓取结果:
额外注意事项
优化 sitemap.xml 还有几个小细节,别忘了:
- 动态生成 sitemap:如果你的站点页面很多,建议用脚本或插件自动生成 sitemap,省时省力。
- 定期检查:站点更新后,sitemap 也要跟着更新,保持
<lastmod>
日期准确。 - 多语言插件:如果用 WordPress,WPML、Polylang 这些插件对多语言 sitemap 支持很好,配置一下就能省不少事。
总结
搞定多语言站点的 sitemap.xml 其实没那么复杂,核心就是:别放会跳转的链接,明确语言版本,加好 hreflang,检查 301。照着这四个步骤走,你的 sitemap 就能干干净净,Ahrefs 再也挑不出毛病,Google 爬虫也会更喜欢你的站点。
试试看吧!如果有啥具体问题(比如你的 CMS 咋配置,或者代码咋写),随时告诉我,我再帮你细化!