Set Up Storybook Decorators - React Intl Provider

Related Post: Set Up Storybook Decorators - Emotion Theme Provider

Problem: Storybook Not Passing Locales to React Intl Provider

I was running into an issue setting up Storybook with React Intl (through gatsby-plugin-intl) and storybook-addon-intl.

In the actual Gatsby app, gatsby-plugin-intl passes locales via the config object in gatsby-config.js.

I had set up the relevant storybook-addon-intl withIntl decorator in .storybook/preview.js, and had also loaded the locale data using gatsby-plugin-intl's addLocaleData. But there was no documentation on how to provide locales into gatsby-plugin-intl's Provider.

gatsby-config.js
// ... other configs

// Get and parse language sets provided by env var
const languages = process.env.GATSBY_SUPPORTED_LANGUAGES.split(
  ","
).map((item) => item.trim());

const languagesArray = process.env.GATSBY_SUPPORTED_LANGUAGES.split(",");

languagesArray.forEach((lang) => {
  excludedPages.push(
    ...excludedPagesList.map((page) => `/${lang.trim() + page}`)
  );
});

// Initial Gastby plugins array
const plugins = [
  // ... other plugins
  {
    resolve: "gatsby-plugin-intl",
    options: {
      path: `${__dirname}/src/locales`,      languages,      defaultLanguage: process.env.GATSBY_DEFAULT_LANGUAGE,
      redirect: false,
    },
  },
];
.storybook/preview.js
// !! This does not work

import { setIntlConfig, withIntl } from "storybook-addon-intl";

import { addLocaleData } from "gatsby-plugin-intl";
import enLocaleData from "react-intl/locale-data/en";
import esLocaleData from "react-intl/locale-data/es";

// ... other decorators

// Set supported locales
export const locales = ["en-us", "es-es"];

// Import translation messages
export const messages = locales.reduce((acc, locale) => {
  return {
    ...acc,
    [locale]: require(`../src/locales/${locale}.json`),
  };
}, {});

const getMessages = (locale) => messages[locale];

// Set `storybook-addon-intl` configuration (handles `react-intl`)
setIntlConfig({
  locales,
  defaultLocale: "en-us",
  getMessages,
});

// Load the locale data for all your supported locales
addLocaleData(enLocaleData);addLocaleData(esLocaleData);
// Adds storybook-addon-intl
addDecorator(withIntl);

Manually Setting Up IntlContextProvider

After digging around the gatsby-plugin-intl source code, I noticed that an IntlContextProvider was being exported.

I was able to pass a similar config object from gatsby-config.js into this provider, and set it up as another Storybook decorator.

.storybook/decorators/GatsbyIntlProvider.js
import React from "react";
import { IntlContextProvider } from "gatsby-plugin-intl/intl-context";

import { locales, messages } from "../preview";

const intlConfig = {
  language: "en-us",
  languages: locales,
  messages: messages,
  originalPath: "/",
  redirect: true,
  routed: true,
};

const GatsbyIntlProvider = (storyFn) => (  <IntlContextProvider value={intlConfig}>{storyFn()}</IntlContextProvider>);
export default GatsbyIntlProvider;
.storybook/preview.js
import { setIntlConfig, withIntl } from "storybook-addon-intl";

import { addLocaleData } from "gatsby-plugin-intl";
import enLocaleData from "react-intl/locale-data/en";
import esLocaleData from "react-intl/locale-data/es";

import { GatsbyIntlProvider } from "./decorators";

// Set supported locales
export const locales = ["en-us", "es-es"];

// Import translation messages
export const messages = locales.reduce((acc, locale) => {
  return {
    ...acc,
    [locale]: require(`../src/locales/${locale}.json`),
  };
}, {});

const getMessages = (locale) => messages[locale];

// Set `storybook-addon-intl` configuration (handles `react-intl`)
setIntlConfig({
  locales,
  defaultLocale: "en-us",
  getMessages,
});

// Load the locale data for all your supported locales
addLocaleData(enLocaleData);
addLocaleData(esLocaleData);

// Adds gatsby-plugin-intl IntlContextProvider
addDecorator(GatsbyIntlProvider);
// Adds storybook-addon-intl
addDecorator(withIntl);

// ... other decorators

Gatsby Starter: TypeScript + Emotion + Storybook

If you want to see the full config in a project, I created a Gatsby Starter that uses Gatsby + TypeScript + Emotion + Storybook + React Intl + SVGR + Jest.

Check it out at: Gatsby Starter: TypeScript + Emotion + Storybook