Skip to content

Commit aa303b1

Browse files
authored
Merge pull request #333 from InvolutionHell/chore/seo-single-hop-and-metadata
chore(seo): redirects 单跳 + root metadata hreflang,i18n 段化收尾
2 parents 6506c8d + 1e99a31 commit aa303b1

2 files changed

Lines changed: 52 additions & 35 deletions

File tree

app/layout.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,18 @@ export const metadata: Metadata = {
5353
creator: "longsizhuo",
5454
publisher: "Involution Hell",
5555
category: "Technology",
56+
// alternates 是 fallback,被 [locale] 段下的 generateMetadata 覆盖。
57+
// 默认 canonical 指 /zh(默认 locale 首页),不指 / 因为根路径会被
58+
// next-intl middleware 308 redirect,搜索引擎索引到 /zh 更直接。
59+
// languages 同时声明 hreflang,让 root metadata 应用到不在 [locale]
60+
// 下的路径(如 /sitemap.xml 详情页 fallback 时)也能正确给出语言关系。
5661
alternates: {
57-
canonical: "/",
62+
canonical: "/zh",
63+
languages: {
64+
"zh-CN": "/zh",
65+
"en-US": "/en",
66+
"x-default": "/zh",
67+
},
5868
},
5969
robots: {
6070
index: true,

next.config.mjs

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -53,154 +53,161 @@ const config = {
5353
async redirects() {
5454
// Option C IA 大重组:按读者意图分 learn / career / community / projects 四大顶层区。
5555
// 顺序敏感——Next.js 首匹配命中,特殊文件级 + cpp_backend 老名字必须排在 wildcard 前。
56+
//
57+
// 2026-05 i18n URL 段化(PR #330):所有 destination 都带 /zh/ 前缀
58+
// (默认 locale)。不带前缀的话会先 301 到 /docs/...,next-intl
59+
// middleware 再 308 到 /zh/docs/...,对 SEO 是两跳 redirect。直接
60+
// destination 写带前缀的 canonical URL 让搜索引擎和用户都单跳到位。
61+
// 英语用户由站内 <LocaleToggle /> 切到 /en/docs/...,cookie 同步偏好。
62+
// source 保持不带 locale 形式(匹配老 URL)。
5663
return [
5764
// ============= 特殊路径(必须在 wildcard 之前) =============
5865
// CommunityShare/RAG → learn/ai/foundation-models/rag (RAG 文件归 ai 主题)
5966
{
6067
source: "/docs/CommunityShare/RAG/rag",
61-
destination: "/docs/learn/ai/foundation-models/rag/rag",
68+
destination: "/zh/docs/learn/ai/foundation-models/rag/rag",
6269
statusCode: 301,
6370
},
6471
{
6572
source: "/docs/CommunityShare/RAG/embedding",
66-
destination: "/docs/learn/ai/foundation-models/rag/embedding",
73+
destination: "/zh/docs/learn/ai/foundation-models/rag/embedding",
6774
statusCode: 301,
6875
},
6976
{
7077
// 文件名顺手规范化:context_engineering_intro → context-engineering-intro
7178
source: "/docs/CommunityShare/RAG/context_engineering_intro",
7279
destination:
73-
"/docs/learn/ai/foundation-models/rag/context-engineering-intro",
80+
"/zh/docs/learn/ai/foundation-models/rag/context-engineering-intro",
7481
statusCode: 301,
7582
},
7683
// CommunityShare/Geek/leworldmodel → community/papers(paper summary 归社区论文)
7784
{
7885
source: "/docs/CommunityShare/Geek/leworldmodel",
79-
destination: "/docs/community/papers/leworldmodel",
86+
destination: "/zh/docs/community/papers/leworldmodel",
8087
statusCode: 301,
8188
},
8289
// CommunityShare/Amazing-AI-Tools 下两篇分家:tool review 归 tools,paper 归 papers
8390
{
8491
source: "/docs/CommunityShare/Amazing-AI-Tools/perplexity-comet",
85-
destination: "/docs/community/tools/perplexity-comet",
92+
destination: "/zh/docs/community/tools/perplexity-comet",
8693
statusCode: 301,
8794
},
8895
{
8996
source:
90-
"/docs/CommunityShare/Amazing-AI-Tools/prompt-repetition-improves-non-reasoning-llms",
97+
"/zh/docs/CommunityShare/Amazing-AI-Tools/prompt-repetition-improves-non-reasoning-llms",
9198
destination:
92-
"/docs/community/papers/prompt-repetition-improves-non-reasoning-llms",
99+
"/zh/docs/community/papers/prompt-repetition-improves-non-reasoning-llms",
93100
statusCode: 301,
94101
},
95102
// PPO 强化学习主题 → learn/ai/reinforcement-learning
96103
{
97104
source:
98-
"/docs/CommunityShare/Personal-Study-Notes/Reinforcement-Learning/ppo",
99-
destination: "/docs/learn/ai/reinforcement-learning/ppo",
105+
"/zh/docs/CommunityShare/Personal-Study-Notes/Reinforcement-Learning/ppo",
106+
destination: "/zh/docs/learn/ai/reinforcement-learning/ppo",
100107
statusCode: 301,
101108
},
102109
// swanlab 之前 test run 已移到 ai/misc-tools/(main commit d6d0a3d),现改到 community/tools
103110
{
104111
source: "/docs/ai/misc-tools/swanlab",
105-
destination: "/docs/community/tools/swanlab",
112+
destination: "/zh/docs/community/tools/swanlab",
106113
statusCode: 301,
107114
},
108115
// cpp_backend 老命名(下划线 / 大驼峰)→ learn/cs/cpp-backend/ (kebab-case)
109116
{
110117
source: "/docs/computer-science/cpp_backend/mempool_simple",
111-
destination: "/docs/learn/cs/cpp-backend/mempool-simple",
118+
destination: "/zh/docs/learn/cs/cpp-backend/mempool-simple",
112119
statusCode: 301,
113120
},
114121
{
115122
source:
116-
"/docs/computer-science/cpp_backend/Handwritten_pool_components/1_Handwritten_threadpool",
123+
"/zh/docs/computer-science/cpp_backend/Handwritten_pool_components/1_Handwritten_threadpool",
117124
destination:
118-
"/docs/learn/cs/cpp-backend/handwritten-pool-components/1-handwritten-threadpool",
125+
"/zh/docs/learn/cs/cpp-backend/handwritten-pool-components/1-handwritten-threadpool",
119126
statusCode: 301,
120127
},
121128
{
122129
source:
123-
"/docs/computer-science/cpp_backend/Handwritten_pool_components/2_Handwritten_mempool1",
130+
"/zh/docs/computer-science/cpp_backend/Handwritten_pool_components/2_Handwritten_mempool1",
124131
destination:
125-
"/docs/learn/cs/cpp-backend/handwritten-pool-components/2-handwritten-mempool1",
132+
"/zh/docs/learn/cs/cpp-backend/handwritten-pool-components/2-handwritten-mempool1",
126133
statusCode: 301,
127134
},
128135
{
129136
source: "/docs/computer-science/cpp_backend/easy_compile/1_cpp_libs",
130-
destination: "/docs/learn/cs/cpp-backend/easy-compile/1-cpp-libs",
137+
destination: "/zh/docs/learn/cs/cpp-backend/easy-compile/1-cpp-libs",
131138
statusCode: 301,
132139
},
133140
{
134141
source: "/docs/computer-science/cpp_backend/easy_compile/2_base_gcc",
135-
destination: "/docs/learn/cs/cpp-backend/easy-compile/2-base-gcc",
142+
destination: "/zh/docs/learn/cs/cpp-backend/easy-compile/2-base-gcc",
136143
statusCode: 301,
137144
},
138145
{
139146
source: "/docs/computer-science/cpp_backend/easy_compile/3_Make",
140-
destination: "/docs/learn/cs/cpp-backend/easy-compile/3-make",
147+
destination: "/zh/docs/learn/cs/cpp-backend/easy-compile/3-make",
141148
statusCode: 301,
142149
},
143150
{
144151
source: "/docs/computer-science/cpp_backend/easy_compile/4_CMake",
145-
destination: "/docs/learn/cs/cpp-backend/easy-compile/4-cmake",
152+
destination: "/zh/docs/learn/cs/cpp-backend/easy-compile/4-cmake",
146153
statusCode: 301,
147154
},
148155
{
149156
source: "/docs/computer-science/cpp_backend/easy_compile/5_vcpkg",
150-
destination: "/docs/learn/cs/cpp-backend/easy-compile/5-vcpkg",
157+
destination: "/zh/docs/learn/cs/cpp-backend/easy-compile/5-vcpkg",
151158
statusCode: 301,
152159
},
153160
// all-projects/ai-town → projects/ai-town (顶层化)
154161
{
155162
source: "/docs/all-projects/ai-town",
156-
destination: "/docs/projects/ai-town",
163+
destination: "/zh/docs/projects/ai-town",
157164
statusCode: 301,
158165
},
159166
// all-projects 裸路径本身也要兜底,防止指 /docs/all-projects 直接 404
160167
{
161168
source: "/docs/all-projects",
162-
destination: "/docs/projects",
169+
destination: "/zh/docs/projects",
163170
statusCode: 301,
164171
},
165172
// CommunityShare / Amazing-AI-Tools index 顶层
166173
{
167174
source: "/docs/CommunityShare",
168-
destination: "/docs/community",
175+
destination: "/zh/docs/community",
169176
statusCode: 301,
170177
},
171178
{
172179
source: "/docs/CommunityShare/Amazing-AI-Tools",
173-
destination: "/docs/community/tools",
180+
destination: "/zh/docs/community/tools",
174181
statusCode: 301,
175182
},
176183

177184
// ============= Wildcard 顶层区重命名 =============
178185
// 学科主目录:ai → learn/ai, computer-science → learn/cs
179186
{
180187
source: "/docs/ai/:path*",
181-
destination: "/docs/learn/ai/:path*",
188+
destination: "/zh/docs/learn/ai/:path*",
182189
statusCode: 301,
183190
},
184191
{
185192
source: "/docs/computer-science/:path*",
186-
destination: "/docs/learn/cs/:path*",
193+
destination: "/zh/docs/learn/cs/:path*",
187194
statusCode: 301,
188195
},
189196
// 求职场景 jobs/{interview-prep,event-keynote} → career/{interview-prep,events}
190197
{
191198
source: "/docs/jobs/interview-prep/:path*",
192-
destination: "/docs/career/interview-prep/:path*",
199+
destination: "/zh/docs/career/interview-prep/:path*",
193200
statusCode: 301,
194201
},
195202
{
196203
source: "/docs/jobs/event-keynote/:path*",
197-
destination: "/docs/career/events/:path*",
204+
destination: "/zh/docs/career/events/:path*",
198205
statusCode: 301,
199206
},
200207
// 项目 all-projects → projects
201208
{
202209
source: "/docs/all-projects/:path*",
203-
destination: "/docs/projects/:path*",
210+
destination: "/zh/docs/projects/:path*",
204211
statusCode: 301,
205212
},
206213
// CommunityShare 分家:其他按主题归 community/*
@@ -209,27 +216,27 @@ const config = {
209216
// 生成的 slug 映射做字面匹配,单跳 301 到正确拼音 URL。
210217
{
211218
source: "/docs/CommunityShare/Language/:path*",
212-
destination: "/docs/community/language/:path*",
219+
destination: "/zh/docs/community/language/:path*",
213220
statusCode: 301,
214221
},
215222
{
216223
source: "/docs/CommunityShare/Life/:path*",
217-
destination: "/docs/community/life/:path*",
224+
destination: "/zh/docs/community/life/:path*",
218225
statusCode: 301,
219226
},
220227
{
221228
source: "/docs/CommunityShare/MentalHealth/:path*",
222-
destination: "/docs/community/mental-health/:path*",
229+
destination: "/zh/docs/community/mental-health/:path*",
223230
statusCode: 301,
224231
},
225232
{
226233
source: "/docs/CommunityShare/Geek/:path*",
227-
destination: "/docs/community/dev-tips/:path*",
234+
destination: "/zh/docs/community/dev-tips/:path*",
228235
statusCode: 301,
229236
},
230237
{
231238
source: "/docs/CommunityShare/Amazing-AI-Tools/:path*",
232-
destination: "/docs/community/tools/:path*",
239+
destination: "/zh/docs/community/tools/:path*",
233240
statusCode: 301,
234241
},
235242
];

0 commit comments

Comments
 (0)