Gatsby: Ajouter un guide officiel pour l'internationalisation des sites Web avec Gatsby

CrĂ©Ă© le 4 fĂ©vr. 2018  Â·  74Commentaires  Â·  Source: gatsbyjs/gatsby

Voyant les réactions à mon commentaire sur un autre numéro , j'ai décidé d'ouvrir ce numéro.

Je pense que i18n est beaucoup plus difficile qu'il ne devrait l'ĂȘtre. Je n'ai trouvĂ© aucune documentation officielle ni aucun plug-in pour l'internationalisation du contenu sur les sites Web crĂ©Ă©s par Gatsby. Je suis tombĂ© sur jsLingui , qui semble rĂ©soudre la plupart des problĂšmes, mais il n'y a toujours pas de guides sur la maintenance, par exemple, des fichiers/pages de dĂ©marques dans diffĂ©rentes langues.

documentation

Commentaire le plus utile

Hé les gars, ça fait presque un an

J'ai rĂ©cemment publiĂ© le nouveau plugin gatsby gatsby-plugin-intl qui fait facilement de votre site Web gatsby un cadre d'internationalisation prĂȘt Ă  l'emploi.

DÉMO : https://gatsby-starter-default-intl.netlify.com

  • Cadre d'internationalisation prĂȘt Ă  l'emploi alimentĂ© par react-intl

  • Prend en charge la redirection automatique en fonction de la langue prĂ©fĂ©rĂ©e de l'utilisateur dans le navigateur

  • Prend en charge les routes d'URL multilingues dans un seul composant de page. Cela signifie que vous n'avez pas besoin de crĂ©er des pages distinctes telles que pages/en/index.js ou pages/ko/index.js .

  • Comme certains d'entre vous l'ont suggĂ©rĂ© ci-dessus, il regroupe dĂ©sormais uniquement la langue actuelle pendant la construction.

De plus, je tiens à mentionner que de nombreux exemples / démarreurs i18n sont en fait rendus cÎté client. Le meilleur moyen de vérifier si l'application est rendue en tant que SSR est de visualiser le code source et de vérifier si les textes localisés existent. Veuillez vérifier cette question lorsque vous internationalisez votre site Web gatsby pour le référencement.

Tous les 74 commentaires

Il y a cet article sur l'utilisation d'i18next avec GatsbyJS , qui est la méthode la plus avancée à ce jour pour moi.

Mais je n'ai pas l'impression que i18next soit la "voie statique".

À propos de l'article de blog, j'avais ces questions/rĂ©serves :
https://twitter.com/semdubois/status/930389055388508160

Il y a https://github.com/angeloocana/gatsby-plugin-i18n mais il a plusieurs limitations et il ne reçoit pas beaucoup d'activitĂ©/attention. Il pourrait ĂȘtre utile de le dĂ©placer dans le rĂ©fĂ©rentiel Gatsby. J'aimerais moi aussi une solution consolidĂ©e appropriĂ©e.

Je suis également tombé sur js lingui et cela semble prometteur, surtout avec la v2 qui vient de sortir.

J'essaye aussi de comprendre ça. L'utilisation de la méthode i18next sur le post est la plus pratique et la plus intuitive, mais il me reste deux questions...

  1. comment puis-je incorporer différents fichiers de démarques pour les langues comme dans la solution gatsby-plugin-i18n ?

  2. Cela renonce-t-il complÚtement au rendu statique du contenu ?

Pour info @angeloocana

Je vais écrire un bref résumé de la façon dont nous le gérons en ce moment en utilisant react-intl . Cette application n'est pas encore en production, nous pouvons donc encore rencontrer des problÚmes avec cette configuration, mais elle semble bien fonctionner jusqu'à présent.

Nous gardons presque tout notre contenu (qui a Ă©tĂ© migrĂ© de notre blog Wordpress) dans Contentful . Nous n'utilisons pas ses fonctionnalitĂ©s de traduction, mais Ă  la place nous avons un espace (une sorte de projet ou de dossier) par langue. Nous utilisons le plugin gatsby-source-contentful pour rĂ©cupĂ©rer ces donnĂ©es, cependant, auparavant, nous rĂ©cupĂ©rions et convertissions nous-mĂȘmes ces donnĂ©es en fichiers JSON et utilisions le plugin gatsby-source-filesystem (nous utilisions une structure de dossiers comme /en/blog/... , /de/blog/... ), donc peu importe que l'on utilise Contentful ou non, tant que chaque nƓud connaĂźt ses paramĂštres rĂ©gionaux.

Nous avons également du texte comme des étiquettes de boutons, des liens ou du contenu statique qui ne provient pas de Contentful, mais qui est plutÎt traduit dans Transifex et synchronisé avec les fichiers JSON qui sont stockés dans le référentiel. Pour cette partie, nous avions besoin d'utiliser une bibliothÚque i18n et avons décidé d'utiliser react-intl , simplement parce que je le connais déjà et je sais qu'il gÚre également le formatage des dates et des nombres. Voici comment nous l'avons configuré : https://github.com/gatsbyjs/gatsby/issues/3830#issuecomment -362710469. Nous utilisons ensuite, par exemple, intl.formatMessage lors de la génération de balises méta et <FormattedMessage /> composants <FormattedDate /> etc. dans les modÚles.

@szimek Si je vous comprends bien, alors vous avez react-intl gérer la traduction du texte du composant pendant que les messages sont dans des itinéraires codés en dur sous le répertoire des pages ?

Cela signifierait que les routes codĂ©es en dur sont les seules Ă  ĂȘtre rendues statiquement? Et les traductions inter-composantes i18n sont rendues dynamiquement ?

@deltaskelta Je ne suis pas sûr de comprendre votre question.

Nous n'avons pas de routage cÎté client personnalisé (comme décrit par exemple ici ) pour le moment, uniquement des pages générées statiquement. Lors de la génération d'une page post (nous générons également des pages index et category spécifiques aux paramÚtres régionaux et paginées en utilisant une version légÚrement modifiée du plugin gatsby-pagination ), nous sommes en utilisant le code suivant :

posts.edges.map(({ node }) => {
  const id = node.contentfulid;
  const locale = node.node_locale;

  return createPage({
    path: `/${locale}/blog/posts/${id}`,
    layout: locale,
    component: path.resolve('./src/templates/post-page.jsx'),
    context: {
      id,
      locale,
    },
  });
});

MĂȘme si vous avez dĂ©sactivĂ© JS, tout le contenu, y compris les balises META, est rendu dans la bonne langue.

