microapps / gatsby-plugin-react-i18next

Easily translate your Gatsby website into multiple languages
MIT License
121 stars 72 forks source link

warning: You will need to pass in an i18next instance by using initReactI18next #179

Open v4iv opened 1 year ago

v4iv commented 1 year ago

Hi everyone,

Not really a breaking issue but I'm getting the following warning on build, but not on dev. I don't really understand why? BTW currently I only support one language - English.

...
warning react-i18next:: You will need to pass in an i18next instance by using initReactI18next
warning react-i18next:: You will need to pass in an i18next instance by using initReactI18next
warning react-i18next:: You will need to pass in an i18next instance by using initReactI18next
...

This is my repo : The Leaky Cauldron Blog

This is my netlify build logs - Build Logs

v4iv commented 1 year ago

Okay so I figured it out, unlike shown in the example, useTranslation doesn't work in Head

Pjaerr commented 1 year ago

👋 Hey @v4iv did you ever figure out a way to get access to translations inside of the Head export?

v4iv commented 1 year ago

No 🙁

Pjaerr commented 1 year ago

👋 @v4iv ...just incase this is useful to you. Our workaround to accessing the translations inside of the Head export is to create a hook called useHeadTranslation():

/**
 * A temporary workaround that lets us access our translation strings from within the Gatsby Head export.
 * In the future the hope is that we can replace this like-for-like with the useTranslation() hook from 'gatsby-plugin-react-i18next'.
 *
 * @param {import("gatsby-plugin-react-i18next/dist/types").PageContext} pageContext
 * @param {{locales: {edges: {node: {language: string; ns: string; data: string}}[]}}} pageData
 * @returns {{t: (key: string) => string}}
 */
const useHeadTranslation = (pageContext, pageData) => {
  const edges = pageData.locales.edges.filter(
    edge => edge.node.language === pageContext.language
  )

  return {
    t: key => {
      const path = key.split(".")

      const namespace = path[0]

      const translations = JSON.parse(
        edges.find(edge => edge.node.ns === namespace).node.data
      )

      // I don't like that this is really hard to understand. It's essentially letting us do `translations['about.title']` where "about.title" is dynamic. 🤔
      return (
        path.reduce((arr, pathSegment) => arr[pathSegment], translations) ?? key
      )
    },
  }
}

export default useHeadTranslation

which you can import and use as:

import useHeadTranslation from "@/hooks/use-head-translation"

export const Head = ({ data, pageContext }) => {
  const { t } = useHeadTranslation(pageContext, data)

  return <SEO title={t("about.title")} description={t("about.description")} />
}

This all assumes that your page is querying for your locales like:

locales: allLocale {
      edges {
        node {
          ns
          data
          language
        }
      }
    }

This method works quite well (for us) as you get vscode intellisense as we're still technically using the t() function. Worth noting that the code I shared doesn't support dynamic values (translation strings like My name is {{name}}) but could easily be tweaked to support this if you wanted.

Hope this helps you 🤞

v4iv commented 1 year ago

Thanks bud!