=

Comment gérer l'internationalisation avec NextJS SSG

Emmanuel Gautier

Emmanuel Gautier / March 14, 2021

Générer statiquement un site avec le framework NextJS pour différentes langues n'est pas si simple. Le framework n'apporte pas un support claire pour ce type de cas d'usage et la documentation NextJS explique que le routing i18n n'est pas supporté pour le SSG.

Mettre en place le projet

Pour commencer, il nous faut créer un nouveau projet next avec le template with-react-intl

npx create-next-app -e with-react-intl

Si vous n'avez plus besoin de gérer des ressources traduites côté client, vous pouvez supprimer les lignes de la fonction getInitialProps et la partie pour la traduction dans la fonction render.

Le serveur pour le SSR est inutile si vous voulez seulement la partie SSG également. Vous vous supprimer la config tsconfig, le fichier server.ts et modifier votre package.json comme suivant :

"scripts": {
    "dev": "next dev",
    "build": "npm run extract:i18n && npm run compile:i18n && next build",
    "export": "next export",
    "extract:i18n": "formatjs extract '{pages,components}/*.{js,ts,tsx}' --format simple --id-interpolation-pattern '[sha512:contenthash:base64:6]' --out-file lang/en.json",
    "compile:i18n": "formatjs compile-folder --ast --format simple lang compiled-lang",
    "start": "next start"
  },

Static Site Generation (aka SSG) avec NextJS

Quand vous génerez votre site statiquement, il n'est plus possible d'utiliser l'entête de la requête du navigateur ou toute autre information du navigateur pour savoir quelle langue utiliser.

Nous avons besoin d'introduire une nouvelle variable d'environnement NEXT_LOCALE qui va contenir la locale du site géneré durant le process d'export.

Exemple de contenu dans un fichier .env.*

NEXT_LOCALE=fr

Vous pouvez maintenant utiliser la variable NEXT_LOCALE dans le fichier _app.tsx dans la fonction getInitialProps pour définir la langue.

const getInitialProps: typeof App.getInitialProps = async appContext => {
  const locale = appContext.router.locale || process.env.NEXT_LOCALE
  const [supportedLocale, messagePromise] = getMessages(locale)

  const [, messages, appProps] = await Promise.all([
    polyfill(supportedLocale),
    messagePromise,
    App.getInitialProps(appContext),
  ])

  return {
    ...(appProps as any),
    locale: supportedLocale,
    messages: messages.default,
  }
}

Grâce à cette variable et le changement fait, react-intl va maintenant utiliser la langue contenue dans la variable d'environnement. Les messages traduits vont être pris à partir de la bonne langue.

Maintenant, vous avez un site disponible en plusieurs langues. Vous pouvez construire votre site sur plusieurs noms de domaine également avec une gestion de plusieurs pipeline de build. Vous pouvez réaliser ce type d'implémentation avec des services comme Netlify, Vercel, ... etc.

Exemple généré pour deux langues et déployé avec Vercel :

Si vous souhaitez en savoir plus, vous pouvez jeter un oeil au Code Source