De notre cÎté, nous utilisons i18next avec quelques ajustements

Les grands principes sont les suivants :

  • Les paramĂštres rĂ©gionaux sont disponibles sous forme .json fichiers /dist/ pendant la construction.
  • Nous travaillons sur une seule page qui produira autant de versions statiques que nous avons de langues, en utilisant onCreatePage (en gatsby-node.js ).
  • Les informations des pages (par exemple le chemin) sont centralisĂ©es dans un seul fichier.

ParamÚtres régionaux

Les traductions ont Ă©tĂ© principalement regroupĂ©es par page, avec un espace de noms (= fichier JSON) par page + un fichier global (pour les textes partagĂ©s tels que l'en-tĂȘte/le pied de page).

|- src/
  |- locales/
    |- en/
      |- foo.json
      |- bar.json
    |- fr/
      |- foo.json
      |- bar.json

Malheureusement, il n'y a pas de rechargement à chaud sur les modifications de locales 👎

i18suivant

i18next est initialisé avec la configuration suivante :

import i18n from "i18next";
import Backend from "i18next-xhr-backend";
import { reactI18nextModule } from "react-i18next";
import config from "config";  // Our custom configurations env-specifics

const NAMESPACES = [
  "foo",
  "bar",
  ...
];

export default function createI18n() {
  const options = {
    fallbackLng   : false,
    whitelist     : ["en", "fr"],
    ns            : NAMESPACES,
    debug         : config.debug,
    interpolation : {
      escapeValue : false
    },
    react         : {
      wait : true
    },
    backend       : {
      loadPath : `${config.pathPrefix}locales/{{lng}}/{{ns}}.json`
    },
    parseMissingKeyHandler : () => "",  // Display an empty string when missing/loading key
  };

  return i18n
    .use(Backend)
    .use(reactI18nextModule)
    .init(options);
}

Informations sur les pages

Avant de générer toutes les versions i18n de nos pages, nous avons besoin de connaßtre quelques informations que nous avons regroupées dans un fichier pagesInfos.js :

module.exports = {
  index : {
    id          : "index",
    namespace   : "home",
    path        : {
      fr : "/",
      en : "/en/"
    }
  },
  projects : {
    id          : "projects",
    namespace   : "projects",
    path        : {
      fr : "/nos-clients/",
      en : "/en/our-clients/"
    }
  },
  // etc...

OĂč les clĂ©s sont les noms de fichiers des pages et les espaces de noms sont les noms de fichiers des locales . Ils peuvent ĂȘtre diffĂ©rents

Dans ce cas:

|- src/
  |- pages/
    |- index.js
    |- projects.js
  |- locales/
    |- en/
      |- home.json
      |- projects.json
    |- fr/
      |- home.json
      |- projects.json

Et oĂč chemin sont les chemins de nos futures versions (langues) de nos pages.

Créer des pages

Avec le mĂȘme exemple que ci-dessus, notre objectif ici est de crĂ©er une version FR + EN des pages d'accueil et de projet.

Pour y arriver, nous avons créé une fonction dédiée :

/**
 * Generate a custom page informations
 * <strong i="15">@param</strong>  {Object} defaultInfos  Default informations generated by Gatsby
 * <strong i="16">@return</strong> {Object}               Customized page object
 */
function generatePagesInfos(defaultInfos) {
  const pageId = defaultInfos.jsonName.slice(0, -5);  // NOTE: Get pageId from "pageName.json"
  const pageInfos = pagesInfos[pageId];

  const pageFR = {
    ...defaultInfos,
    context : {
      pageId      : pageInfos.id,
      namespace   : pageInfos.namespace,
      language    : "fr"
    },
    path : pageInfos.path.fr
  };

  const pageEN = {
    ...defaultInfos,
    context : {
      pageId      : pageInfos.id,
      namespace   : pageInfos.namespace,
      language    : "en"
    },
    path : pageInfos.path.en
  };

  return [pageFR, pageEN];
}

Cet assistant sera ensuite utilisé lors du hook onCreatePage , en sélectionnant chaque page via une regex :

exports.onCreatePage = async ({ page, boundActionCreators }) => {
  const { createPage, deletePage } = boundActionCreators;

  return new Promise((resolve, reject) => {

    if (page.path.match(page.path.match(/^\/$/))) {
      const i18nPages = generatePagesInfos(page);
      deletePage(page);                         // Remove old default page
      i18nPages.map(page => createPage(page));  // Create custom i18n pages
    }

    if (page.path.match(/^\/projects\/?$/)) {
      const i18nPages = generatePagesInfos(page);
      deletePage(page);
      i18nPages.map(page => createPage(page));
    }

    // etc...

    resolve();
  });
}

Nous avons maintenant deux versions de chaque page, avec un chemin d'accĂšs personnalisĂ© (Ă  partir de notre fichier d'informations sur les pages). Vous avez peut-ĂȘtre remarquĂ© que nous transmettons une information language Ă  chaque page via pathContext . Cette valeur sera utilisĂ©e sur chaque page pour afficher la bonne langue.

Afficher la bonne langue

Nous utilisons la classe React pour les pages, le décorateur suivant connaßt automatiquement la langue de la page actuelle et met à jour i18n si nécessaire :

import React from "react";
import PropTypes from "prop-types";
import { i18n } from "context";    // Our custom context

/**
 * <strong i="10">@returns</strong> {React.PureComponent} Component with locales as proptypes
 */
export default function setLanguageFromPage() {

  return WrappedComponent => (
    class extends React.PureComponent {

      static propTypes = {
        pathContext : PropTypes.shape({
          language : PropTypes.string.isRequired
        })
      }

      componentDidMount() {
        const currentLanguage = i18n.language;
        const pageLanguage = this.props.pathContext.language;

        // First request
        if (!currentLanguage) {
          i18n.language = pageLanguage;
        }

        // Only update on language change
        if (currentLanguage !== pageLanguage) {
          i18n.changeLanguage(pageLanguage);
        }
      }

      render() {
        return <WrappedComponent {...this.props} />;
      }

    }
  );

}

Ensuite, appelez-le sur les pages :

@setLanguageFromPage()
export default class ProjectsPage extends React.PureComponent {
// ...

Pfew, tout ce que vous avez Ă  faire maintenant est d'utiliser la fonction de traduction de i18next.

Conclusion

👍 Un seul fichier source qui gĂ©nĂšre autant de versions que nĂ©cessaire pendant la construction
👍 Gestion facile de la sortie des pages
👍 Quelques efforts au dĂ©but, mais ensuite tout est simple

👎 Pas de rechargement à chaud pour les locales

J'ai l'impression que ce n'est pas vraiment le "mode de vie statique"... Mais c'est le mieux que nous ayons réussi à obtenir pour l'instant.

J'aimerais voir ce que vous en pensez et comment vous gérez cela.

PS. Poke @szimek , c'est ce que je voulais vous montrer il y a quelques jours :)

J'utilise @angeloocana https://github.com/angeloocana/gatsby-plugin-i18n + React-intl et ce n'est pas aussi compliqué que les méthodes ci-dessus, mais il y a quelques limitations (voir les problÚmes de repo) et je suis pas si heureux de React-intl. J'adorerais essayer https://github.com/lingui/js-lingui de @ tricoder42, je n'ai tout simplement pas eu le temps.

@monsieurnebo quel est le but d'exĂ©cuter deletePage juste avant createPage ? J'aime votre solution et j'ai essayĂ© de la mettre en Ɠuvre, mais j'ai quelques erreurs.

  • Soit j'obtiens un pathContext.language incorrect sans utiliser deletePage

  • ou j'obtiens une erreur de construction lorsque j'inclus deletePage comme votre exemple. (il dit TypeError: Cannot read property 'id' of undefined lorsque la construction arrive Ă  l'Ă©tape run graphql queries )

C'est la meilleure solution que j'ai vue jusqu'à présent.

@deltaskelta Content de voir que ça te plait !

deletePage est utilisé pour annuler la création de la page par défaut par Gatsby. Si vous ne l'ajoutez pas, vous obtiendrez vos pages personnalisées et celle par défaut.

Vérifiez votre répertoire public avec et sans cette ligne, vous verrez la différence ;)

À propos de vos erreurs, il est difficile de deviner sans code. Pourrais-tu faire un dĂ©pĂŽt avec ton code ? J'y jetterais un Ɠil alors.

EDIT : Seriez-vous intéressé par un exemple ?

Oh, ce n'était pas lié à l'appel deletePage. Il s'agissait de ne pas copier l'objet pages puisque j'avais modifié votre exemple. Je trébuche toujours avec la copie d'objets aprÚs avoir été loin de js pendant un certain temps ;)

@monsieurnebo J'ai joué avec votre solution et il semble que vous ayez toujours besoin de javascript pour charger les paramÚtres régionaux à partir des fichiers json, est-ce correct? En plus de cela, il semble que tous les composants qui sont encapsulés avec le react-i18next HOC ont besoin de javascript pour rendre quoi que ce soit dans le composant...

Pouvez-vous confirmer si c'est ainsi que cela fonctionne de votre cÎté?

EDIT : au fait, j'ai raté votre mention d'un exemple, si vous avez le temps, j'aimerais voir un exemple complet.

@deltaskelta je ferai un exemple quand j'aurai du temps libre :)

@monsieurnebo pouvez-vous confirmer que votre méthode ne rend pas statiquement les chaßnes dans le code HTML et nécessite javascript ?

Ouais, c'est pour ça que ce n'est pas totalement le "mode de vie statique"

J'aimerais un plugin qui génÚre du texte statique à la place.

Hmm je vois. Un rendu statique serait la voie Ă  suivre...

Je pensais, puisque les contextes sont dĂ©jĂ  passĂ©s avec le nom de la langue pour la plupart des pages de votre gatsby-node alors il ne serait pas trop difficile de simplement demander les clĂ©s des messages dans les requĂȘtes graphql pour chaque page et les transmettre de cette maniĂšre, mais je prĂ©fĂ©rerais utiliser un outil i18n tout au long si possible ...

@szimek comment react-intl rend-il les traductions à l'étape de construction et n'utilise-t-il aucun js ?

Comme mentionné, pour autant que je sache, Gatsby-plugin-i18n génÚre du texte statique. Avez-vous vérifié son exemple?

@deltaskelta Eh bien, toutes les traductions sont disponibles pendant le temps de construction (c'est pourquoi j'utilise plusieurs mises en page), donc ça "fonctionne" â„ąïž ;) J'espĂšre juste qu'il continuera Ă  fonctionner dans la v2... Je peux prĂ©parer un exemple d'application si vous vouloir. Je n'ai pas encore vraiment examinĂ© gatsby-plugin-i18n , car je travaille avec Contentful, pas avec des fichiers.

