gatsby-plugin-react-i18next icon indicating copy to clipboard operation
gatsby-plugin-react-i18next copied to clipboard

Doesn't work together with client routes and reach router

Open Lillvik opened this issue 4 years ago • 9 comments

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
    },
  ]
}

Lillvik avatar May 15 '21 14:05 Lillvik

I've just been bitten by this too and went down the matchPath Page options rabbit hole...

It seems that the problem is that this plugin hasn't been updated to handle the new Gatsby File System Routes API, so no amount of hacking the Page options is gonna help us.

However, I think I've got a working solution. The problem seems to be that the plugin doesn't set/update its additional languages pages (onCreatePage.ts) for these "wildcard" routes that have a defined matchPath -- you can see how the plugin does this for the builtin "404" wildcard path.

You can use/reference my fork with the change made at this commit.

If you want to try it for yourself, you can also use my fork in your package.json with "gatsby-plugin-react-i18next": "github:ozburo/gatsby-plugin-react-i18next#master",.

I'll be happy to submit a PR if this seems to be a good working fix for all concerned.

ozburo avatar May 18 '21 14:05 ozburo

Unfortunately I couldn't get it to work. How did you construct your onCreatePage and Reach Router in your Application and how did you configure the plugin in gatsby-config.js?

Lillvik avatar May 18 '21 17:05 Lillvik

My gatsby-plugin-react-i18next config is the same as in the docs, and I'm just using a [...].js catch-all route in my app, i'm not implementing anything w/ Reach Router.

Essentially, in my case, I need the plugin to create all the langs prefixes, i.e. /fr/* for my /* catch-all, which is what that page's matchPath is.

I figured this might be a fix that only works in my case, but I'll thought I'd share since there doesn't seem to be much action around here.

I had to fork and hack around with the plugin locally in my Gatsby project to find some kinda solution.

ozburo avatar May 18 '21 17:05 ozburo

This is getting interesting...

I just had a little play around, i.e. using Reach Router in your Client-Only route (like they show in the Gatsby docs), instead of just using a conditional render in my [...].js file based on the incoming props.

It looks like there's a limitation w/ Reach Router, i.e. "No complex routes" which we need so we can catch the lang partial provided by this plugin, i.e. /fr/app/profile

What I did then is simply doubled up the Router component to catch both routes with and without the language prefix.

This is my test /app/[...].js file:

import React from "react"
import { graphql } from "gatsby"
import { Router } from "@reach/router"
import Layout from "../../components/layout"

const App = () => {
  return (
    <Layout>
      <Router basepath="/:lang/app">
        <Profile path="/profile" />
        <Details path="/details" />
        <Login path="/login" />
        <Default path="/" />
      </Router>
      <Router basepath="/app">
        <Profile path="/profile" />
        <Details path="/details" />
        <Login path="/login" />
        <Default path="/" />
      </Router>
    </Layout>
  )
}

export const query = graphql`
  query($language: String!) {
    locales: allLocale(filter: { language: { eq: $language } }) {
      edges {
        node {
          ns
          data
          language
        }
      }
    }
  }
`

export default App

const Profile = () => {
  return <div>PROFILE</div>
}

const Details = () => {
  return <div>DETAILS</div>
}

const Login = () => {
  return <div>LOGIN</div>
}

const Default = () => {
  return <div>DEFAULT</div>
}

This seems to work for me, using my fork/fix.

Hope that helps some.

ozburo avatar May 18 '21 22:05 ozburo

Thanks, it's really good to here that you've managed to get it to work. Unfortunately, I've tried a similar approach before and tried your example now in my solution but I still get "NOT FOUND", hence there must be something that I'm doing different. Do you have a repository with your solution that you can share?

Lillvik avatar May 24 '21 09:05 Lillvik

Does this help? (no custom plugin) https://stackoverflow.com/questions/67242212/gatsby-cant-find-client-routes-when-using-gatsby-plugin-react-i18next/69905274#69905274

bebbi avatar Nov 09 '21 21:11 bebbi

Am facing the same issue. I tried the approaches specified above however, unfortunately, it is not working. Am getting route NOT FOUND error. Any updates on this ?

nithyananthan-s02 avatar Mar 06 '22 15:03 nithyananthan-s02

In case anyone else is still struggling with this: Try adding your custom route to the pages config option like so (de is the default language in my case):

pages: [
    {
        matchPath: '/:lang?/client-route/:someParameter',
        getLanguageFromPath: true,
        languages: ['de', 'en'],
    }
]

c0necto avatar May 12 '23 07:05 c0necto

pages: [
    {
        matchPath: '/:lang?/client-route/:someParameter',
        getLanguageFromPath: true,
        languages: ['de', 'en'],
    }
]

unfortunately, this won't work

ChiuMungZitAlexander avatar Aug 01 '23 03:08 ChiuMungZitAlexander