带有 next-rewrite 的 next-i18next 不适用于根页面重写路径

问题描述

我们有一个现有的应用,认情况下,根 "/"重定向"/search"。通过我们的 next-redirects.js 文件运行良好:

async function redirects() {
  return [
    {
      source: '/',destination: '/search',permanent: true,},];
}

我必须使用 next-i18next 实现对应用程序的翻译,以便我们可以使用 NextJS 进行文本翻译 + 开箱即用的路由。我已按照 next-i8next docs 中的步骤操作。我将 next-i18next.config.js 文件添加为:

const path = require('path');

module.exports = {
  i18n: {
    defaultLocale: 'en',locales: ['en','es'],localePath: path.resolve('./public/static/locales'),// custom path file route
};

next.config 看起来像:

const { i18n } = require('./next-i18next.config');

const defaultConfig = {
  env: {
    SOME_ENV,images: {
    deviceSizes: [980],domains: [
      'd1','d2',],i18n,redirects: require('./next-redirects'),webpack: (config,options) => {
    if (!options.isServer) {
      config.resolve.alias['@sentry/node'] = '@sentry/browser';
    }

    if (
      NODE_ENV === 'production'
    ) {
      config.plugins.push(
        new SentryWebpackPlugin({
          include: '.next',ignore: ['node_modules'],urlPrefix: '~/_next',release: VERCEL_GITHUB_COMMIT_SHA,})
      );
    }

    return config;
  },};

module.exports = withPlugins([withSourceMaps],defaultConfig);

根据 nextJS 文档,我们有一个 custom _app 文件appWithTranslation HOC 包裹,并且使用 getinitialProps 进行设置:

function MyApp({ Component,pageProps }) {
  const [mounted,setMounted] = useState(false);

  useEffect(() => {
    // Remove the server-side injected CSS.
    const jssstyles = document.querySelector('#jss-server-side');
    if (jssstyles) {
      jssstyles.parentNode.removeChild(jssstyles);
    }

    TagManager.initialize(tagManagerArgs);

    setMounted(true);
  },[]);

  
  const Layout = Component.Layout || Page;

  return (
    <>
      <Head>
        <link rel="icon" href="/favicon.png" type="image/ico" />
        <Meta name="viewport" content="width=device-width,initial-scale=1" />
      </Head>
      <AppProviders>
        <Context {...pageProps}>
          <Layout {...pageProps}>
            <>
              <Component {...pageProps} />
              <Feedback />
              <PageLoader />
            </>
          </Layout>
        </Context>
      </AppProviders>
    </>
  );
}

MyApp.getinitialProps = async ({ Component,ctx }) => {
  let pageProps = {};

  if (Component.getinitialProps) {
    pageProps = await Component.getinitialProps({ ctx });
  }

  const cookies = Cookie.parse(ctx?.req?.headers?.cookie || '');
  if (Object.keys(cookies).length) {
    const { token } = JSON.parse(cookies?.user || '{}');

    let user = null;
    if (token) {
      const { data } = await get('api/users',{ token });
      if (data) {
        user = data;
        user.token = token;
      }
    }

    pageProps.user = user;
    pageProps.cart = cookies?.cart;
    pageProps.defaultBilling = cookies?.defaultBilling;
    pageProps.reservationestimateItem = cookies?.reservationestimateItem;
    pageProps.reservationestimate = cookies?.reservationestimate;
  }

  return { pageProps };
};

export default appWithTranslation(MyApp);

我们有 _document 文件来处理一些情绪主题

export default class MyDocument extends Document {
  static async getinitialProps(ctx) {
    const initialProps = await Document.getinitialProps(ctx);
    const styles = extractCritical(initialProps.html);
    return {
      ...initialProps,styles: (
        <>
          {initialProps.styles}
          <style
            data-emotion-css={styles.ids.join(' ')}
            // eslint-disable-next-line react/no-danger
            dangerouslySetInnerHTML={{ __html: styles.css }}
          />
        </>
      ),};
  }

  render() {
    return (
      <Html lang="en">
        <Head />
        <body>
          <Main />
          <NextScript />
          <script
            type="text/javascript"
            src="https://js.stripe.com/v2/"
            async
          />
        </body>
      </Html>
    );
  }
}

// `getinitialProps` belongs to `_document` (instead of `_app`),// it's compatible with server-side generation (SSG).
MyDocument.getinitialProps = async ctx => {
  const sheets = new ServerStyleSheets();
  const originalRenderPage = ctx.renderPage;

  ctx.renderPage = () =>
    originalRenderPage({
      enhanceApp: App => props => sheets.collect(<App {...props} />),});

  const initialProps = await Document.getinitialProps(ctx);

  return {
    ...initialProps,// Styles fragment is rendered after the app and page rendering finish.
    styles: [
      ...React.Children.toArray(initialProps.styles),sheets.getStyleElement(),};
};

此时重定向逻辑应继续导航到 search 页面,其设置如下:

export const SearchPage = () => {
  const router = useRouter();
  const { t } = useTranslation('search');
  

  return (
    <>
      <Head>
        <title>{`${t('searchTitle')}`}</title>
        <Meta
          property="og:title"
          content={`${t('searchTitle')}`}
          key="title"
        />
        <Meta
          name="description"
          content={t('MetaDescription')}
        />
      </Head>
      <Search />
    </>
  );
};

SearchPage.namespace = 'SearchPage';

export const getStaticPaths = () => ({
  paths: [],// indicates that no page needs be created at build time
  fallback: 'blocking' // indicates the type of fallback
});
export const getStaticProps = async ({ locale }) => ({
  // exposes `_nextI18Next` as props which includes our namespaced files
  props: {
    ...await serverSideTranslations(locale,['common','search']),}
});

export default SearchPage;

搜索页面具有 getStaticPathsgetStaticProps 函数,根据 next-i18next 的所有页面文件的需要。

为什么此设置不再适用于重定向

这意味着重写不起作用。但是 i18n 怎么办呢?

它是否在 _app 或 _document 文件中?

  • 如果我直接导​​航到 /search,它可以正常加载,因此页面路由似乎没问题。

其他注意事项:

  • NextJS "next": "^10.0.2",
  • next-i18next "next-i18next": "^7.0.1",

解决方法

Next & Locales 似乎存在一些可能的问题... https://github.com/vercel/next.js/issues/20488 https://github.com/vercel/next.js/issues/18349

我的解决方法并不漂亮,但有效:

  1. 删除原来的 next-rewrite
  2. 添加一个新的 index.js 页面文件来处理 getServerSideProps 中的重定向:
const Index = () => null;

export async function getServerSideProps({ locale }) {
  return {
    redirect: {
      destination: `${locale !== 'en' ? `/${locale}` : ''}/search`,permanent: true,},};
}

export default Index;

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...