Page 404 multilingue - Gatsby.js
Tags: gatsby, intl, 404, seo
Published: 2022-01-21 08:36:40

Aujourd'hui, nous allons voir comment, en Gatsby.js, nous pouvons faire en sorte d'avoir une page 404 par langue. Par exemple, si nous cherchons à accéder à l'url : _{votresite}.com/en/page-qui-nexiste-pas_, le serveur renverra une page 404 différente de celle qu'il nous retournera si nous cherchons à accéder à l'url :
_{votresite}.com/fr/page-qui-nexiste-pas_


## Introduction :

En Gatsby.js il est très simple de mettre en place une page 404 pour l'intégralité du site. Pour cela, il nous suffit de créer une page *404.jsx/tsx* (souvent déjà générée dans les templates) dans le dossier ***pages***.

Mais dans ce cas, cette page sera la même pour toutes les langues. Nous nous souhaitons avoir une page spécifique par langue.


## Les solutions

**Approche 1 : Créer une page 404 par langue et faire une redirection** 

Une première approche (pas la meilleure), est de créer une page 404 par langue dans le dossier pages. 

Par exemple : 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jyhu0zgrf152s8an1rs9.png)

Nous pouvons alors réaliser une redirection vers cette page, dans la page 404.jsx, en fonction de la langue de l'utilisateur, grâce à ce code : 

```jsx
import { useEffect } from "react"

import { navigate } from "gatsby"

const getRedirectLanguage = () => {
  if (typeof navigator === `undefined`) {
    return "fr"
  }

  let languages = navigator.languages ?? [navigator.language]
  languages = languages.map((lang: string) => lang.toLowerCase())

  if (!languages) return "fr"

  let actualLanguage
  languages.forEach(lang => {
    if (lang.includes("fr")) {
      actualLanguage = "fr"
    } 
    if (lang.includes("en")) {
      actualLanguage = "en"
    } 
    if (lang.includes("de")) {
      actualLanguage = "de"
    } 
  })

  return actualLanguage ?? "fr"
}

const NotFoundPage = () => {
  useEffect(() => {
    const urlLang = getRedirectLanguage()

    navigate(`/${urlLang}/`, { replace: true })
  }, [])

  return null
}

export default NotFoundPage
```

Le problème est que l'utilisateur est redirigé, mais surtout il perd son url. Ce n'est pas un comportement souhaitable pour une page 404.


**Approche 2 : Utiliser le _**matchPath**_ API de Gatsby.js**

La bonne approche est d'utiliser le paramètre _matchPath_ de Gatsby.js. En reprenant la création d'une page 404 par langue dans le dossier pages et grâce à l'API _onCreatePage_ de Gatsby, nous pouvons, lors de leur création, modifier le _matchPath_ des pages 404.

Et si c'est une page 404, il nous suffit de changer son _matchPath_ par `/${langCode}/*`.
Ainsi, cette page sera affichée à chaque fois que le client cherche à accéder à une URL de la langue, sauf bien sûr pour les pages existantes.

Voici le code nécessaire pour réaliser cette modification de _matchPath_.

```jsx
exports.onCreatePage = async ({ page, actions }) => {
  const { createPage, deletePage } = actions

  if (page.path.match(/^\/[a-z]{2}\/404\/$/)) {
    const oldPage = { ...page }

    const language = page.path.split(`/`)[1]
    page.matchPath = `/${language}/*`

    deletePage(oldPage)
    createPage(page)
  }
}
```

Ce code modifiera donc le _**matchPath**_ de toutes les pages 404 dans toutes les langues, par exemple : /fr/404, /de/404, etc.


## Conclusions

Nous avons ainsi réussi à mettre en place une page 404 différente par langue grâce à l'API _**onCreatePage**_ de Gatsby.js.

Cela nous permet maintenant de créer une page 404 spécifique par langue, tout en gardant l'URL erroné.

## Source

Si vous le souhaitez, vous pouvez retrouver la documentation de Gatsby.js sur ce sujet ici :
https://www.gatsbyjs.com/docs/creating-prefixed-404-pages-for-different-languages/