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

Next.js + next-i18next切换语言时页面自动重载问题求助

解决Next.js + next-i18next切换语言时页面重载并回到顶部的问题

我看了你的代码,核心问题出在语言切换的实现方式上——你现在用router.push来切换locale,这会触发Next.js加载对应locale的静态页面(因为你的首页用了getStaticProps,Next.js会为每个locale生成独立的静态文件),所以必然导致页面重载、回到顶部。

下面给你两种解决思路,按需选择:

方案一:直接在客户端切换语言(不修改URL)

这是最简单的方式,用next-i18next提供的i18n实例直接切换语言,完全避免路由跳转,组件只会重新渲染:

修改你的Options组件,引入useTranslation获取i18n对象,替换掉router.push:

import { useTranslation } from 'next-i18next'; // 别忘了导入

const Options = () => {
    const router = useRouter();
    const { theme, resolvedTheme, setTheme } = useTheme();
    const loaded = useLoaded();
    const { i18n } = useTranslation(); // 获取i18n实例

    return (
        <StyledOptions>
            <ul>
                <li>
                    <IconButton onClick={() => setTheme(resolvedTheme === 'light' ? 'dark':'light')} >
                        {theme === 'dark' && loaded ? <MdLightMode /> : <MdDarkMode />}
                    </IconButton>
                </li>
                <li onClick={() => i18n.changeLanguage('cs')}> {/* 替换为changeLanguage */}
                    CZK
                </li>
                <li onClick={() => i18n.changeLanguage('en')}> {/* 替换为changeLanguage */}
                    ENG
                </li>
            </ul>
        </StyledOptions>
    );
};

export default Options;

这种方式的优势是:

  • 完全无页面重载,组件只重新渲染翻译内容
  • 保持当前滚动位置不变
  • 代码改动极小

方案二:切换语言同时更新URL(保持locale在地址栏可见)

如果需要地址栏显示对应locale(比如/cs或/en),可以结合i18n.changeLanguage和router.replace,并加上shallow: true参数(避免触发页面重载和重新执行getStaticProps):

修改Options组件的点击事件:

import { useTranslation } from 'next-i18next';

const Options = () => {
    const router = useRouter();
    const { theme, resolvedTheme, setTheme } = useTheme();
    const loaded = useLoaded();
    const { i18n } = useTranslation();

    // 封装语言切换逻辑
    const switchLanguage = async (lang: string) => {
        await i18n.changeLanguage(lang);
        // 用replace更新路由,shallow: true确保只在客户端更新,不触发页面重载
        router.replace(router.pathname, router.asPath, { locale: lang, shallow: true });
    };

    return (
        <StyledOptions>
            <ul>
                <li>
                    <IconButton onClick={() => setTheme(resolvedTheme === 'light' ? 'dark':'light')} >
                        {theme === 'dark' && loaded ? <MdLightMode /> : <MdDarkMode />}
                    </IconButton>
                </li>
                <li onClick={() => switchLanguage('cs')}>
                    CZK
                </li>
                <li onClick={() => switchLanguage('en')}>
                    ENG
                </li>
            </ul>
        </StyledOptions>
    );
};

export default Options;

注意:shallow: true只适用于同一页面内的路由变化,你的场景是首页切换语言,完全符合这个条件。

额外检查点

确保你的_app.tsx已经正确用appWithTranslation高阶组件包裹,这是next-i18next正常工作的前提:

import { appWithTranslation } from 'next-i18next';

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

export default appWithTranslation(MyApp);

你的getStaticProps配置是正确的,serverSideTranslations已经正确注入了翻译资源,不需要改动。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 00:09:06