Je n'ai pas lu les détails mais il y a une discussion (ou plutÎt un monologue) sur le combo gatsby-plugin-i18n + content ici : https://github.com/angeloocana/gatsby-plugin-i18n/issues/31

@szimek Je serais trĂšs intĂ©ressĂ© par un exemple. @sedubois Je sais que gatsby-plugin-i18n gĂ©nĂšre aussi du texte statique mais je ne vois pas oĂč se passe la magie qui manque dans i18next afin de gĂ©nĂ©rer des fichiers totalement statiques....

Je pense que je pourrais voir pourquoi maintenant... passez-vous react-intl les messages via pathContext dans gatsby-node pendant le rendu ?

EDIT : si c'est le cas (ce qui a du sens), alors la bibliothÚque i18n utilisée est "un peu" hors de propos car on passe des messages à travers le contexte et on les rend statiquement, ce qui est une configuration gatsby pure et la bibliothÚque i18n ne gÚre que des cas spéciaux tels que dates et pluriels avec js.

AprĂšs des tests plus poussĂ©s de i18next et de react-intl il semble que le HOC de traduction de i18next nĂ©cessite javascript pour se charger, donc mĂȘme si les messages sont transmis via le contexte et rendus statiquement, toute utilisation du HOC de traduction rendra l'ensemble du composant nĂ©cessitant javascript pour s'exĂ©cuter.

react-intl composant FormattedMessage , d'autre part, restitue un message par dĂ©faut (qui peut ĂȘtre basĂ© sur le contexte qui lui est passĂ©) et restitue statiquement dans le code HTML lors de la construction.

De par sa conception, je pense que l'intégration la plus naturelle d'i18n serait avec react-intl si vous souhaitez obtenir des traductions statiques en HTML. Si j'ai mal compris le flux que vous utilisez, veuillez me corriger

@mattferderer a eu la bonne idée ici, mais je pense que cela a besoin d'un peu de peaufinage. https://github.com/gatsbyjs/gatsby/issues/3830#issuecomment -362715706

