Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update with-react-i18next example to use react-i18next@8.0.6 #5368

Merged

Conversation

rafaelalmeidatk
Copy link
Contributor

@rafaelalmeidatk rafaelalmeidatk commented Oct 2, 2018

Fixes #5352 . This updates the example updating react-i18next to v8.0.6, replacing the translate HOC to withNamespaces and I18n to NamespacesConsumer.

There is one thing that I am not sure if is correct or not so I need some guidance. You gotta wrap the page with the withI18next HOC so it will extend the getInitialProps of the page with this:

Extended.getInitialProps = async (ctx) => {
  const composedInitialProps = ComposedComponent.getInitialProps
    ? await ComposedComponent.getInitialProps(ctx)
    : {}

  const i18nInitialProps = ctx.req
    ? i18n.getInitialProps(ctx.req, namespaces)
    : {}

  return {
    ...composedInitialProps,
    ...i18nInitialProps
  }
}

The problem lies in i18n.getInitialProps that has this code:

i18n.getInitialProps = (req, namespaces) => {
  if (!namespaces) namespaces = i18n.options.defaultNS
  if (typeof namespaces === 'string') namespaces = [namespaces]

  req.i18n.toJSON = () => null // do not serialize i18next instance and send to client

  const initialI18nStore = {}
  req.i18n.languages.forEach((l) => {
    initialI18nStore[l] = {}
    namespaces.forEach((ns) => {
      initialI18nStore[l][ns] = (req.i18n.services.resourceStore.data[l] || {})[ns] || {}
    })
  })

  return {
    i18n: req.i18n, // use the instance on req - fixed language on request (avoid issues in race conditions with lngs of different users)
    initialI18nStore,
    initialLanguage: req.i18n.language
  }
}

In my understanding, among other things, it gets the i18n object from the request (included by the server.js) and uses the data to create initialI18nStore and initialLanguage, and then return these two objects plus the i18n object itself. If you add the i18n object on the return, then there will be a crash on the client-side render of the page:

TypeError: Cannot read property 'ready' of null

I don't know why, but returning it breaks NamespacesConsumer component from react-i18next (the state becomes null). So I commented this line and the provider on _app.js is getting the i18n instance from the i18n.js file (the same as server.js). I don't know if this would be an issue so I would like help to debug this.

This updates react-i18next to v8.0.6, replacing the "translate" HOC to "withNamespaces" and "I18n to "NamespacesConsumer".

Also fixes a crash on the page don't inserting the i18n instance on the page props
@rafaelalmeidatk rafaelalmeidatk changed the title Update react-i18next to v8.0.6 Update with-react-i18next example to use react-i18next@8.0.6 Oct 2, 2018
@rafaelalmeidatk
Copy link
Contributor Author

Found the problem. i18n.getInitialProps is returning i18n on the props for the rendering of _app on the server-side, it should not exist on the client (that is why i18n={i18n || initialI18nInstance}) because serializing it results in a circular reference. What was causing the crash was the attempt to don't serialize it: the method toJSON was returning null so it was crashing the component anyway. I changed it and now it returns an empty object.

@marcelothomaz
Copy link

marcelothomaz commented Oct 14, 2018

Should we put a check whether req is defined or not in i18n.getInitialProps before doing req.i18n.language.forEach()?

Something similar to the example on react-i18next own repo:

// for serverside pass down initial translations
  if (req) {
    const initialI18nStore = {};
    req.i18n.languages.forEach(l => {
      initialI18nStore[l] = {};
      namespaces.forEach(ns => {
        initialI18nStore[l][ns] = (req.i18n.services.resourceStore.data[l] || {})[ns] || {};
      });
    });

    ret.initialI18nStore = initialI18nStore;
    ret.initialLanguage = req.i18n.language;
  }

@lock lock bot locked as resolved and limited conversation to collaborators Oct 14, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

with-react-i18next fails with react-i18next 8.0.4 (latest)
3 participants