Gatsby: Question - how to correctly set up react-intl provider with Gatsby?

Created on 31 Jan 2018  ·  5Comments  ·  Source: gatsbyjs/gatsby

I'm trying to add react-intl to my project and when I run gatsby build static pages are generated correctly, but when I load them in the browser, intl object is messed up in template components, i.e. it has incorrect locale and intl.messages object is empty.

My current setup looks like this:

  1. I've got a separate layout for each locale, e.g.
// src/layouts/de.js
import React from 'react';
import Layout from './index';
import messages from '../../data/translations/de.json';

export default (props) => <Layout {...props} locale="de" messages={messages} />;
  1. I'm using IntlProvider in index layout:
// src/layouts/index.js
import React from 'react';
import { IntlProvider } from 'react-intl';

function TemplateWrapper({ children, locale, messages }) {
  return (
    <IntlProvider locale={locale} messages={messages}>
      <div>{children()}</div>
    </IntlProvider>
  );
}

export default TemplateWrapper;
  1. In individual page templates I'm using FormattedMessage and injectIntl.

I've added console.log at each step to see where it gets messed up.

Here are logs when running gatsby build for /de/blog page:

Rendering "de" layout...
path /de/blog
Rendering "index" layout...
path /de/blog
locale de
messages Datenschutz
Rendering "index" page...
locale de
messages Datenschutz

Here are logs when opening /de/blog page in a browser:

component---src-layouts-de-jsx-48cc900e186c41daf6ff.js:3 Rendering "de" layout...
component---src-layouts-de-jsx-48cc900e186c41daf6ff.js:3 path /de/blog/
component---src-layouts-de-jsx-48cc900e186c41daf6ff.js:3 messages Datenschutz
component---src-layouts-de-jsx-48cc900e186c41daf6ff.js:3 Rendering "index" layout...
component---src-layouts-de-jsx-48cc900e186c41daf6ff.js:3 path /de/blog/
component---src-layouts-de-jsx-48cc900e186c41daf6ff.js:3 locale de
component---src-layouts-de-jsx-48cc900e186c41daf6ff.js:3 messages Datenschutz
component---src-templates-index-jsx-66713dbb6ea96235f9fd.js:2 Rendering "index" page...
component---src-templates-index-jsx-66713dbb6ea96235f9fd.js:2 locale en
component---src-templates-index-jsx-66713dbb6ea96235f9fd.js:2 messages undefined

As you can see in the template the data is different when running it in a browser, than in the generated static page.

Any idea how to set it up properly?

question or discussion

Most helpful comment

Turns out it had nothing to do with Gatsby and I was simply missing

import { addLocaleData } from 'react-intl';
import localeData from 'react-intl/locale-data/de';
addLocaleData(localeData);

in my layouts 🤦‍♂️

All 5 comments

Turns out it had nothing to do with Gatsby and I was simply missing

import { addLocaleData } from 'react-intl';
import localeData from 'react-intl/locale-data/de';
addLocaleData(localeData);

in my layouts 🤦‍♂️

how do you polyfill Intl for older browsers like IE10?

@antoinerousseau I'm using https://polyfill.io. It doesn't always work correctly, as I still sometimes get notifications about missing Intl in older and less common browsers like Samsung Internet 3.x or UC Browser, but it might also be some bug in my code.

I've got the following code in gatsby-browser.js:

exports.onClientEntry = () => {
  /*
   * Polyfills via polyfill.io
   */
  return new Promise((resolve, reject) => {
    // Global callback for polyfill.io script
    // eslint-disable-next-line no-underscore-dangle
    window.__polyfillio__ = () => {
      resolve();
    };

    const features = [];

    if (!('Intl' in window)) {
      const locale = getLocaleFromPath(window.location.pathname);
      features.push(`Intl.~locale.${locale}`);
    }

    if (!('fetch' in window)) {
      features.push('fetch');
    }

    if (!('URL' in window && 'URLSearchParams' in window)) {
      features.push('URL');
    }

    // Use 'always' flag to download polyfills regardless of user agent.
    // We add features to the list only if they are not supported.
    if (features.length) {
      const s = document.createElement('script');
      s.src = `https://cdn.polyfill.io/v2/polyfill.min.js?features=${features.join(
        ',',
      )}&rum=1&flags=always&callback=__polyfillio__`;
      s.async = true;
      s.onerror = reject;
      document.head.appendChild(s);
    } else {
      resolve();
    }
  });
};

thanks @szimek for sharing your code.
isn't fetch already polyfilled by gatsby?

@antoinerousseau I'm not sure. We had this code before we migrated to Gatsby v2.

But it looks like it might not be: https://github.com/zloirock/core-js/issues/25.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

benstr picture benstr  ·  3Comments

rossPatton picture rossPatton  ·  3Comments

dustinhorton picture dustinhorton  ·  3Comments

KyleAMathews picture KyleAMathews  ·  3Comments

ferMartz picture ferMartz  ·  3Comments