Comment charger les traductions depuis des fichiers dans Next.js (Pages Router) v16

Séparer le contenu traduisible du code

Problème

Coder en dur les chaînes de caractères destinées aux utilisateurs directement dans les composants crée un couplage étroit entre le contenu et le code. À chaque modification du texte, les développeurs doivent localiser et modifier les fichiers d'implémentation. L'ajout d'une deuxième langue nécessite de trouver chaque chaîne codée en dur et de l'envelopper dans une logique conditionnelle. Une troisième langue étend encore cette logique. Cette approche rend les flux de travail de traduction dépendants des déploiements de code et empêche les membres non techniques de l'équipe de mettre à jour le contenu de manière indépendante.

Au fur et à mesure que l'application se développe, la gestion des traductions devient de plus en plus difficile. Les chaînes dispersées dans des dizaines de composants sont difficiles à auditer, dupliquer ou mettre à jour de manière cohérente. Les traducteurs ne peuvent pas travailler en parallèle avec les développeurs car ils ont besoin d'accéder au code source lui-même.

Solution

Stocker tout le texte destiné aux utilisateurs dans des fichiers de ressources externes, organisés par langue, avec un fichier JSON par locale. Chaque message est identifié par une clé unique plutôt que par son texte littéral. Les composants référencent ces clés au lieu de chaînes codées en dur.

Charger le fichier de traduction approprié en fonction de la locale reçue de Next.js et transmettre les messages au fournisseur de react-intl. L'application peut ensuite changer de langue en chargeant un fichier différent sans modifier aucun code de composant. Cela découple le contenu de l'implémentation, permettant aux traducteurs de travailler dans des fichiers JSON standard tandis que les développeurs référencent des clés de message stables.

Étapes

1. Créer des fichiers de traduction organisés par locale

Placer les messages de traduction dans des fichiers JSON séparés par locale. Chaque fichier contient des paires clé-valeur où les clés sont des identifiants stables et les valeurs sont les chaînes traduites pour cette langue.

{
"welcome": "Welcome back",
"greeting": "Hello, {name}",
"itemCount": "You have {count, plural, one {# item} other {# items}}"
}

Créez un fichier par locale prise en charge (par exemple, messages/en.json, messages/es.json, messages/fr.json) dans un répertoire messages à la racine de votre projet. Utilisez les mêmes clés dans tous les fichiers afin que react-intl puisse rechercher la traduction correcte pour la locale active.

2. Charger les messages dans getStaticProps

Lisez le fichier de traduction en fonction de la locale reçue de Next.js dans getStaticProps. Cela garantit que les messages sont disponibles côté serveur et transmis à la page en tant que props.

import { GetStaticProps } from "next";

export const getStaticProps: GetStaticProps = async (context) => {
  const locale = context.locale || "en";
  const messages = (await import(`../messages/${locale}.json`)).default;

  return {
    props: {
      messages,
    },
  };
};

L'import dynamique charge uniquement le fichier pour la locale actuelle. Next.js fournit automatiquement la valeur locale en fonction de l'URL ou des préférences de l'utilisateur.

3. Transmettre les messages à IntlProvider dans _app

Enveloppez votre composant racine avec IntlProvider et configurez-le avec la locale actuelle de l'utilisateur et les messages traduits correspondants. Accédez aux messages depuis pageProps afin que chaque page puisse fournir ses propres traductions.

import { AppProps } from "next/app";
import { IntlProvider } from "react-intl";
import { useRouter } from "next/router";

export default function App({ Component, pageProps }: AppProps) {
  const { locale, defaultLocale } = useRouter();

  return (
    <IntlProvider
      locale={locale || "en"}
      defaultLocale={defaultLocale || "en"}
      messages={pageProps.messages}
    >
      <Component {...pageProps} />
    </IntlProvider>
  );
}

Le provider rend les messages disponibles pour tous les composants de l'arborescence. Chaque page charge son propre fichier de messages via getStaticProps, et _app reçoit ces messages via pageProps.

4. Référencer les messages par clé dans les composants

Utilisez le composant FormattedMessage de react-intl ou le hook useIntl pour afficher du texte traduit. Référencez les messages par leur clé plutôt que de coder en dur les chaînes de caractères.

import { FormattedMessage, useIntl } from "react-intl";

export default function HomePage() {
  const intl = useIntl();
  const userName = "Alice";

  return (
    <div>
      <h1>
        <FormattedMessage id="welcome" />
      </h1>
      <p>
        <FormattedMessage id="greeting" values={{ name: userName }} />
      </p>
      <input placeholder={intl.formatMessage({ id: "searchPlaceholder" })} />
    </div>
  );
}

React-intl recherche et formate le message traduit à l'id donné. Si une traduction est manquante, il revient au defaultMessage s'il est fourni. Les variables transmises dans la prop values sont interpolées dans la chaîne de message.