Joy
Joy

Reputation: 9550

Gatsby: load i18n content dynamically from contentful

We have a static site using Gatsby and contentful. Now we want to support multi-languages, with localized content from contentful. I am able to populate a graghql query:

query frontpageTeaser($lang: String) {
    contentfulFrontpage(node_locale: { eq: "zh-CN" }) {
      myArticalContent
      ...
    }
  } 

This query is able to load the Chinese content from contentful, and English if changed to node_locale: { eq: "en-US" }.

Now the issue is: we want to support a language switch, so that when switching language, the graphql loads corresponding localized content.

We are using gatsby-plugin-react-i18next, which has this great feature:

Support multi-language url routes in a single page component. You don’t have to create separate pages such as pages/en/index.js or pages/es/index.js.

Pages like http://localhost:8000/zh-CN/ does load Chinese from local /locales/zh-CN/translation.json, but how to load localized content when switching language?

Graphql seems providing page query, so i added gatsby-node.js:

exports.createPages = async function ({ actions, graphql }) {
  actions.createPage({
    path: '/zh-CN/',
    component: require.resolve(`./src/pages/index.js`),
    context: { lang: 'zh-CN' },
  })
}

And use this on page:

export const query = graphql`
  query frontpageTeaser($lang: String) {
    contentfulFrontpage(node_locale: { eq: $lang }) {
      myArticalContent
    }
  } 
`

But it always returns en. Please kindly help :). Thanks.

Upvotes: 1

Views: 2218

Answers (2)

Joy
Joy

Reputation: 9550

Before getting a better solution, this one works:

// @todo gatsby plugin https://www.gatsbyjs.org/packages/gatsby-plugin-react-i18next/
// this plugin provides current language `context.i18n.language`, which not know how to pass it to graphql page query.
// This snippet moves it one-level up to `context.locale`.
// @todo need to explore a better solution.
exports.onCreatePage = ({ page, actions }) => {
  const { createPage, deletePage } = actions

  if (!page.context.locale) {
    const language = page.context.i18n.language
    const locale = language === 'en' ? 'en-US' : language
    deletePage(page)

    createPage({
      ...page,
      context: {
        ...page.context,
        locale,
      }
    })
  }
}

Upvotes: 0

Makenna Smutz
Makenna Smutz

Reputation: 111

This can be a complex switch. There is an example project that has smoothly done it with another CMS + Gatsby, here.

Specific places to point out in the codebase:

  • Configuration of which locales you use, here
  • A dynamic link depending on the active locale, here
  • The context for your whole app to know what the active locale is, here
  • Actually implementing the locale context provider in the higher order component Layout, here
  • There is also some magic inside of the gatsby-node.js which updates what you've already been working on! You can find that, here.

Hope that helps :)

Upvotes: 1

Related Questions