Gatsby can't find client routes when using gatsby-plugin-react-i18next

1.2k Views Asked by At

I'm using client routes in Gatsby together with gatsby-plugin-react-i18next. When I'm trying to access one of the client routes while not using the default language, e.g. the url is prefixed with /sv, then I get that the route doesn't exists. If I add the prefix /sv to the router basepath, the Default component/path is working but not the Profile component/path.

While using the default language without the /sv prefix, everything is working as expected.

src/pages/account.tsx

<Router basepath={'/account'}>
  <AccountRoute path="/profile" component={Profile} />
  <Default path="/" />
</Router>

gatsby-node.js

exports.onCreatePage = async ({ page, actions }) => {
  const { createPage } = actions
  if (page.path.match(/^\/account/)) {
    page.matchPath = "/account/*"

    createPage(page)
  }
}

I've also tried to add the prefix /sv to the matchPath in gatsby-node.js but then I'm redirected to double prefixes /sv/sv route that doesn't exists. If I tell gatsby-plugin-react-i18next to not generate language pages for the account pages, I get the same result.

gatsby-config.js

{
  resolve: `gatsby-plugin-react-i18next`,
  options: {
    ...
  },
  pages: [
    {
      matchPath: '/:lang?/account/(.*)',
      getLanguageFromPath: true
    },
  ]
}
1

There are 1 best solutions below

2
On

We want to solve:

  1. getting the lang prefix to work
  2. getting the default page (no lang prefix) to work

For this, I currently used this solution:

gatsby-node.js:

function langPrefix(page) {
  return page.context.language === page.context.i18n.defaultLanguage &&
    !page.context.i18n.generateDefaultLanguagePage
    ? ''
    : `/${page.context.language}`
}



exports.onCreatePage = ({ page, actions }) => {
  const { createPage } = actions
  // Removing the ^ skips an optional /:lang prefix
  if (page.path.match(/\/app/)) {
    // adding lang if it's not the default page.
    page.matchPath = `${langPrefix(page)}/app/*`
    createPage(page)
  }
}

Additionally, I duplicated routes to handle the cases with and without lang prefix:

<...>
  {/* Version for default language (no /:lang/ in path) */}
  <Router basepath={`/app`}>
    <ViewerWrapper path="/:myProp" />
  </Router>
  {/* Version for explicit language (/:lang/ in path) */}
  <Router basepath={`/:lang/app`}>
    <ViewerWrapper path="/:myProp" />
  </Router>
</...>

Now keep the simplifications coming :)

Props to Mario Skrlec and ozburo for their approaches.