You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Next.js中读取Accept-language头,适配Strapi多语言API内容

解决方案:Next.js结合Strapi基于Accept-Language返回多语言内容

一、你的中间件问题修正

你的中间件逻辑方向是对的,但有两个小问题:

  1. match函数返回的是单个匹配的locale字符串,不是数组,变量名改成req.preferredLocale更准确
  2. Next.js的Pages Router和App Router中间件语法不同,需对应调整

Pages Router 修正后的中间件

import { match } from '@formatjs/intl-localematcher';
import Negotiator from 'negotiator';

export default function middleware(req, res, next) {
  const acceptLangHeader = req.headers['accept-language'] || 'en-US,en;q=0.5';
  const negotiator = new Negotiator({ headers: { 'accept-language': acceptLangHeader } });
  const userLangs = negotiator.languages();
  const supportedLocales = ['en-US', 'nl-NL', 'nl'];
  const defaultLocale = 'en-US';

  // 匹配到单个最优locale
  req.preferredLocale = match(userLangs, supportedLocales, defaultLocale);
  next();
}

App Router 中间件写法(适用Next.js 13+)

App Router的中间件不能直接修改req,需通过请求头传递偏好语言:

import { match } from '@formatjs/intl-localematcher';
import Negotiator from 'negotiator';
import { NextResponse } from 'next/server';

export function middleware(request) {
  const acceptLangHeader = request.headers.get('accept-language') || 'en-US,en;q=0.5';
  const negotiator = new Negotiator({ headers: { 'accept-language': acceptLangHeader } });
  const userLangs = negotiator.languages();
  const supportedLocales = ['en-US', 'nl-NL', 'nl'];
  const defaultLocale = 'en-US';

  const preferredLocale = match(userLangs, supportedLocales, defaultLocale);
  
  // 将偏好语言通过请求头传递给后续路由/组件
  const response = NextResponse.next();
  response.headers.set('x-preferred-locale', preferredLocale);
  return response;
}

二、结合Strapi API获取对应语言内容

Strapi启用国际化插件后,所有内容API都支持通过locale查询参数指定返回语言,比如GET /api/posts?locale=nl-NL。

Pages Router 示例(在getServerSideProps中使用)

export async function getServerSideProps(context) {
  // 从中间件设置的req.preferredLocale拿值
  const preferredLocale = context.req.preferredLocale;
  // 调用Strapi API时带上locale参数
  const res = await fetch(`${process.env.NEXT_PUBLIC_STRAPI_URL}/api/posts?locale=${preferredLocale}`);
  const data = await res.json();

  return {
    props: {
      posts: data.data,
      locale: preferredLocale
    }
  };
}

App Router 示例(Server Component中获取)

import { headers } from 'next/headers';

export default async function PostsPage() {
  // 从中间件设置的请求头拿偏好语言
  const headersList = headers();
  const preferredLocale = headersList.get('x-preferred-locale') || 'en-US';
  
  const res = await fetch(`${process.env.NEXT_PUBLIC_STRAPI_URL}/api/posts?locale=${preferredLocale}`, {
    next: { revalidate: 60 } // 可选:添加缓存策略
  });
  const data = await res.json();

  return (
    <div>
      <h1>Posts in {preferredLocale}</h1>
      {data.data.map(post => (
        <div key={post.id}>{post.attributes.title}</div>
      ))}
    </div>
  );
}

三、更轻量的替代方案(无需中间件)

如果不想依赖第三方包,可直接在数据获取逻辑里解析Accept-Language头:

function getPreferredLocale(acceptLangHeader, supportedLocales, defaultLocale) {
  if (!acceptLangHeader) return defaultLocale;
  
  // 解析头信息并按权重排序
  const langEntries = acceptLangHeader.split(',').map(entry => {
    const [lang, weight] = entry.trim().split(';q=');
    return { lang: lang.toLowerCase(), weight: weight ? parseFloat(weight) : 1.0 };
  }).sort((a, b) => b.weight - a.weight);

  // 匹配支持的locale
  for (const { lang } of langEntries) {
    const match = supportedLocales.find(locale => locale.toLowerCase().startsWith(lang));
    if (match) return match;
  }
  return defaultLocale;
}

// 在Server Component中使用
export default async function PostsPage() {
  const headersList = headers();
  const acceptLang = headersList.get('accept-language');
  const supportedLocales = ['en-US', 'nl-NL', 'nl'];
  const preferredLocale = getPreferredLocale(acceptLang, supportedLocales, 'en-US');
  
  const res = await fetch(`${process.env.NEXT_PUBLIC_STRAPI_URL}/api/posts?locale=${preferredLocale}`);
  const data = await res.json();

  return <div>{/* 渲染内容 */}</div>;
}

内容的提问来源于stack exchange,提问作者Samuel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 11:27:04