les mises en page sont rendues avant les pages, donc sans crĂ©er plusieurs mises en page, il n'y a aucun moyen de transmettre des messages Ă  travers le contexte, Ă  partir de la fonction createPages (corrigez-moi si je me trompe ici). Donc, afin de rendre i18n plus facile, je pense que la mise en page devrait simplement appeler children() , puis les diffĂ©rentes mises en page par effet de langue seraient accomplies en faisant en sorte que gatsby-node crĂ©e un chemin diffĂ©rent par langue indexer les pages de pages/index qui peuvent ĂȘtre transmises via le contexte

EDIT : désolé pour la divagation mais tout est devenu clair et j'ai dû l'enregistrer quelque part

EDIT2: Je me trompe dĂ©finitivement ci-dessus, les en-tĂȘtes et les pieds de page doivent ĂȘtre insĂ©rĂ©s dans la mise en page, je ne sais tout simplement pas comment leur faire parvenir les messages sans crĂ©er plusieurs mises en page. La seule autre façon que je puisse penser serait de diviser les URL et de regexer les paramĂštres rĂ©gionaux ... mais cela semble ĂȘtre une chose difficile Ă  faire

@KyleAMathews avec v2 n'ayant qu'une seule mise en page, comment pouvons-nous transmettre des données telles que des messages i18n au composant de mise en page racine via un contexte basé sur le chemin ou un tableau de clés de langue ?

Si cela pouvait ĂȘtre fait, il serait alors facile d'implĂ©menter i18n, mais je ne vois pas comment le faire sans faire plusieurs mises en page

@deltaskelta Voici un exemple de ce que nous faisons : https://github.com/szimek/gatsby-react-intl-example. Il montre comment afficher des articles individuels, comment générer une page d'index pour chaque paramÚtre régional, comment utiliser les composants react-intl , comment utiliser react-intl injectIntl HOC pour définir un titre (ou toute autre balise meta) pour les pages d'index en utilisant intl.formatMessage helper etc.

Les pages générées sont :

  • /en
  • /en/hello-world
  • /pl
  • /pl/witaj-swiecie

Dans la vraie application, nous utilisons une version modifiée de gatsby-pagination , car la version originale ne prend pas en charge l'option de mise en page. Nous avons également défini post_id champ post_id .

D'AILLEURS. Je viens de réaliser que nous devrons probablement générer des plans de site distincts pour chaque langue, afin que Swiftype (le moteur de recherche que nous utilisons) sache quelles pages nous avons.

@deltaskelta briÚvement, vous auriez des composants de page pour chaque langue, puis un composant de mise en page par langue. Voici une façon de procéder.

// French
import React from 'react'
import FrenchLayout from '../components/layouts/french'
import ImportantPage from '../components/pages/important-page'

export default ({ data }) => (
  <FrenchLayout>
    <ImportantPage {...data} />
  </FrenchLayout>
)

// French query here
// English
import React from 'react'
import EnglishLayout from '../components/layouts/english'
import ImportantPage from '../components/pages/important-page'

export default ({ data }) => (
  <EnglishLayout>
    <ImportantPage {...data} />
  </EnglishLayout>
)

// English query here

@KyleAMathews Ces fichiers sont des modÚles, n'est-ce pas ? Cela signifie-t-il que si j'ai 3 types de pages et 7 langues, j'aurais besoin de 21 modÚles ? :)

Ce qui précÚde est la façon la plus optimisée de le faire. Si chaque composant de mise en page n'est pas si différent, vous pouvez les combiner en un seul composant de mise en page, puis changer de mise en page en fonction de la langue active.

Je n'ai pas lu les détails mais il y a une discussion (ou plutÎt un monologue) sur le combo gatsby-plugin-i18n + content ici : angeloocana/gatsby-plugin-i18n#31

@sedubois , haha, gatsby-starter-contentful-i18n dans les documents de Gatsby via ce PR : https://github.com/gatsbyjs/gatsby/pull/4138

Intéressé par l'autre solution ci-dessus, en particulier comment elle se compare au plugin communautaire re: SEO, etc.

@mccrodp Votre solution ressemble assez à la mienne, la principale différence est que gatsby-plugin-i18n ne vous oblige pas à passer explicitement l'option layout à createPage , mais le fait pour vous Dans les coulisses. Cependant, il utilise toujours plusieurs mises en page ;)

J'ai suivi la suggestion de @KyleAMathews et components/Layout qui utilise une bibliothÚque i18n et j'ai entiÚrement supprimé mon dossier de mise en page gatsby. De cette façon, dans gatsby-node je peux créer des pages pour mes paramÚtres régionaux et ils ont accÚs à tout ce à quoi une page a accÚs, y compris les chemins.

Je peux ensuite transmettre la locale directement au composant de mise en page qui la transmet Ă  i18n.

Il est lĂ©gĂšrement gĂȘnant d'avoir Ă  envelopper chaque composant au niveau de la page avec la mise en page, mais cela a dissipĂ© tant de confusion et simplifiĂ© beaucoup mon code.

Salut @deltaskelta , as-tu un exemple de ta solution ? J'adorerais voir si quelque chose peut en ĂȘtre tirĂ© pour pousser en amont le plugin communautaire i18n. Merci.

tout mon projet est dans un état désordonné en ce moment mais je pense que je peux exposer les bases...

  1. Pas de layout - car (si je me souviens bien), le layout entre en jeu avant les chemins ou autre chose qui Ă©tait trĂšs important, ce qui m'empĂȘchait de lui donner les bons objets messages...

  2. Nourrissez les bons messages et locale dans le gatsby-node travers le contexte...

exports.onCreatePage = ({ page, boundActionCreators }) => {
  const { createPage, deletePage } = boundActionCreators;

  if (page.path.includes('404')) {
    return; // no need for localized 404 pages
  }

  return new Promise(resolve => {
    // if it is not the app page then I need localized static pages
    const pages = localizedPages(page);
    deletePage(page);
    pages.map(page => createPage(page));

    resolve();
  });
};

// to be passed to the localized pages so it can calculate the matchPath
const getMatchPath = lang => {
  return `${locales[lang]['path']}/app/:path`;
};

