Gatsby: Document how to create multilingual 404 pages

Created on 25 Apr 2018  Β·  16Comments  Β·  Source: gatsbyjs/gatsby

Description

In our current project, we are working on a multilingual website with 2 languages. One of our requirement includes to have localised 404 pages. Instead of translating the content and layout on client-side, I would like to render a distinct 404 page for each language, like we do for normal pages with createPage. We host our website on Netlify, which describes how to set up custom 404 pages here. https://www.netlify.com/docs/redirects/#custom-404

For a short summary of the Netlify behaviour: They use rules set in the _redirects file to rewrite (not redirect) any incorrect path to the according 404 page.

Unfortunately, this seems not to be compatible with Gatsby. According to the following code in production-app.js, it does a look up on the pages existing within Gatsby and if it doesn't find it, it will statically fetch and render the 404.html component. Yet the "incorrect" path would have already returned the correct 404 page served by Netlifys rewrite rule.

...
if (loader.getPage(props.location.pathname)) {
  return createElement(ComponentRenderer, {
    page: true,
    ...props
  });
} else {
  return createElement(ComponentRenderer, {
    page: true,
    location: { pathname: `/404.html` }
  });
}
...

Steps to reproduce

  1. Start with a plain gatsby starter
  2. Create two error pages, for example /404.jsx and /en/404.jsx
  3. Install the gatsby-plugin-netlify
  4. Add a custom _redirects file for Netlify and add the following:
