如何用Next.js的getStaticPaths&getStaticProps实现Strapi多语言博客
Next.js + Strapi 本地化详情页404问题修复
问题背景
当前使用Next.js和Strapi实现内容本地化,文件结构如下:
pages/ blog/ - [post].tsx - portfolio.tsx
- portfolio.tsx可根据当前locale正确获取对应语言的文章,卡片显示正常,但点击卡片进入[post].tsx详情页时,无论当前域名(波兰语对应localhost:3000,英语对应example.com:3000),均出现404错误。
- Strapi中同一篇文章的不同语言版本拥有独立ID(如波兰语版本ID为10,英语版本ID为12)。
- 卡片跳转链接为:
<Link href="/blog/${id}" locale={route.locale} />
现有代码的核心问题
1. getStaticPaths生成了无效路径
原代码中getStaticPaths仅请求单个locale的文章数据,然后为所有locale复用这些ID生成路径:
- 仅获取波兰语文章的ID(10、11),然后为英语locale生成
/en/blog/10、/en/blog/11等路径,但这些ID在英语版本中不存在,访问时触发404。 - 英语文章的真实ID(12、13)未被纳入paths,因此访问
/en/blog/12时,因fallback为false直接返回404。
2. getStaticProps缺少错误处理
原代码未处理API请求失败的情况,若请求到不存在的ID,会导致页面崩溃而非正确返回404。
修复方案
步骤1:修正getStaticPaths,生成全语言有效路径
遍历所有locale,分别获取每个语言下的文章ID,为每个locale生成对应的有效路径,确保每个路径的locale与文章ID匹配。
步骤2:优化getStaticProps,合并请求并添加错误处理
合并重复的API请求,同时增加请求失败时的404返回逻辑,避免页面崩溃。
完整修复代码
[post].tsx 修正后代码
export const getStaticPaths = async ({ locales }) => { // 遍历所有locale,获取对应语言的文章数据 const articlesByLocale = await Promise.all( locales.map(async (locale) => { const res = await fetch( `https://strapi.com/api/articles?locale=${locale}&populate=*` ); const data = await res.json(); return { locale, articles: data.data }; }) ); // 生成每个locale对应的有效路径 const paths = articlesByLocale.flatMap(({ locale, articles }) => articles.map((post) => ({ params: { post: post.id.toString() }, locale, })) ); return { paths, fallback: false, }; }; export const getStaticProps = async (context) => { const id = context.params.post; // 合并请求,一次性获取文章及blocks数据 const res = await fetch( `https://strapi.tincors.com/api/articles/${id}?populate[blocks][populate]=*` ); // 处理请求失败或文章不存在的情况 if (!res.ok) { return { notFound: true }; } const data = await res.json(); // 增加可选链避免空值报错 const block_data_slider = data.data.attributes.blocks[0]?.files?.data || []; return { props: { article: data.data, slider: block_data_slider, }, }; };
额外优化建议
如果希望用户通过统一的标识符(如slug)访问不同语言的文章(而非语言相关的ID),可以在Strapi中为文章添加全局唯一的slug字段(或本地化slug),然后:
- 将路由改为
[slug].tsx - 在getStaticPaths中基于slug生成路径
- 在getStaticProps中通过
locale和slug参数请求对应语言的文章:
// getStaticProps示例 const res = await fetch( `https://strapi.tincors.com/api/articles?filters[slug][$eq]=${slug}&locale=${context.locale}&populate[blocks][populate]=*` );
内容的提问来源于stack exchange,提问作者Evoworx
相关产品推荐
相关产品推荐

