Next.js自动将带有语言代码的遗留URL(如以“-es”结尾的URL)重定向到核心页面,并通过i18next实现自动翻译

前端开发 2026-07-10

我们在Next.js中结合 i18next,对一个带有EN/ES双语的应用进行了重构。它可以工作,但需要支持遗留应用中启用西语的URL,例如 /page1-es/page2-es,使其能重定向到新应用的 /page1page2,并在组件内实现自动的 i18next 翻译。

由于在重定向时无法传递自定义数据(URL也不显示任何参数),我当前的代码是:在Next.js的 not-found.tsx 中指定对相应新页面的重定向,同时设置一个 sessionStorage 属性,稍后可以从拥有 i18next App基础架构的组件中取到该属性。

export default function Custom404(){ // not-found.tsx

    const pathname = usePathname();

    const ES_AUTO_REDIRECTS = new Map([
        ["/page1-es", "/page1"],
        ["/page2-es", "/page2"]
    ]);

    useEffect(() => {
        // sessionStorage requires an Effect as it is only available in the browser
        let esRedirectURL = ES_AUTO_REDIRECTS.get(pathname);
        if (esRedirectURL) {
            // Manually change language to ES via sessionStorage attribute and redirect to the appropriate page
            sessionStorage.setItem("init-language", "es");
            redirect(esRedirectURL);
        } else {
            // For any general 404 Not Found errors, always redirect to home page
            redirect('/');
        }
    }, []);

    return (
        <div></div>
    )

常规页面接着会有自己的 TranslationProvider,并调用各自的组件,这些组件会读取此属性并在启动时设定语言,

      <TranslationsProvider
        namespaces={i18nNamespaces}
        locale={params.locale}>
        <App page="page1" />
      </TranslationsProvider>

在页面所连接的组件内部(页面/组件的链接关系未展示):

export const Page1Component = () => {

    const { i18n } = useTranslation(['appTranslations']);

    useEffect(() => {
        let initLanguage = sessionStorage.getItem("init-language");
        if (initLanguage) {
            i18n.changeLanguage(initLanguage);
            // Remove after use
            sessionStorage.removeItem("init-language");
        }
    }, []);

这可行,但会有闪烁,因为在重定向的Effect生效前,空白的Not Found页面会被快速显示。这个Effect会引入闪烁,但 sessionStorage 需要一个Effect(它需要浏览器环境,不能放在主代码中)。

是否有办法在不让Not Found出现闪烁的情况下完成这次重定向与翻译?404错误页不在应用的i18next基础设施内,也不属于其中。

最终结果应当是把URL改到核心URL,并在需要时完成内联翻译。

解决方案

我发现的唯一办法,是通过 next.config.tsredirects 部分,将重定向到一个临时的 ?lang=.. URL,然后再重定向一次到组件中不带 ?lang=.. 参数的干净URL。与之前类似,但至少没有空白页的闪烁,只有内容的闪烍,稍微好一些。

const nextConfig: NextConfig = {
  async redirects() {
      return [
        {
          source: '/page1-es',
          destination: '/page1?lang=es',
          permanent: true,
        },       
        /* etc. */

然后在组件中,

const pathname = usePathname();

useEffect(() => {
    const searchParams = new URLSearchParams(window.location.search);
    let langParam = searchParams.get("lang");
    if (langParam) {
        i18n.changeLanguage(langParam);
        redirect(pathname); // Redirect to the respective clean URL without the "?lang=.." URL param after processing
    }
}, []);
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章