// this is a helper function that makes pages in each language.
const localizedPages = (page, matchPathFunc) => {
  var pages = [];
  Object.keys(locales).map(lang => {
    const path = locales[lang]['path'] + page.path;

    pages.push({
      ...page,
      path: path,
      matchPath: matchPathFunc ? matchPathFunc(lang) : undefined,
      context: {
        locale: lang,
        messages: locales[lang],
        pathRegex: `/.pages${page.path}./` // so pages can match markdown in their dir
      }
    });
  });

  return pages;
};
  1. CrĂ©ez maintenant un composant de mise en page global qui doit ĂȘtre appelĂ© sur chaque composant au niveau de la page...
// this is the main entrypoint for the layout to the site
const GlobalLayout = ({ locale, children, path }) => {
  const theme = getTheme();
  return (
    <MuiThemeProvider theme={theme}>
      <CssBaseline>
        <IntlProvider locale={locale} messages={locales[locale]}>
          <div>
            <Header locale={locale} messages={locales[locale]} path={path} />
            {children}
          </div>
        </IntlProvider>
      </CssBaseline>
    </MuiThemeProvider>
  );
};
  1. Appelez le composant de mise en page globale avec vos composants au niveau de la page qui ont les paramÚtres régionaux appropriés et les messages transmis à partir du contexte
const BlogPost = ({ data, pathContext, location }) => {
  const { locale } = pathContext;
  return (
    <GlobalLayout locale={locale} path={location.pathname}>
      <FullWidth>
        <h1>{data.markdownRemark.frontmatter.title}</h1>
        <h3>{data.markdownRemark.frontmatter.date}</h3>
        <div dangerouslySetInnerHTML={{ __html: data.markdownRemark.html }} />
      </FullWidth>
    </GlobalLayout>
  );
};

Je dois nettoyer et réorganiser ce code parce que je l'ai en quelque sorte fait rapidement pour prouver que cela pouvait fonctionner et je vais le revoir plus tard ... J'espÚre que cela vous en donne l'essentiel

J'ai créé un démarreur gatsby qui utilise js-lingui pour traduire les messages :
https://github.com/dcroitoru/gatsby-starter-i18n-lingui

Dans la vraie application, nous utilisons une version modifiĂ©e de gatsby-pagination, car la version originale ne prend pas en charge l'option de mise en page. Nous avons Ă©galement dĂ©fini un champ post_id pour chaque message qui nous permet de trouver des traductions du mĂȘme message, par exemple dans le cas de cette application de dĂ©monstration, les deux messages auraient le mĂȘme post_id.

@szimek est-il possible que vous partagiez votre pagination gatsby modifiĂ©e ? Je serais trĂšs curieux de le voir car j'ai moi-mĂȘme un problĂšme similaire.

@martynhoyer Mon patch a été fusionné, je suis donc revenu à la version originale de gatsby-pagination . Quel problÚme as-tu ?

Salut @sgoudie
J'utilise ce tutoriel : https://www.gatsbyjs.org/blog/2017-10-17-building-i18n-with-gatsby/ mais je ne trouve aucun de mes locales/{lang}/*.json . Est-ce que quelqu'un a une idée ?
2018-04-25 12_04_13-o intermedium agora e banco inter

Ma config :
gasbty-node.js
```javascriptexports.onPostBuild = () => {
console.log('Copie des paramÚtres régionaux')
fs.copySync(
chemin.join(__dirname, '/src/locales'),
path.join(__dirname, '/public/locales')
)
}

```

Ajouter

exports.onPostBootstrap = () => {
    console.log("Copying locales");
    fs.copySync(
        path.join(__dirname, "/src/locales"),
        path.join(__dirname, "/public/locales")
    );
};

Ă  gatsby-node.js

@ThiagoMiranda J'Ă©tais confrontĂ© au mĂȘme problĂšme puis j'ai rĂ©alisĂ© que gatsby develop n'appelait pas onPostBuild, seulement gatsby build appelait. onPostBootstrap est appelĂ© Ă  chaque fois.

Quelqu'un sait comment créer https://moz.com/learn/seo/hreflang-tag dans les mises en page ?

@RobinHerzog Nous les créons dans des modÚles à l'aide de Helmet. Ils sont spécifiques au type de page, donc au moins dans notre cas, cela n'avait pas de sens de les créer dans une mise en page.

@szimek merci pour la réponse. Je comprends mais dans mon cas ce serait intéressant de l'avoir dans les mises en page.

<link rel="alternate" href={Route['en-us'][this.props.data.prismicDocument.data.group]} hreflang="en-us" /> <link rel="alternate" href={Route['fr-fr'][this.props.data.prismicDocument.data.group]} hreflang="fr-fr" />

Pour le moment, comme vous l'avez dit, copiez ces lignes dans tous les modĂšles.

Je commence seulement à développer avec React/JavaScript, mais tout ce que j'ai vu pour prendre en charge i18n était trop complexe. Voici mon propre travail pour l'utilisation la plus courante : wise-starter

Le rechargement en direct, le référencement convivial et les langues par défaut n'utilisent pas la clé dans l'URL.
Toutes les pages .js sont générées pour toutes les langues.
Toutes les mises en page et .md doivent ĂȘtre crĂ©Ă©s pour toutes les langues afin d'Ă©viter les erreurs.
Les composants LangSelect et Link sont i18n smart.

Si vous pouvez m'aider et m'expliquer comment je pourrais améliorer mon code et mon style, je vous en serais reconnaissant.

@Tom-Pichaud, je pense que puisque vous ne transmettez pas de messages aux composants de la page, ils ne seront pas rendus statiquement lĂ -bas.

La configuration Markdown i18n dans gatsby-node ressemble à ce que les gens ont fait ici, mais je suis curieux de savoir si vous obtenez un rendu statique avec javascript désactivé sur les composants de votre page ?

Oui j'obtiens un rendu statique, c'Ă©tait mon objectif en tout cas, i18n-react fait l'affaire !

@TomPichaud vous serait-il possible de partager en quoi le i18n -react que vous avez mentionné est meilleur que

Une chose que je ne comprends pas tout à fait est le besoin réel de packages externes pour charger les messages traduits (autres que la pluralisation et les parents, probablement).

Pour un site simple avec un contenu statique, je duplique simplement les pages pour chaque langue onCreatePage et passe la locale Ă  context :

// some file with the locales
const locales = {
  en: {
    path: 'en',
    default: true,
  },
  pt: {
    path: 'pt',
  },
}
// gatsby-node.js
exports.onCreatePage = ({ page, boundActionCreators }) => {
  const { createPage, deletePage } = boundActionCreators

  return new Promise(resolve => {
    deletePage(page)

    Object.keys(locales).map(lang => {
      const localizedPath = locales[lang].default
        ? page.path
        : locales[lang].path + page.path

      return createPage({
        ...page,
        path: localizedPath,
        context: {
          locale: lang,
        },
      })
    })

    resolve()
  })
}

