1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00

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

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 commit is contained in:
Rafael Almeida 2018-10-11 11:20:01 -03:00 committed by Tim Neutkens
parent 384fbdc3aa
commit 449dd29da0
5 changed files with 10 additions and 9 deletions

View file

@ -1,10 +1,10 @@
import React from 'react'
import { translate } from 'react-i18next'
import { withNamespaces } from 'react-i18next'
function MyComponent ({ t }) {
return <p>{t('extendedComponent')}</p>
}
const Extended = translate('common')(MyComponent)
const Extended = withNamespaces('common')(MyComponent)
export default Extended

View file

@ -39,7 +39,7 @@ 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
req.i18n.toJSON = () => {} // do not serialize i18next instance to prevent circular references on the client
const initialI18nStore = {}
req.i18n.languages.forEach((l) => {

View file

@ -1,8 +1,8 @@
import { translate } from 'react-i18next'
import { withNamespaces } from 'react-i18next'
import i18n from '../i18n'
export const withI18next = (namespaces = ['common']) => ComposedComponent => {
const Extended = translate(namespaces, { wait: process.browser })(
const Extended = withNamespaces(namespaces, { wait: process.browser })(
ComposedComponent
)

View file

@ -20,6 +20,6 @@
"next": "latest",
"react": "^16.5.2",
"react-dom": "^16.5.2",
"react-i18next": "7.13.0"
"react-i18next": "8.0.6"
}
}

View file

@ -1,6 +1,6 @@
import React from 'react'
import App, { Container } from 'next/app'
import { I18n as I18nR, I18nextProvider } from 'react-i18next'
import { NamespacesConsumer, I18nextProvider } from 'react-i18next'
import initialI18nInstance from '../i18n'
import LanguageSwitch from '../components/LanguageSwitch'
@ -17,10 +17,11 @@ export default class MyApp extends App {
initialLanguage={initialLanguage}
>
<React.Fragment>
<I18nR ns='common' wait>
<NamespacesConsumer ns='common' wait>
{t => <h1>{t('common:integrates_react-i18next')}</h1>}
</I18nR>
</NamespacesConsumer>
<LanguageSwitch />
<Component {...pageProps} />
</React.Fragment>
</I18nextProvider>