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

32 lines
953 B
JavaScript
Raw Normal View History

#5620: Fix react-i18next example to properly SSR (#5265) This fixes https://github.com/zeit/next.js/issues/5260 by making sure that `index.js` has `getInitialProps` defined on the page exported component, not the child component. When fixing that, I uncovered an issue where the server side rendered HTML did not match the clientside HTML, so I reworked _app.js to use the `i18nextprovider` component which has props to hydrate the initial data (for SSR), and makes sure the correct i18n instance is passed to all child components through context. Before: ```html <!DOCTYPE html> <html> <head> <meta charSet="utf-8" class="next-head"/> <link rel="preload" href="/_next/static/development/pages/index.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_app.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_error.js" as="script"/> <link rel="preload" href="/_next/static/runtime/webpack.js" as="script"/> <link rel="preload" href="/_next/static/runtime/main.js" as="script"/> </head> <body> <div id="__next"></div> <script src="/_next/static/development/dll/dll_4a2ab6ce0cb456fbfead.js"></script><script>__NEXT_DATA__ = {"props":{"pageProps":{}},"page":"/","pathname":"/","query":{},"buildId":"development"};__NEXT_LOADED_PAGES__=[];__NEXT_REGISTER_PAGE=function(r,f){__NEXT_LOADED_PAGES__.push([r, f])}</script><script async="" id="__NEXT_PAGE__/" src="/_next/static/development/pages/index.js"></script><script async="" id="__NEXT_PAGE__/_app" src="/_next/static/development/pages/_app.js"></script><script async="" id="__NEXT_PAGE__/_error" src="/_next/static/development/pages/_error.js"></script><script src="/_next/static/runtime/webpack.js" async=""></script><script src="/_next/static/runtime/main.js" async=""></script> </body> </html> ``` After: ```html <!DOCTYPE html> <html> <head> <meta charSet="utf-8" class="next-head"/> <link rel="preload" href="/_next/static/development/pages/index.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_app.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_error.js" as="script"/> <link rel="preload" href="/_next/static/runtime/webpack.js" as="script"/> <link rel="preload" href="/_next/static/runtime/main.js" as="script"/> </head> <body> <div id="__next"> <h1>This example integrates react-i18next for simple internationalization.</h1> <div> <h1>welcome to next.js</h1> <p>This example integrates react-i18next for simple internationalization.</p> <p>test words for en</p> <div><button>fire in the wind for en</button></div> <p>You can either pass t function to child components.</p> <p>Or wrap your component using the translate hoc provided by react-i18next.</p> <p>Alternatively, you can use <code>Trans</code> component.</p> <a href="/page2">Go to page 2</a><br/><a href="/page3">Go to page 3 (no hoc)</a> </div> </div> <script src="/_next/static/development/dll/dll_4a2ab6ce0cb456fbfead.js"></script><script>__NEXT_DATA__ = {"props":{"pageProps":{"i18n":null,"initialI18nStore":{"en":{"home":{"welcome":"welcome to next.js","sample_test":"test words for en","sample_button":"fire in the wind for en","link":{"gotoPage2":"Go to page 2","gotoPage3":"Go to page 3 (no hoc)"}},"common":{"integrates_react-i18next":"This example integrates react-i18next for simple internationalization.","pureComponent":"You can either pass t function to child components.","extendedComponent":"Or wrap your component using the translate hoc provided by react-i18next.","transComponent":"Alternatively, you can use \u003c1\u003eTrans\u003c/1\u003e component."}}},"initialLanguage":"en-US"}},"page":"/","pathname":"/","query":{},"buildId":"development"};__NEXT_LOADED_PAGES__=[];__NEXT_REGISTER_PAGE=function(r,f){__NEXT_LOADED_PAGES__.push([r, f])}</script><script async="" id="__NEXT_PAGE__/" src="/_next/static/development/pages/index.js"></script><script async="" id="__NEXT_PAGE__/_app" src="/_next/static/development/pages/_app.js"></script><script async="" id="__NEXT_PAGE__/_error" src="/_next/static/development/pages/_error.js"></script><script src="/_next/static/runtime/webpack.js" async=""></script><script src="/_next/static/runtime/main.js" async=""></script> </body> </html> ```
2018-09-24 10:13:38 +00:00
import React from 'react'
import App, { Container } from 'next/app'
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.
2018-10-11 14:20:01 +00:00
import { NamespacesConsumer, I18nextProvider } from 'react-i18next'
#5620: Fix react-i18next example to properly SSR (#5265) This fixes https://github.com/zeit/next.js/issues/5260 by making sure that `index.js` has `getInitialProps` defined on the page exported component, not the child component. When fixing that, I uncovered an issue where the server side rendered HTML did not match the clientside HTML, so I reworked _app.js to use the `i18nextprovider` component which has props to hydrate the initial data (for SSR), and makes sure the correct i18n instance is passed to all child components through context. Before: ```html <!DOCTYPE html> <html> <head> <meta charSet="utf-8" class="next-head"/> <link rel="preload" href="/_next/static/development/pages/index.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_app.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_error.js" as="script"/> <link rel="preload" href="/_next/static/runtime/webpack.js" as="script"/> <link rel="preload" href="/_next/static/runtime/main.js" as="script"/> </head> <body> <div id="__next"></div> <script src="/_next/static/development/dll/dll_4a2ab6ce0cb456fbfead.js"></script><script>__NEXT_DATA__ = {"props":{"pageProps":{}},"page":"/","pathname":"/","query":{},"buildId":"development"};__NEXT_LOADED_PAGES__=[];__NEXT_REGISTER_PAGE=function(r,f){__NEXT_LOADED_PAGES__.push([r, f])}</script><script async="" id="__NEXT_PAGE__/" src="/_next/static/development/pages/index.js"></script><script async="" id="__NEXT_PAGE__/_app" src="/_next/static/development/pages/_app.js"></script><script async="" id="__NEXT_PAGE__/_error" src="/_next/static/development/pages/_error.js"></script><script src="/_next/static/runtime/webpack.js" async=""></script><script src="/_next/static/runtime/main.js" async=""></script> </body> </html> ``` After: ```html <!DOCTYPE html> <html> <head> <meta charSet="utf-8" class="next-head"/> <link rel="preload" href="/_next/static/development/pages/index.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_app.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_error.js" as="script"/> <link rel="preload" href="/_next/static/runtime/webpack.js" as="script"/> <link rel="preload" href="/_next/static/runtime/main.js" as="script"/> </head> <body> <div id="__next"> <h1>This example integrates react-i18next for simple internationalization.</h1> <div> <h1>welcome to next.js</h1> <p>This example integrates react-i18next for simple internationalization.</p> <p>test words for en</p> <div><button>fire in the wind for en</button></div> <p>You can either pass t function to child components.</p> <p>Or wrap your component using the translate hoc provided by react-i18next.</p> <p>Alternatively, you can use <code>Trans</code> component.</p> <a href="/page2">Go to page 2</a><br/><a href="/page3">Go to page 3 (no hoc)</a> </div> </div> <script src="/_next/static/development/dll/dll_4a2ab6ce0cb456fbfead.js"></script><script>__NEXT_DATA__ = {"props":{"pageProps":{"i18n":null,"initialI18nStore":{"en":{"home":{"welcome":"welcome to next.js","sample_test":"test words for en","sample_button":"fire in the wind for en","link":{"gotoPage2":"Go to page 2","gotoPage3":"Go to page 3 (no hoc)"}},"common":{"integrates_react-i18next":"This example integrates react-i18next for simple internationalization.","pureComponent":"You can either pass t function to child components.","extendedComponent":"Or wrap your component using the translate hoc provided by react-i18next.","transComponent":"Alternatively, you can use \u003c1\u003eTrans\u003c/1\u003e component."}}},"initialLanguage":"en-US"}},"page":"/","pathname":"/","query":{},"buildId":"development"};__NEXT_LOADED_PAGES__=[];__NEXT_REGISTER_PAGE=function(r,f){__NEXT_LOADED_PAGES__.push([r, f])}</script><script async="" id="__NEXT_PAGE__/" src="/_next/static/development/pages/index.js"></script><script async="" id="__NEXT_PAGE__/_app" src="/_next/static/development/pages/_app.js"></script><script async="" id="__NEXT_PAGE__/_error" src="/_next/static/development/pages/_error.js"></script><script src="/_next/static/runtime/webpack.js" async=""></script><script src="/_next/static/runtime/main.js" async=""></script> </body> </html> ```
2018-09-24 10:13:38 +00:00
import initialI18nInstance from '../i18n'
import LanguageSwitch from '../components/LanguageSwitch'
export default class MyApp extends App {
render () {
const { Component, pageProps } = this.props
#5620: Fix react-i18next example to properly SSR (#5265) This fixes https://github.com/zeit/next.js/issues/5260 by making sure that `index.js` has `getInitialProps` defined on the page exported component, not the child component. When fixing that, I uncovered an issue where the server side rendered HTML did not match the clientside HTML, so I reworked _app.js to use the `i18nextprovider` component which has props to hydrate the initial data (for SSR), and makes sure the correct i18n instance is passed to all child components through context. Before: ```html <!DOCTYPE html> <html> <head> <meta charSet="utf-8" class="next-head"/> <link rel="preload" href="/_next/static/development/pages/index.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_app.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_error.js" as="script"/> <link rel="preload" href="/_next/static/runtime/webpack.js" as="script"/> <link rel="preload" href="/_next/static/runtime/main.js" as="script"/> </head> <body> <div id="__next"></div> <script src="/_next/static/development/dll/dll_4a2ab6ce0cb456fbfead.js"></script><script>__NEXT_DATA__ = {"props":{"pageProps":{}},"page":"/","pathname":"/","query":{},"buildId":"development"};__NEXT_LOADED_PAGES__=[];__NEXT_REGISTER_PAGE=function(r,f){__NEXT_LOADED_PAGES__.push([r, f])}</script><script async="" id="__NEXT_PAGE__/" src="/_next/static/development/pages/index.js"></script><script async="" id="__NEXT_PAGE__/_app" src="/_next/static/development/pages/_app.js"></script><script async="" id="__NEXT_PAGE__/_error" src="/_next/static/development/pages/_error.js"></script><script src="/_next/static/runtime/webpack.js" async=""></script><script src="/_next/static/runtime/main.js" async=""></script> </body> </html> ``` After: ```html <!DOCTYPE html> <html> <head> <meta charSet="utf-8" class="next-head"/> <link rel="preload" href="/_next/static/development/pages/index.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_app.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_error.js" as="script"/> <link rel="preload" href="/_next/static/runtime/webpack.js" as="script"/> <link rel="preload" href="/_next/static/runtime/main.js" as="script"/> </head> <body> <div id="__next"> <h1>This example integrates react-i18next for simple internationalization.</h1> <div> <h1>welcome to next.js</h1> <p>This example integrates react-i18next for simple internationalization.</p> <p>test words for en</p> <div><button>fire in the wind for en</button></div> <p>You can either pass t function to child components.</p> <p>Or wrap your component using the translate hoc provided by react-i18next.</p> <p>Alternatively, you can use <code>Trans</code> component.</p> <a href="/page2">Go to page 2</a><br/><a href="/page3">Go to page 3 (no hoc)</a> </div> </div> <script src="/_next/static/development/dll/dll_4a2ab6ce0cb456fbfead.js"></script><script>__NEXT_DATA__ = {"props":{"pageProps":{"i18n":null,"initialI18nStore":{"en":{"home":{"welcome":"welcome to next.js","sample_test":"test words for en","sample_button":"fire in the wind for en","link":{"gotoPage2":"Go to page 2","gotoPage3":"Go to page 3 (no hoc)"}},"common":{"integrates_react-i18next":"This example integrates react-i18next for simple internationalization.","pureComponent":"You can either pass t function to child components.","extendedComponent":"Or wrap your component using the translate hoc provided by react-i18next.","transComponent":"Alternatively, you can use \u003c1\u003eTrans\u003c/1\u003e component."}}},"initialLanguage":"en-US"}},"page":"/","pathname":"/","query":{},"buildId":"development"};__NEXT_LOADED_PAGES__=[];__NEXT_REGISTER_PAGE=function(r,f){__NEXT_LOADED_PAGES__.push([r, f])}</script><script async="" id="__NEXT_PAGE__/" src="/_next/static/development/pages/index.js"></script><script async="" id="__NEXT_PAGE__/_app" src="/_next/static/development/pages/_app.js"></script><script async="" id="__NEXT_PAGE__/_error" src="/_next/static/development/pages/_error.js"></script><script src="/_next/static/runtime/webpack.js" async=""></script><script src="/_next/static/runtime/main.js" async=""></script> </body> </html> ```
2018-09-24 10:13:38 +00:00
const { i18n, initialI18nStore, initialLanguage } = pageProps || {}
return (
<Container>
#5620: Fix react-i18next example to properly SSR (#5265) This fixes https://github.com/zeit/next.js/issues/5260 by making sure that `index.js` has `getInitialProps` defined on the page exported component, not the child component. When fixing that, I uncovered an issue where the server side rendered HTML did not match the clientside HTML, so I reworked _app.js to use the `i18nextprovider` component which has props to hydrate the initial data (for SSR), and makes sure the correct i18n instance is passed to all child components through context. Before: ```html <!DOCTYPE html> <html> <head> <meta charSet="utf-8" class="next-head"/> <link rel="preload" href="/_next/static/development/pages/index.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_app.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_error.js" as="script"/> <link rel="preload" href="/_next/static/runtime/webpack.js" as="script"/> <link rel="preload" href="/_next/static/runtime/main.js" as="script"/> </head> <body> <div id="__next"></div> <script src="/_next/static/development/dll/dll_4a2ab6ce0cb456fbfead.js"></script><script>__NEXT_DATA__ = {"props":{"pageProps":{}},"page":"/","pathname":"/","query":{},"buildId":"development"};__NEXT_LOADED_PAGES__=[];__NEXT_REGISTER_PAGE=function(r,f){__NEXT_LOADED_PAGES__.push([r, f])}</script><script async="" id="__NEXT_PAGE__/" src="/_next/static/development/pages/index.js"></script><script async="" id="__NEXT_PAGE__/_app" src="/_next/static/development/pages/_app.js"></script><script async="" id="__NEXT_PAGE__/_error" src="/_next/static/development/pages/_error.js"></script><script src="/_next/static/runtime/webpack.js" async=""></script><script src="/_next/static/runtime/main.js" async=""></script> </body> </html> ``` After: ```html <!DOCTYPE html> <html> <head> <meta charSet="utf-8" class="next-head"/> <link rel="preload" href="/_next/static/development/pages/index.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_app.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_error.js" as="script"/> <link rel="preload" href="/_next/static/runtime/webpack.js" as="script"/> <link rel="preload" href="/_next/static/runtime/main.js" as="script"/> </head> <body> <div id="__next"> <h1>This example integrates react-i18next for simple internationalization.</h1> <div> <h1>welcome to next.js</h1> <p>This example integrates react-i18next for simple internationalization.</p> <p>test words for en</p> <div><button>fire in the wind for en</button></div> <p>You can either pass t function to child components.</p> <p>Or wrap your component using the translate hoc provided by react-i18next.</p> <p>Alternatively, you can use <code>Trans</code> component.</p> <a href="/page2">Go to page 2</a><br/><a href="/page3">Go to page 3 (no hoc)</a> </div> </div> <script src="/_next/static/development/dll/dll_4a2ab6ce0cb456fbfead.js"></script><script>__NEXT_DATA__ = {"props":{"pageProps":{"i18n":null,"initialI18nStore":{"en":{"home":{"welcome":"welcome to next.js","sample_test":"test words for en","sample_button":"fire in the wind for en","link":{"gotoPage2":"Go to page 2","gotoPage3":"Go to page 3 (no hoc)"}},"common":{"integrates_react-i18next":"This example integrates react-i18next for simple internationalization.","pureComponent":"You can either pass t function to child components.","extendedComponent":"Or wrap your component using the translate hoc provided by react-i18next.","transComponent":"Alternatively, you can use \u003c1\u003eTrans\u003c/1\u003e component."}}},"initialLanguage":"en-US"}},"page":"/","pathname":"/","query":{},"buildId":"development"};__NEXT_LOADED_PAGES__=[];__NEXT_REGISTER_PAGE=function(r,f){__NEXT_LOADED_PAGES__.push([r, f])}</script><script async="" id="__NEXT_PAGE__/" src="/_next/static/development/pages/index.js"></script><script async="" id="__NEXT_PAGE__/_app" src="/_next/static/development/pages/_app.js"></script><script async="" id="__NEXT_PAGE__/_error" src="/_next/static/development/pages/_error.js"></script><script src="/_next/static/runtime/webpack.js" async=""></script><script src="/_next/static/runtime/main.js" async=""></script> </body> </html> ```
2018-09-24 10:13:38 +00:00
<I18nextProvider
i18n={i18n || initialI18nInstance}
initialI18nStore={initialI18nStore}
initialLanguage={initialLanguage}
>
<React.Fragment>
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.
2018-10-11 14:20:01 +00:00
<NamespacesConsumer ns='common' wait>
#5620: Fix react-i18next example to properly SSR (#5265) This fixes https://github.com/zeit/next.js/issues/5260 by making sure that `index.js` has `getInitialProps` defined on the page exported component, not the child component. When fixing that, I uncovered an issue where the server side rendered HTML did not match the clientside HTML, so I reworked _app.js to use the `i18nextprovider` component which has props to hydrate the initial data (for SSR), and makes sure the correct i18n instance is passed to all child components through context. Before: ```html <!DOCTYPE html> <html> <head> <meta charSet="utf-8" class="next-head"/> <link rel="preload" href="/_next/static/development/pages/index.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_app.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_error.js" as="script"/> <link rel="preload" href="/_next/static/runtime/webpack.js" as="script"/> <link rel="preload" href="/_next/static/runtime/main.js" as="script"/> </head> <body> <div id="__next"></div> <script src="/_next/static/development/dll/dll_4a2ab6ce0cb456fbfead.js"></script><script>__NEXT_DATA__ = {"props":{"pageProps":{}},"page":"/","pathname":"/","query":{},"buildId":"development"};__NEXT_LOADED_PAGES__=[];__NEXT_REGISTER_PAGE=function(r,f){__NEXT_LOADED_PAGES__.push([r, f])}</script><script async="" id="__NEXT_PAGE__/" src="/_next/static/development/pages/index.js"></script><script async="" id="__NEXT_PAGE__/_app" src="/_next/static/development/pages/_app.js"></script><script async="" id="__NEXT_PAGE__/_error" src="/_next/static/development/pages/_error.js"></script><script src="/_next/static/runtime/webpack.js" async=""></script><script src="/_next/static/runtime/main.js" async=""></script> </body> </html> ``` After: ```html <!DOCTYPE html> <html> <head> <meta charSet="utf-8" class="next-head"/> <link rel="preload" href="/_next/static/development/pages/index.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_app.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_error.js" as="script"/> <link rel="preload" href="/_next/static/runtime/webpack.js" as="script"/> <link rel="preload" href="/_next/static/runtime/main.js" as="script"/> </head> <body> <div id="__next"> <h1>This example integrates react-i18next for simple internationalization.</h1> <div> <h1>welcome to next.js</h1> <p>This example integrates react-i18next for simple internationalization.</p> <p>test words for en</p> <div><button>fire in the wind for en</button></div> <p>You can either pass t function to child components.</p> <p>Or wrap your component using the translate hoc provided by react-i18next.</p> <p>Alternatively, you can use <code>Trans</code> component.</p> <a href="/page2">Go to page 2</a><br/><a href="/page3">Go to page 3 (no hoc)</a> </div> </div> <script src="/_next/static/development/dll/dll_4a2ab6ce0cb456fbfead.js"></script><script>__NEXT_DATA__ = {"props":{"pageProps":{"i18n":null,"initialI18nStore":{"en":{"home":{"welcome":"welcome to next.js","sample_test":"test words for en","sample_button":"fire in the wind for en","link":{"gotoPage2":"Go to page 2","gotoPage3":"Go to page 3 (no hoc)"}},"common":{"integrates_react-i18next":"This example integrates react-i18next for simple internationalization.","pureComponent":"You can either pass t function to child components.","extendedComponent":"Or wrap your component using the translate hoc provided by react-i18next.","transComponent":"Alternatively, you can use \u003c1\u003eTrans\u003c/1\u003e component."}}},"initialLanguage":"en-US"}},"page":"/","pathname":"/","query":{},"buildId":"development"};__NEXT_LOADED_PAGES__=[];__NEXT_REGISTER_PAGE=function(r,f){__NEXT_LOADED_PAGES__.push([r, f])}</script><script async="" id="__NEXT_PAGE__/" src="/_next/static/development/pages/index.js"></script><script async="" id="__NEXT_PAGE__/_app" src="/_next/static/development/pages/_app.js"></script><script async="" id="__NEXT_PAGE__/_error" src="/_next/static/development/pages/_error.js"></script><script src="/_next/static/runtime/webpack.js" async=""></script><script src="/_next/static/runtime/main.js" async=""></script> </body> </html> ```
2018-09-24 10:13:38 +00:00
{t => <h1>{t('common:integrates_react-i18next')}</h1>}
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.
2018-10-11 14:20:01 +00:00
</NamespacesConsumer>
<LanguageSwitch />
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.
2018-10-11 14:20:01 +00:00
#5620: Fix react-i18next example to properly SSR (#5265) This fixes https://github.com/zeit/next.js/issues/5260 by making sure that `index.js` has `getInitialProps` defined on the page exported component, not the child component. When fixing that, I uncovered an issue where the server side rendered HTML did not match the clientside HTML, so I reworked _app.js to use the `i18nextprovider` component which has props to hydrate the initial data (for SSR), and makes sure the correct i18n instance is passed to all child components through context. Before: ```html <!DOCTYPE html> <html> <head> <meta charSet="utf-8" class="next-head"/> <link rel="preload" href="/_next/static/development/pages/index.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_app.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_error.js" as="script"/> <link rel="preload" href="/_next/static/runtime/webpack.js" as="script"/> <link rel="preload" href="/_next/static/runtime/main.js" as="script"/> </head> <body> <div id="__next"></div> <script src="/_next/static/development/dll/dll_4a2ab6ce0cb456fbfead.js"></script><script>__NEXT_DATA__ = {"props":{"pageProps":{}},"page":"/","pathname":"/","query":{},"buildId":"development"};__NEXT_LOADED_PAGES__=[];__NEXT_REGISTER_PAGE=function(r,f){__NEXT_LOADED_PAGES__.push([r, f])}</script><script async="" id="__NEXT_PAGE__/" src="/_next/static/development/pages/index.js"></script><script async="" id="__NEXT_PAGE__/_app" src="/_next/static/development/pages/_app.js"></script><script async="" id="__NEXT_PAGE__/_error" src="/_next/static/development/pages/_error.js"></script><script src="/_next/static/runtime/webpack.js" async=""></script><script src="/_next/static/runtime/main.js" async=""></script> </body> </html> ``` After: ```html <!DOCTYPE html> <html> <head> <meta charSet="utf-8" class="next-head"/> <link rel="preload" href="/_next/static/development/pages/index.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_app.js" as="script"/> <link rel="preload" href="/_next/static/development/pages/_error.js" as="script"/> <link rel="preload" href="/_next/static/runtime/webpack.js" as="script"/> <link rel="preload" href="/_next/static/runtime/main.js" as="script"/> </head> <body> <div id="__next"> <h1>This example integrates react-i18next for simple internationalization.</h1> <div> <h1>welcome to next.js</h1> <p>This example integrates react-i18next for simple internationalization.</p> <p>test words for en</p> <div><button>fire in the wind for en</button></div> <p>You can either pass t function to child components.</p> <p>Or wrap your component using the translate hoc provided by react-i18next.</p> <p>Alternatively, you can use <code>Trans</code> component.</p> <a href="/page2">Go to page 2</a><br/><a href="/page3">Go to page 3 (no hoc)</a> </div> </div> <script src="/_next/static/development/dll/dll_4a2ab6ce0cb456fbfead.js"></script><script>__NEXT_DATA__ = {"props":{"pageProps":{"i18n":null,"initialI18nStore":{"en":{"home":{"welcome":"welcome to next.js","sample_test":"test words for en","sample_button":"fire in the wind for en","link":{"gotoPage2":"Go to page 2","gotoPage3":"Go to page 3 (no hoc)"}},"common":{"integrates_react-i18next":"This example integrates react-i18next for simple internationalization.","pureComponent":"You can either pass t function to child components.","extendedComponent":"Or wrap your component using the translate hoc provided by react-i18next.","transComponent":"Alternatively, you can use \u003c1\u003eTrans\u003c/1\u003e component."}}},"initialLanguage":"en-US"}},"page":"/","pathname":"/","query":{},"buildId":"development"};__NEXT_LOADED_PAGES__=[];__NEXT_REGISTER_PAGE=function(r,f){__NEXT_LOADED_PAGES__.push([r, f])}</script><script async="" id="__NEXT_PAGE__/" src="/_next/static/development/pages/index.js"></script><script async="" id="__NEXT_PAGE__/_app" src="/_next/static/development/pages/_app.js"></script><script async="" id="__NEXT_PAGE__/_error" src="/_next/static/development/pages/_error.js"></script><script src="/_next/static/runtime/webpack.js" async=""></script><script src="/_next/static/runtime/main.js" async=""></script> </body> </html> ```
2018-09-24 10:13:38 +00:00
<Component {...pageProps} />
</React.Fragment>
</I18nextProvider>
</Container>
)
}
}