Ensuite, sur la page réelle, j'utilise les paramÚtres régionaux dans le contexte pour interroger le contenu à l'aide du filtre de graphql.

Disons que j'ai le contenu de la maison dans /data/home/en.js et /data/home/pt.js :

import React from 'react'

const IndexPage = ({ pathContext: { locale }, ...props }) => {
  const { childHomeJson: data } = props.data.allFile.edges[0].node

  return <div>{data.hello}</div>
}

export const query = graphql`
  query HomeContent($locale: String) {
    allFile(filter: { name: { eq: $locale } }) {
      edges {
        node {
          childHomeJson {
            hello
          }
        }
      }
    }
  }
`

export default IndexPage

fonctionne bien avec netlifyCMS (bien qu'un peu détaillé jusqu'à ce qu'ils prennent en charge i18n) et les images dans les fichiers JSON (bien que nous devions créer un nouveau NodeField avec le chemin relatif pour que le systÚme de fichiers de Gatsby l'obtienne)

N'est-ce pas suffisant dans la plupart des cas ?

Je teste toujours et je n'ai rien utilisé de tout cela en production, mais je pense utiliser l'API de contexte de react pour les paramÚtres régionaux afin de résoudre certains problÚmes en suspens comme les liens localisés

@pbrandone Cela semble ĂȘtre une excellente approche pour moi. Je pense que quelque chose de similaire devrait ĂȘtre documentĂ© officiellement.

Merci pour toutes les contributions, la quantité d'idées discutées ici marque clairement la demande d'un support i18n bien documenté.

@pbrandone Cela signifie-t-il que vous devez spĂ©cifier explicitement toutes les clĂ©s utilisĂ©es par tous les composants enfants dans IndexPage dans cette requĂȘte et transmettre les traductions Ă  tous les composants via des accessoires ?

De plus, j'utilise des rĂšgles de pluralisation et des dates relatives, donc je dois quand mĂȘme charger des donnĂ©es supplĂ©mentaires spĂ©cifiques aux paramĂštres rĂ©gionaux :/

Cependant, je suis d'accord que ce serait formidable d'avoir une documentation officielle sur la façon de faire i18n sans aucune bibliothÚque pour des cas simples et ensuite comment le faire avec les bibliothÚques les plus populaires.

@szimek bien, dans ce cas oui.

Il est trÚs facile d'ajouter react-intl (ou toute autre bibliothÚque i18n) tho :

// in src/components/layout/index.js

import React from 'react'
import { IntlProvider, addLocaleData } from 'react-intl'

// Locale data
import enData from 'react-intl/locale-data/en'
import ptData from 'react-intl/locale-data/pt'

// Messages
import en from '../../data/en.json'
import pt from '../../data/pt.json'

const messages = { en, pt }

addLocaleData([...enData, ...ptData])

const Layout = ({ locale, children }) => (
  <IntlProvider locale={locale} messages={messages[locale]}>
    {children}
  </IntlProvider>
)

export default Layout

puis sur les pages :

import React from 'react'
import { FormattedMessage } from 'react-intl'

import Layout from '../components/layouts'

const IndexPage = ({ pathContext: { locale } }) => (
  <Layout locale={locale}>
    <FormattedMessage id="hello" />
  </Layout>
)

export default IndexPage

Mais alors vous ne seriez pas en mesure d'utiliser plusieurs fichiers JSON (par exemple par page), ni d'avoir toutes les données CMS dans ces fichiers à interroger et à transformer avec la puissance de graphql.
Avec l'approche graphql, nous pourrions, par exemple, avoir des clés avec des chemins d'accÚs aux images dans ces fichiers JSON pour charger différentes images par paramÚtre régional et pouvoir toujours utiliser gatsby-image dessus.
Et puis ajoutez netlify CMS pour Ă©diter ces fichiers JSON 😃

