使用Next.js和next-intl重写区域设置

jobtbby3  于 2023-10-18  发布在  其他
关注(0)|答案(2)|浏览(126)

我目前正在使用Next.js(v13.5.4)next-intl(v3.0.0-beta.19)进行国际化。我的目标是将语言环境的URL结构从en-GB修改为en/UK
我已经用应用程序路由器设置了Next,并在server component guide之后初始化了next-intl。
下面是我在next.config.js中设置URL重写的尝试:

/** @type {import('next').NextConfig} */
const nextConfig = {
    async rewrites() {
        return {
            beforeFiles: [
                {
                    source: "/en/uk/:path*",
                    destination: "/en-GB/:path*",
                }
            ]
        }
    },
}

module.exports = withNextIntl(nextConfig);

使用此配置,导航到http://localhost:3000/en-GB的功能与预期相同。但是,访问http://localhost:3000/en/uk会重定向到http://localhost:3000/en-GB/en/uk(其中en-GB是我访问的最后一个区域设置)。
下面是我的中间件:

import createMiddleware from 'next-intl/middleware';

export default createMiddleware({
    locales: ['de-DE', 'en-GB'],
    defaultLocale: ''
});

export const config = {
    matcher: ['/((?!api|_next|_vercel|.*\\..*).*)']
};

尝试解决:

  • 已从重写配置中删除beforeFiles段。
  • 在我的配置中加入了locale: false
  • 将中间件中的匹配器调整为matcher: ['/((?!api|en/uk|_next|_vercel|.*\\..*).*)'],导致错误:* 错误:找不到next-intl locale,请配置中间件。*

任何见解,替代解决方案或建议将不胜感激。

yqyhoc1h

yqyhoc1h1#

看起来我走在正确的道路上,但我的中间件中缺少了这一部分:

export function middleware(request: NextRequest) {
    return NextResponse.next();
}

下面是URL重写工作的最终结果:

  • src/middleware.ts*
import createMiddleware from 'next-intl/middleware';
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
    return NextResponse.next();
}

export default createMiddleware({
    locales: ['de-DE', 'en-GB'],
    defaultLocale: ''
});

export const config = {
    // Skip all paths that should not be internationalized.
    matcher: ['/((?!api|_next|_vercel|.*\\..*).*)']
};
  • next.config.js*
/** @type {import('next').NextConfig} */
const nextConfig = {
    async rewrites() {
        return [
            {
                source: '/en/uk/:path*',
                destination: '/en-GB/:path*',
            },
            {
                source: '/de/de/:path*',
                destination: '/de-DE/:path*',
            }
        ]

    },
}

module.exports = nextConfig

重写配置中的beforeFiles不需要,所以我删除了它。

3wabscal

3wabscal2#

我之前的回答只适用于客户端组件。为了让它与服务器组件一起工作,你需要在中间件中重写url。这是因为next.js优先考虑中间件中的重定向和重写,而不是配置中的重写。下面是我的中间件:

import createIntlMiddleware from 'next-intl/middleware';
import { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
    const localeMapping = {
        'en/uk': 'en-GB',
        'de/de': 'de-DE',
    };
    let modifiedRequest = request;

    // URL Rewrites
    for (const [srcPath, targetPath] of Object.entries(localeMapping)) {
        if (request.nextUrl.pathname.startsWith(`/${srcPath}`)) {
            const remainingPath = request.nextUrl.pathname.replace(`/${srcPath}`, '');
            const newUrl = new URL(`/${targetPath}${remainingPath}`, request.url);
            modifiedRequest = new NextRequest(newUrl, request);
            break;
        }
    }

    const locales = Object.values(localeMapping);

    // Translations middleware logic
    const defaultLocale = modifiedRequest.headers.get('x-default-locale') || 'en-GB';
    const handleI18nRouting = createIntlMiddleware({
        locales,
        defaultLocale
    });

    const response = handleI18nRouting(modifiedRequest);
    response.headers.set('x-default-locale', defaultLocale);

    return response;
}

export const config = {
    // Skip all paths that should not be internationalized.
    matcher: ['/((?!api|_next|_vercel|.*\\..*).*)']
};

相关问题