diff --git a/examples/with-react-i18next/README.md b/examples/with-react-i18next/README.md index b6d1ddd4..535c9b24 100644 --- a/examples/with-react-i18next/README.md +++ b/examples/with-react-i18next/README.md @@ -53,30 +53,30 @@ This example app shows how to integrate [react-i18next](https://github.com/i18ne **Plus:** -* Routing and separating translations into multiple files (lazy load them on client routing) -* Child components (pure or using translation hoc) +- Routing and separating translations into multiple files (lazy load them on client routing) +- Child components (pure or using translation hoc) ### Features of this example app -* Server-side language negotiation -* Full control and usage of i18next on express server using [i18next-express-middleware](https://github.com/i18next/i18next-express-middleware) which asserts no async request collisions resulting in wrong language renderings -* Support for save missing features to get untranslated keys automatically created `locales/{lng}/{namespace}.missing.json` -> never miss to translate a key -* Proper pass down on translations via initialProps -* Taking advantage of multiple translation files including lazy loading on client (no need to load all translations upfront) -* Use express to also serve translations for clientside -* In contrast to react-intl the translations are visible both during development and in production +- Server-side language negotiation +- Full control and usage of i18next on express server using [i18next-express-middleware](https://github.com/i18next/i18next-express-middleware) which asserts no async request collisions resulting in wrong language renderings +- Support for save missing features to get untranslated keys automatically created `locales/{lng}/{namespace}.missing.json` -> never miss to translate a key +- Proper pass down on translations via initialProps +- Taking advantage of multiple translation files including lazy loading on client (no need to load all translations upfront) +- Use express to also serve translations for clientside +- In contrast to react-intl the translations are visible both during development and in production ### learn more -* [next.js](https://github.com/zeit/next.js) -* [react-i18next repository](https://github.com/i18next/react-i18next) -* [react-i18next documentation](https://react.i18next.com) +- [next.js](https://github.com/zeit/next.js) +- [react-i18next repository](https://github.com/i18next/react-i18next) +- [react-i18next documentation](https://react.i18next.com) **Translation features:** -* [i18next repository](https://github.com/i18next/i18next) -* [i18next documentation](https://www.i18next.com) +- [i18next repository](https://github.com/i18next/i18next) +- [i18next documentation](https://www.i18next.com) **Translation management:** -* [locize](http://locize.com) +- [locize](http://locize.com) diff --git a/examples/with-react-i18next/i18n.js b/examples/with-react-i18next/i18n.js index c0bc635c..d836770e 100644 --- a/examples/with-react-i18next/i18n.js +++ b/examples/with-react-i18next/i18n.js @@ -1,4 +1,4 @@ -const i18next = require('i18next') +const i18n = require('i18next') const XHR = require('i18next-xhr-backend') const LanguageDetector = require('i18next-browser-languagedetector') @@ -10,7 +10,7 @@ const options = { ns: ['common'], defaultNS: 'common', - debug: process.env.NODE_ENV !== 'production', + debug: false, // process.env.NODE_ENV !== 'production', saveMissing: true, interpolation: { @@ -23,22 +23,20 @@ const options = { } } -const i18nInstance = i18next - // for browser use xhr backend to load translations and browser lng detector if (process.browser) { - i18nInstance + i18n .use(XHR) // .use(Cache) .use(LanguageDetector) } // initialize if not already initialized -if (!i18nInstance.isInitialized) i18nInstance.init(options) +if (!i18n.isInitialized) i18n.init(options) // a simple helper to getInitialProps passed on loaded i18n data -const getInitialProps = (req, namespaces) => { - if (!namespaces) namespaces = i18nInstance.options.defaultNS +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 @@ -58,8 +56,4 @@ const getInitialProps = (req, namespaces) => { } } -module.exports = { - getInitialProps, - i18nInstance, - I18n: i18next.default -} +module.exports = i18n diff --git a/examples/with-react-i18next/lib/withI18next.js b/examples/with-react-i18next/lib/withI18next.js index 3e1f87af..8d521c73 100644 --- a/examples/with-react-i18next/lib/withI18next.js +++ b/examples/with-react-i18next/lib/withI18next.js @@ -1,8 +1,8 @@ -import { translate, loadNamespaces } from 'react-i18next' -import { getInitialProps, I18n } from '../i18n' +import { translate } from 'react-i18next' +import i18n from '../i18n' export const withI18next = (namespaces = ['common']) => ComposedComponent => { - const Extended = translate(namespaces, { i18n: I18n, wait: process.browser })( + const Extended = translate(namespaces, { i18n, wait: process.browser })( ComposedComponent ) @@ -12,11 +12,8 @@ export const withI18next = (namespaces = ['common']) => ComposedComponent => { : {} const i18nInitialProps = ctx.req - ? getInitialProps(ctx.req, namespaces) - : await loadNamespaces({ - components: [{ props: { namespaces } }], - i18n: I18n - }) + ? i18n.getInitialProps(ctx.req, namespaces) + : {} return { ...composedInitialProps, diff --git a/examples/with-react-i18next/locales/de/home.json b/examples/with-react-i18next/locales/de/home.json index 689b8237..3250ae4d 100644 --- a/examples/with-react-i18next/locales/de/home.json +++ b/examples/with-react-i18next/locales/de/home.json @@ -1,6 +1,9 @@ { "welcome": "Willkommen zu next.js", + "sample_test": "test words for de", + "sample_button": "fire in the wind for de", "link": { - "gotoPage2": "Zur Seite 2" + "gotoPage2": "Zur Seite 2", + "gotoPage3": "Zur Seite 3 (no hoc)" } } diff --git a/examples/with-react-i18next/locales/en/home.json b/examples/with-react-i18next/locales/en/home.json index b4870bde..5e8b9e44 100644 --- a/examples/with-react-i18next/locales/en/home.json +++ b/examples/with-react-i18next/locales/en/home.json @@ -1,6 +1,9 @@ { "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" + "gotoPage2": "Go to page 2", + "gotoPage3": "Go to page 3 (no hoc)" } } diff --git a/examples/with-react-i18next/package.json b/examples/with-react-i18next/package.json index f69b9713..541e23af 100644 --- a/examples/with-react-i18next/package.json +++ b/examples/with-react-i18next/package.json @@ -11,15 +11,15 @@ "author": "", "license": "MIT", "dependencies": { - "express": "4.16.2", - "i18next": "10.4.1", - "i18next-browser-languagedetector": "2.1.0", - "i18next-express-middleware": "1.0.10", - "i18next-node-fs-backend": "1.0.0", + "express": "4.16.3", + "i18next": "11.3.6", + "i18next-browser-languagedetector": "2.2.0", + "i18next-express-middleware": "1.2.0", + "i18next-node-fs-backend": "1.2.1", "i18next-xhr-backend": "1.5.1", - "next": "5.0.0", - "react": "16.2.0", - "react-dom": "16.2.0", - "react-i18next": "7.3.6" + "next": "^6.1.1", + "react": "^16.4.1", + "react-dom": "^16.4.1", + "react-i18next": "7.8.1" } } diff --git a/examples/with-react-i18next/pages/_app.js b/examples/with-react-i18next/pages/_app.js new file mode 100644 index 00000000..6b2d7db4 --- /dev/null +++ b/examples/with-react-i18next/pages/_app.js @@ -0,0 +1,24 @@ +import App, { Container } from 'next/app' +import { I18n as I18nR } from 'react-i18next' +import i18n from '../i18n' + +export default class MyApp extends App { + render () { + const { Component, pageProps } = this.props + + return ( + + + { + (t) => ( +
+

{t('common:integrates_react-i18next')}

+ +
+ ) + } +
+
+ ) + } +} diff --git a/examples/with-react-i18next/pages/index.js b/examples/with-react-i18next/pages/index.js index 2b67c976..6669283a 100644 --- a/examples/with-react-i18next/pages/index.js +++ b/examples/with-react-i18next/pages/index.js @@ -6,15 +6,29 @@ import ExtendedComponent from '../components/ExtendedComponent' import ComponentWithTrans from '../components/ComponentWithTrans' import { withI18next } from '../lib/withI18next' -export default withI18next(['home', 'common'])(({ t, initialI18nStore }) => ( +const TestContent = withI18next(['home', 'common'])(({ t, initialI18nStore }) => (

{t('welcome')}

{t('common:integrates_react-i18next')}

+

{t('sample_test')}

+
+ +
{t('link.gotoPage2')} +
+ + {t('link.gotoPage3')} +
)) + +const Test = () => { + return +} + +export default Test diff --git a/examples/with-react-i18next/pages/page2.js b/examples/with-react-i18next/pages/page2.js index 360dbb0a..f5b566eb 100644 --- a/examples/with-react-i18next/pages/page2.js +++ b/examples/with-react-i18next/pages/page2.js @@ -6,7 +6,7 @@ import ExtendedComponent from '../components/ExtendedComponent' import ComponentWithTrans from '../components/ComponentWithTrans' import { withI18next } from '../lib/withI18next' -export default withI18next(['page2', 'common'])(({ t, initialI18nStore }) => ( +const Page2 = ({ t }) => (

{t('welcomePage2')}

{t('common:integrates_react-i18next')}

@@ -17,4 +17,6 @@ export default withI18next(['page2', 'common'])(({ t, initialI18nStore }) => ( {t('link.gotoPage1')}
-)) +) + +export default withI18next(['page2', 'common'])(Page2) diff --git a/examples/with-react-i18next/pages/page3.js b/examples/with-react-i18next/pages/page3.js new file mode 100644 index 00000000..52bff41a --- /dev/null +++ b/examples/with-react-i18next/pages/page3.js @@ -0,0 +1,14 @@ +// a page not using i18next - no hoc - not t function +import React from 'react' +import Link from 'next/link' + +export default () => { + return ( +
+

Hello Page 3

+ + back + +
+ ) +} diff --git a/examples/with-react-i18next/server.js b/examples/with-react-i18next/server.js index dcc046e7..5f2686e8 100644 --- a/examples/with-react-i18next/server.js +++ b/examples/with-react-i18next/server.js @@ -8,11 +8,11 @@ const handle = app.getRequestHandler() const i18nextMiddleware = require('i18next-express-middleware') const Backend = require('i18next-node-fs-backend') -const { i18nInstance } = require('./i18n') +const i18n = require('./i18n') // init i18next with serverside settings // using i18next-express-middleware -i18nInstance +i18n .use(Backend) .use(i18nextMiddleware.LanguageDetector) .init({ @@ -30,13 +30,13 @@ i18nInstance const server = express() // enable middleware for i18next - server.use(i18nextMiddleware.handle(i18nInstance)) + server.use(i18nextMiddleware.handle(i18n)) // serve locales for client server.use('/locales', express.static(path.join(__dirname, '/locales'))) // missing keys - server.post('/locales/add/:lng/:ns', i18nextMiddleware.missingKeyHandler(i18nInstance)) + server.post('/locales/add/:lng/:ns', i18nextMiddleware.missingKeyHandler(i18n)) // use next.js server.get('*', (req, res) => handle(req, res))