Je n'ai pas correctement examiné gatsby v2 mais apparemment, il existe un composant StaticQuery qui nous permet d'interroger les composants enfants (quelqu'un me corrige si je me trompe !)

Si tel est le cas, nous pourrions crĂ©er un contexte React pour rendre la locale disponible n'importe oĂč, puis interroger les clĂ©s nĂ©cessaires dans chaque composant avec le filtrage des paramĂštres rĂ©gionaux

@pbrandone vous avez raison, cela rend statiquement de cette façon. Je me souviens qu'il teste dans le passĂ© et Ă  dĂ©faut, mais c'Ă©tait avant d' avoir une bonne comprĂ©hension dĂ©cente de la façon dont Gatsby Ɠuvres, que je pouvais avoir mon react-intl configuration dans Gatsby navigateur qui semble comme il pourrait ne pas rendre sans javascript. Ma solution ressemble maintenant Ă  la vĂŽtre

@KyleAMathews J'essaie de mettre Ă  jour notre page vers Gatsby vers la v2 et j'ai un problĂšme avec notre configuration react-intl et les requĂȘtes graphql.

J'ai précédemment expliqué comment j'utilise des mises en page spécifiques à une langue pour charger des données de langue dans Gatsby v1 - https://github.com/szimek/gatsby-react-intl-example. Dans Gatsby v2, j'ai eu l'idée de remplacer ces mises en page par des composants de page spécifiques à la langue. J'aurais un composant src/templates/Post.js indépendant de la langue, puis des composants spécifiques à la langue comme src/templates/Post.en.js , src/templates/Post.de.js qui ne chargeraient que les données de langue et rendraient le composant indépendant de la langue.

Dans votre commentaire prĂ©cĂ©dent (https://github.com/gatsbyjs/gatsby/issues/3853#issuecomment-367115380), vous avez montrĂ© un exemple oĂč chaque composant de page a une requĂȘte spĂ©cifique Ă  la langue.

Le problĂšme avec cela est que lors de l'appel de createPage , je passe les noms de ces composants spĂ©cifiques au langage (par exemple src/templates/Post.en.js ) en tant qu'option component , mais la requĂȘte graphql est dans le composant indĂ©pendant de la langue, car c'est __exactement le mĂȘme pour toutes les langues__ (cela dĂ©pend de locale , mais je le passe dans context ). J'aimerais Ă©viter de rĂ©pĂ©ter exactement la mĂȘme requĂȘte dans tous ces composants spĂ©cifiques Ă  la langue.

Des idĂ©es comment le rĂ©soudre? Puis-je extraire cette requĂȘte vers une variable ? Quand je l'ai essayĂ©, Gatsby se plaint que les noms de requĂȘte et de fragment sont les mĂȘmes...

J'ai récemment ajouté un démarreur Gatsby par défaut avec des fonctionnalités de routes d'URL multilingues et de détection de la langue du navigateur. (démo)

gatsby-starter-default-intl

Caractéristiques:

  • Localisation (multilingue) fournie par react-intl .

  • Redirection automatique basĂ©e sur la langue prĂ©fĂ©rĂ©e de l'utilisateur dans le navigateur fourni par browser-lang .

  • Prend en charge les routes d'URL multilingues au sein d'un seul composant de page. Cela signifie que vous n'avez pas besoin de crĂ©er des pages distinctes telles que pages/en/index.js ou pages/ko/index.js .

  • BasĂ© sur gatsby-starter-default avec le moins de modifications.

@wiziple Merci ! Cela a l'air vraiment intéressant. Je ne savais pas que vous pouviez faire quelque chose comme ça : https://github.com/wiziple/gatsby-starter-default-intl/blob/master/src/i18n/withIntl.js#L38 ;) Espérons que cela fonctionne toujours dans le Webpack 4...

Est-il possible de charger les donnĂ©es locales de la mĂȘme maniĂšre ici https://github.com/wiziple/gatsby-starter-default-intl/blob/master/src/i18n/withIntl.js#L6 ? Nous prenons en charge 6 (bientĂŽt 7 langues), donc ce serait gĂ©nial si je pouvais charger uniquement celle pour laquelle je construis la page. ce n'est pas grave si ce n'est pas possible - heureusement, ces fichiers de donnĂ©es locales sont relativement petits.

Je vais aussi devoir regarder comment vous générez ces pages, car dans mon cas toutes les pages ne sont pas traduites dans toutes les langues (il n'y a pas une seule langue "source"), donc la solution avec onCreatePage ne fonctionnera probablement pas dans mon cas.

EspĂ©rons que cela rĂ©soudra mon problĂšme avec la mĂȘme requĂȘte graphql dans chaque composant de page spĂ©cifique Ă  la langue.

@szimek
Le site Web que je gÚre a 14 langues et chaque fichier de langue fait 12-15 Ko. Je suis presque sûr que nous devons fournir la bonne langue pour chaque routeur de langue au moment de la construction afin de générer des données de référencement. Je ne sais donc pas comment je peux gérer cela sans fournir toutes les langues.

Je comprends qu'il est parfois difficile de fournir chaque page traduite dans toutes les langues. Vous pourrez peut-ĂȘtre rĂ©soudre ce problĂšme en fournissant une exception sur onCreatePage dans gatsby-node.js . Dans mon cas, j'ai simplement rĂ©solu en ne proposant pas de langue traduite, quel que soit le routeur de langue. Vous pouvez trouver le site vitrine sur la production Ă  partir du dĂ©marreur README.md et vĂ©rifier ses performances.

@wiziple Merci beaucoup !

J'ai utilisĂ© votre composant withIntl avec l'astuce dynamique require pour les traductions (je ne sais pas s'il y a des inconvĂ©nients Ă  l'utiliser) et cela semble trĂšs bien fonctionner. Cela a rĂ©solu le problĂšme avec lequel je me dĂ©battais - comment gĂ©rer la mĂȘme requĂȘte graphql dans plusieurs composants de page spĂ©cifiques Ă  une langue - en ayant un seul composant de page pour toutes les langues.

@wiziple merci pour le partage du repo. M'a mis sur la bonne voie 😄 🎉

lingui semble ĂȘtre une meilleure alternative . Je ne pense pas que @dcroitoru ait Ă©tĂ© correctement reconnu pour un bon exemple. A juste besoin d'un peu d'amour pour le pousser vers Gatsby 2.0

Je suis d'accord que Lingui est en effet vraiment sympa, mĂȘme s'il a encore besoin d'un starter complet, avec la derniĂšre version de Gatsby mais aussi Lingui. Le dĂ©marreur mentionnĂ© n'est pas officiel et il manquait certaines fonctionnalitĂ©s la derniĂšre fois que j'ai vĂ©rifiĂ© (par exemple, utiliser un chargeur pour exĂ©cuter la compilation lingui Ă  la volĂ©e). L'auteur de Lingui @tricoder42 a dĂ©clarĂ© qu'il fournirait de la documentation lorsque Lingui v3 sera disponible (ce qui semble ĂȘtre bientĂŽt).

NB : j'ai remarqué que mon besoin d'une librairie i18n diminuait aprÚs l'intégration d'un CMS (DatoCMS), mais j'ai toujours besoin de Lingui pour certaines chaßnes qui ne trouvent pas leur place dans le CMS et aussi pour la pluralisation et éventuellement d'autres choses plus tard donc j'ai définitivement veux le garder dans ma base de code.

Quoi qu'il en soit, dans mon cas, l'existence de gatsby-plugin-i18n a rendu les choses assez confuses car il n'est pas maintenu, a un nom déroutant et détourne l'attention de ces autres solutions vraiment intéressantes comme js-lingui et CMS que j'ai ensuite pris tandis que pour comprendre et assembler ensemble.

Je viens de créer ce démarreur pour vous aider : https://github.com/smakosh/gatsby-starter-i18n
Article : https://dev.to/smakosh/implement-i18n-to-a-gatsby-site-5ala

J'ai fait deux exemples d'internationalisation avec l'intégration de react-intl

Le premier exemple est axé sur le regroupement uniquement des traductions actuelles dans des morceaux js (quelque chose que je n'ai pas pu trouver dans d'autres plugins que j'ai vérifiés).

Le deuxiĂšme exemple se concentre sur l'utilisation de requĂȘtes dynamiques pour fournir uniquement les traductions demandĂ©es pour une combinaison page/langue donnĂ©e.

Espérons que ces exemples seront utiles à quelqu'un.

J'ai également fait un message moyen rapide (et j'ai oublié de le publier ici) avec à peu prÚs ce qu'il y a dans https://github.com/gatsbyjs/gatsby/issues/3853#issuecomment -395432693 (bien qu'un peu plus en profondeur).

https://blog.significa.pt/i18n-with-gatsby-528607b4da81 pour toute personne intéressée

Les anciens numéros seront fermés aprÚs 30 jours d'inactivité. Ce problÚme est resté silencieux pendant 20 jours et est marqué comme obsolÚte. Répondez ici ou ajoutez l'étiquette « not stale » pour garder ce problÚme ouvert !

Hé les gars, ça fait presque un an

J'ai rĂ©cemment publiĂ© le nouveau plugin gatsby gatsby-plugin-intl qui fait facilement de votre site Web gatsby un cadre d'internationalisation prĂȘt Ă  l'emploi.

DÉMO : https://gatsby-starter-default-intl.netlify.com

  • Cadre d'internationalisation prĂȘt Ă  l'emploi alimentĂ© par react-intl

  • Prend en charge la redirection automatique en fonction de la langue prĂ©fĂ©rĂ©e de l'utilisateur dans le navigateur

  • Prend en charge les routes d'URL multilingues dans un seul composant de page. Cela signifie que vous n'avez pas besoin de crĂ©er des pages distinctes telles que pages/en/index.js ou pages/ko/index.js .

  • Comme certains d'entre vous l'ont suggĂ©rĂ© ci-dessus, il regroupe dĂ©sormais uniquement la langue actuelle pendant la construction.

De plus, je tiens à mentionner que de nombreux exemples / démarreurs i18n sont en fait rendus cÎté client. Le meilleur moyen de vérifier si l'application est rendue en tant que SSR est de visualiser le code source et de vérifier si les textes localisés existent. Veuillez vérifier cette question lorsque vous internationalisez votre site Web gatsby pour le référencement.

Hé les gars, ça fait presque un an

J'ai rĂ©cemment publiĂ© le nouveau plugin gatsby gatsby-plugin-intl qui fait facilement de votre site Web gatsby un cadre d'internationalisation prĂȘt Ă  l'emploi.

DÉMO : https://gatsby-starter-default-intl.netlify.com

  • Cadre d'internationalisation prĂȘt Ă  l'emploi alimentĂ© par react-intl
  • Prend en charge la redirection automatique en fonction de la langue prĂ©fĂ©rĂ©e de l'utilisateur dans le navigateur
  • Prend en charge les routes d'URL multilingues dans un seul composant de page. Cela signifie que vous n'avez pas besoin de crĂ©er des pages distinctes telles que pages/en/index.js ou pages/ko/index.js .
  • Comme certains d'entre vous l'ont suggĂ©rĂ© ci-dessus, il regroupe dĂ©sormais uniquement la langue actuelle pendant la construction.

De plus, je tiens à mentionner que de nombreux exemples / démarreurs i18n sont en fait rendus cÎté client. Le meilleur moyen de vérifier si l'application est rendue en tant que SSR est de visualiser le code source et de vérifier si les textes localisés existent. Veuillez vérifier cette question lorsque vous internationalisez votre site Web gatsby pour le référencement.

HĂ© @wiziple merci beaucoup pour cela, je
Peut-ĂȘtre que je n'ai pas compris, mais avez-vous TOUTES les chaĂźnes d'une langue dans un seul fichier ?
Serait-il possible de diviser le JSON de chaque langue en plusieurs fichiers, peut-ĂȘtre en utilisant la mĂȘme structure de composants ?

@cant89 Je vois votre point, mais ce n'est actuellement pas possible sans changer le code du plugin. Ou vous pouvez créer un script qui analyse le répertoire src et récupÚre tous les fichiers de langue des composants. Fusionnez en un seul JSON puis connectez-vous à gatsby develop ou gatsby build .
Une fois que vous avez obtenu tous les fichiers JSON et fusionné en tant qu'objet imbriqué, vous pouvez également le convertir en objet aplati.
https://github.com/yahoo/react-intl/wiki/Upgrade-Guide#flatten -messages-object

Nous avons un bon exemple de configuration pour i18n. https://github.com/gatsbyjs/gatsby/tree/master/examples/using-i18n. Nous n'avons pas vraiment d'opinion sur les frameworks i18n. Choisissez-en un à votre goût.

Nous avons un bon exemple de configuration pour i18n. https://github.com/gatsbyjs/gatsby/tree/master/examples/using-i18n. Nous n'avons pas vraiment d'opinion sur les frameworks i18n. Choisissez-en un à votre goût.

Cool, merci, je vais essayer !
Quoi qu'il en soit, le lien sur le fichier readme est cassé, vous voulez probablement dire https://using-i18n.netlify.com/ ?

@wardpeet Votre exemple génÚre-t-il des chaßnes traduites statiques (au moment de la construction) ? Ou génÚre-t-il le texte pendant l'exécution ?

@monsieurnebo ressemble au temps de construction

@cant89, nous mettons toujours Ă  jour le DNS, donc c'est bientĂŽt pour l'instant en utilisant-i18n.netlify.com/ est le bon lien.

@monsieurnebo c'est au moment de la construction. Il crĂ©e une copie de votre site Web pour chaque langue afin que tout puisse ĂȘtre construit de maniĂšre statique. Cela signifie que votre site Web reste rapide car tout n'est qu'un fichier .html.

Je ne sais pas oĂč demander cela, mais un peu pertinent. l'un de ces plugins prend-il en charge les pathPrefix gatsby ?

i.e. 
// gatsby-config.js

modules.exports = {
    pathPrefix: 'bar'
}

https://foo.com => https://foo.com/bar

but now my language locales will now be https://foo.com/bar/de-DE/
when I think I would prefer it be https://foo.com/de-DE/bar if that makes sense.

Hmm intéressant, je pense que le premier a généralement plus de sens, car le pathPrefix fait en sorte que votre domaine soit domain.com/prefix donc changez la racine lorsque vous avez installé Gatsby dans un sous-répertoire, si vous ne l'installez pas sur un sous-répertoire, vous n'en avez pas besoin, si vous utilisez un sous-répertoire en changeant le préfixe pour qu'il soit aprÚs la langue, le casserait.

Maintenant, la question se pose, pourquoi utilisez-vous le pathPrefix en premier lieu ?

Réf : docs pathPrefix

Salut,

La plupart des discussions ici portent sur la façon d'i18n un site gatsby. Mais il y a une diffĂ©rence entre avoir un POC fonctionnel et avoir un systĂšme optimisĂ© prĂȘt pour la production.

Si vous souhaitez en savoir plus sur le fractionnement de code et les fichiers i18n, et pourquoi la plupart des solutions de ce fil ne sont pas optimisées, vous trouverez ce problÚme utile

Cette page vous a été utile?
0 / 5 - 0 notes