Gatsby: load localized content from contentful dynamically

Gatsby is a React-based open source framework with performance, scalability and security built-in. With server-side-rendering, Gatsby is ideal for building a static site with limited user interactions, whose content may not change frequently. Landing pages, blog, news, personal portfolio sites are in this category.

While Gatsby deals with the site generation, Contentful manages the data. More than a headless CMS, Contentful is the API-first content management platform to create, manage and publish content on any digital channel. It's like a database with medias, text and relationship among the data. Gatsby and Contentful can be easily wired to work together, making us easy to maintain a static site.

This article introduces you how to make a Gatsby site with multi-language content managed by Contentful.

Contentful settings

Register a new Contentful account, login and create a new space for your site. Go to your space, navigate to Settings -> Locales page, you will find that Contentful enables two languages by default: English and German. You will need to upgrade your Contentful account if you need more locales. Modify the languages as you like, here I use English and Chinese.

Contentful manages data in a form way. Content model defines fields of a table, and Content are the table rows. For more information, check the doc here. When creating a Field of Content model, make sure the checkbox Enable localization of this field is checked:

contentful-field-locale

Then, you should be able to put content in the Content editing view:

contentful-multi-lang-fields

Please refer to the Contentful Developers Guide for more details about Contentful locales.

For us, we just need to pass GraphQL parameter filter: { node_locale: { eq: $locale } } to fetch specific languange content from Contentful.

gatsby-plugin-react-i18next

At front-end, we use a Gatsby plugin gatsby-plugin-react-i18next to manage i18n. It seamless integrates with react-i18next. Use npm install --save gatsby-plugin-react-i18next or yarn add gatsby-plugin-react-i18next to install it.

Then, modify Gatsby config file gatsby-config.js to add configuration to plugins config:

1{
2  // including a plugin from outside the plugins folder needs the path to it
3  resolve: `gatsby-plugin-react-i18next`,
4  options: {
5    languages: Object.keys(languages),
6    defaultLanguage,
7    path: `${__dirname}/src/locales`,
8    fallbackLng: defaultLanguage,
9    i18nextOptions: {
10      debug: true,
11      lowerCaseLng: false,
12      // keySeparator: '.',
13      // nsSeparator: '.',
14      interpolation: {
15        escapeValue: false // not needed for react as it escapes by default
16      },
17      detection: {
18        order: ['querystring', 'cookie', 'localStorage'],
19      },
20      fallbackNS: 'common',
21      react: {
22        transSupportBasicHtmlNodes: true,
23        transKeepBasicHtmlNodesFor: ['br', 'strong', 'i', 'b', 'small'],
24      }
25    }
26  }
27},

Notice that i18nextOptions is the react-i18next parameters. You can check the doc for the full list of parameters.

1exports.onCreatePage = ({ page, actions }) => {
2  const { createPage, deletePage } = actions
3
4  if (!page.context.locale) {
5    const language = page.context.i18n.language
6    const locale = language === 'en' ? 'en-US' : language
7    deletePage(page)
8
9    createPage({
10      ...page,
11      context: {
12        ...page.context,
13        locale,
14      },
15    })
16  }
17}

Front-end.io @ shaojiang.io