/en/*   /en/404.html    404
/*        /404.html    404

According to this, every 404 underneath /en/... should result in the /en/404.html and everything else should end up with /404.html.

  1. Deploy it to Netlify.
  2. Enter example.com/en/not-existing-page
  3. You will see very quickly the /en/404.html flicking up (by the Netlify rewrite) and then you'll get the /404.html set by Gatsby.

Expected result

I would like to get the /en/404.html. Or more generally, I would like Gatsby to be more flexible on 404 pages.

Actual result

You receive the /404.html.

Environment

documentation question or discussion

Most helpful comment

Good news: this is already possible! Using matchPath you can serve a specific 404 page for any matched path. Since @manuelbieh has shared his repo, I've created a commit which shows how you can do this: https://github.com/davidbailey00/manuelbieh.de/commit/62714633fb13b6e04c9e24f587114419299af946

Sorry everyone for taking so long to give a proper reply! I've renamed the issue title, since we need to document how to do this better :)

TL;DR: before calling createPage, check if the path is one of your specific 404 pages. If so, define the matchPath property to match the pages you want to redirect to that specific 404 page.

All 16 comments

I'm looking for a solution for this, too

I've used this rewrite on netlify which seems to work for me:

/en/* /en/404/index.html 404

Do you have actual /en/404.html in your build?

Yes, we do/did. As described, the english version flashes quickly but then gets replaced by the german (root) version.

Strange that it's working for you... Gatsby renders always the 404.html if a route was not found in it's own route map. (see code above) To my understanding, the Netlify redirect works for an initial page hit but not subsequently, as it will be overridden. Or am I missing something?

for me the same just deployed a modified gatsby-starter-blog having needed files like

| |____
| | |____de
| | | |____404.js
| | | |____index.js
| | |____en
| | | |____404.js
| | | |____index.js
| | |____hello-world
| | | |____index.md
| | | |____salty_egg.jpg
| | |____hi-folks
| | | |____index.md
| | |____index.js
| | |____my-second-post
| | | |____index.md

now i get 404.html like

Page Not found
Looks like you've followed a broken link or entered a URL that doesn't exist on this site.

first try included the original src/pages/404.js from gatsby-starter-blog where it would show my custom 404 and then gatsby's
when i instead click on a non existent link gatsby 404 shows, then my custom and then again gatsby's where it stays..

is it possible to "just" add an option to disable gatsby's 404? would that solve it?

at least commenting out

if (loader.getPage(props.location.pathname)) {
  return createElement(ComponentRenderer, {
    page: true,
    ...props,
  })
// } else {
//   return createElement(ComponentRenderer, {
//     page: true,
//     location: { pathname: `/404.html` },
//   })
}

in node_modules/gatsby/cache-dir/production-app.js solved it
maybe changing to something like } else if (!options.disabled) { would be nice πŸ‘
but I don't know how to get options in this file and what other issues this might introduce?

I notice that this bug report has been up for some time - requesting the feature to optionally disable gatsby's 404 handling. Am using Contentful with Netlify and its extremely easy to create a custom 404 that can be edited by a Contentful editor, but the Gatsby default 404 will load itself shortly after it hits the custom error page.

Netlify seems to pull required plugins from elsewhere based on the contents of package.json too, so there is no straightforward solution like editing the production-app.js either; it will at least require gatsby to be forked in whole.

Similar issue:

Serving our site statically from S3, which allows you to choose a S3 object to be rendered if S3 returns a 4xx. Gatsby's error handling causes a double render of the error page when this happens.

When S3 returns the object, they do so with a 404 status. (See curl -v https://bench.co/not-a-page) Maybe Gatsby could check HTTP status before triggering its own 404 handling? That would help us separate HTTP response 404s from SPA 404s.

Hey everyone, thanks for all the information about this issue :+1: Currently I'm waiting on #8510 to be merged which should fix some of the problems with flickering (e.g. your comment @BlakeTurner), then I'll take a look and hopefully make Gatsby able to detect 404 redirects at the server-side.

Same issue:

I have the nginx conf:

  error_page 404 /404/index.html;

  location = /404/index.html {
    root /var/www/website/$geoip_base_url/;
    internal;
  }

where $geoip_base_url is a country-language combination like us-en.

So, I have a 404 page inside every counry-language folder like /us-en/404/index.html and would like to show a country-language specific 404 page without any redirects. So, after I reach any not found URL nginx shows the right 404 page but after a moment location changes from e.g. /x to e.g. /us-en/404/.

Just to update everyone, since this issue hasn't had much attention recently - I've assigned myself to implement this but at the moment I'm not sure how soon I'll get round to doing it. Recently I've been working on reliability improvements and tests to core code + offline plugin - hopefully when that's all polished up - perhaps in a few weeks - and if I'm not working on anything else by then, I'll be able to start implementing this!

Happy to see I'm not alone with that problem. 404 pages are created in /de/404 and /en/404 but the actual 404 page doesn't care about that. Source:
https://github.com/manuelbieh/manuelbieh.de/tree/relaunch-v3

Sorry, I haven't had time to implement this feature last week, since I've been working on improvements to the offline plugin - I'll make this my priority when I'm next working on Gatsby. Thanks for providing your repo!

Good news: this is already possible! Using matchPath you can serve a specific 404 page for any matched path. Since @manuelbieh has shared his repo, I've created a commit which shows how you can do this: https://github.com/davidbailey00/manuelbieh.de/commit/62714633fb13b6e04c9e24f587114419299af946

Sorry everyone for taking so long to give a proper reply! I've renamed the issue title, since we need to document how to do this better :)

TL;DR: before calling createPage, check if the path is one of your specific 404 pages. If so, define the matchPath property to match the pages you want to redirect to that specific 404 page.

πŸŽ‰ πŸŽ‰ πŸŽ‰ you're my hero @davidbailey00 πŸ₯‡

TL;DR: before calling createPage, check if the path is one of your specific 404 pages. If so, define the matchPath property to match the pages you want to redirect to that specific 404 page.

Just tried it and it's working great so far πŸŽ‰ thanks for figuring out and sharing πŸ‘ πŸ’―

Proof:
gaiama.org/en/nonexistendpage
gaiama.org/de/nonexistendpage

Now I can finally make this page more beautiful and useful, as it wasn't visible before πŸ˜‰

So except for better and more visible documentation I would say the problem is solved, right?!

Hiya!

This issue has gone quiet. Spooky quiet. πŸ‘»

We get a lot of issues, so we currently close issues after 30 days of inactivity. It’s been at least 20 days since the last update here.

If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!

Thanks for being a part of the Gatsby community! πŸ’ͺπŸ’œ

@davidbailey00 This is not yet in the docs, is it? :)

@patricknick not yet, I'll just work on that!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

antoinerousseau picture antoinerousseau  Β·  139Comments

OleksandrSachuk picture OleksandrSachuk  Β·  75Comments

blainekasten picture blainekasten  Β·  130Comments

jonathan-chin picture jonathan-chin  Β·  69Comments

freiksenet picture freiksenet  Β·  131Comments