【问题标题】:next-i18next with next-rewrite does not work with root page rewrite path带有 next-rewrite 的 next-i18next 不适用于根页面重写路径
【发布时间】:2021-06-15 08:52:06
【问题描述】:

我们有一个现有的应用程序,其中根 "/" 默认重定向到 "/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 的所有页面级文件的需要。

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

  • 终端没有错误。
  • 网络选项卡在"/" 的根路由上显示404 错误

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

是 _app 或 _document 文件中的内容吗?

  • 如果我直接导​​航到/search,它可以正常加载,所以页面路由看起来没问题。

其他说明:

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

【问题讨论】:

  • 你的next.config.js是什么样的?
  • 更新@juliomalves
  • 删除了我的答案....browserstack 测试失败,没有重定向

标签: next.js next-i18next


【解决方案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;

【讨论】:

    猜你喜欢
    • 2023-02-21
    • 2015-08-04
    • 2022-01-04
    • 2021-06-06
    • 2021-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多