Skip to content

Commit

Permalink
Implement tree-walking to determine namespace deps based on individua…
Browse files Browse the repository at this point in the history
…l requests
  • Loading branch information
isaachinman committed Dec 12, 2018
1 parent 9c8d15c commit 2386bf2
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 20 deletions.
8 changes: 7 additions & 1 deletion example/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4480,7 +4480,7 @@ neo-async@^2.5.0:
integrity sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==

next-i18next@../:
version "0.5.0"
version "0.9.0"
dependencies:
detect-node "^2.0.4"
hoist-non-react-statics "^3.2.0"
Expand All @@ -4492,6 +4492,7 @@ next-i18next@../:
prop-types "^15.6.2"
react "^16.6.3"
react-i18next "^8.3.8"
react-tree-walker "^4.3.0"

next@^7.0.2:
version "7.0.2"
Expand Down Expand Up @@ -5233,6 +5234,11 @@ react-is@^16.3.2:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.6.3.tgz#d2d7462fcfcbe6ec0da56ad69047e47e56e7eac0"
integrity sha512-u7FDWtthB4rWibG/+mFbVd5FvdI20yde86qKGx4lVUTWmPlSWQ4QxbBIrrs+HnXGbxOUlUzTAP/VDmvCwaP2yA==

react-tree-walker@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/react-tree-walker/-/react-tree-walker-4.3.0.tgz#b7cae498cebb490281e9e99a01bdb9c6b4926cd3"
integrity sha512-sO/pk+JQ2mbtPGdlKbeeo2aT4qXl5nPkGVO96yYQOdX9jYvRNXSnMWIydniLVEoiPvUbpfoc057blGbAQgMBRg==

react@^16.6.3:
version "16.6.3"
resolved "https://registry.yarnpkg.com/react/-/react-16.6.3.tgz#25d77c91911d6bbdd23db41e70fb094cc1e0871c"
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"i18next-xhr-backend": "^1.5.1",
"prop-types": "^15.6.2",
"react": "^16.6.3",
"react-i18next": "^8.3.8"
"react-i18next": "^8.3.8",
"react-tree-walker": "^4.3.0"
}
}
49 changes: 41 additions & 8 deletions src/hocs/app-with-translation.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React from 'react'
import Router from 'next/router'

import reactTreeWalker from 'react-tree-walker'

import { I18nextProvider } from 'react-i18next'
import { lngPathCorrector } from 'utils'
import { NextStaticProvider } from 'components'
Expand Down Expand Up @@ -53,25 +55,56 @@ export default function (WrappedComponent) {
let initialI18nStore = {}
let initialLanguage = null

// Load translations to serialize if we're serverside
// Step 1: Determine initial language
if (req && req.i18n) {

// First language in array is current lang
[initialLanguage] = req.i18n.languages

// Perform a lang change in case we're not on the right lang
await i18n.changeLanguage(initialLanguage)
req.i18n.languages.forEach((l) => {
initialI18nStore[l] = {}
i18n.nsFromReactTree.forEach((ns) => {
initialI18nStore[l][ns] = (req.i18n.services.resourceStore.data[l] || {})[ns] || {}
})

} else if (Array.isArray(i18n.languages) && i18n.languages.length > 0) {
initialLanguage = i18n.language
}

// Step 2: Determine namespace dependencies

// Create stripped-down version of incoming tree to
// walk and check props for NamespacesConsumer
const tree = (<I18nextProvider i18n={i18n}><Component {...this.props} /></I18nextProvider>)
let nsFromTree = []

// Walk tree and determine namespaces necessary to
// render this specific component tree
await reactTreeWalker(tree, (element, instance) => {
if (instance && instance.props && instance.props.ns) {
nsFromTree = [...new Set(nsFromTree.concat(instance.props.ns))]
}
})

// Step 3: Perform data fetching, depending on environment
if (req && req.i18n) {

// Initialise the store with only the initialLanguage and
// necessary namespaces needed to render this specific tree
initialI18nStore[initialLanguage] = {}
nsFromTree.forEach((ns) => {
initialI18nStore[initialLanguage][ns] = (
(req.i18n.services.resourceStore.data[initialLanguage] || {})[ns] || {}
)
})

} else if (Array.isArray(i18n.languages) && i18n.languages.length > 0) {

// Load newly-required translations if changing route clientside
await Promise.all(
i18n.nsFromReactTree
nsFromTree
.filter(ns => !i18n.hasResourceBundle(i18n.languages[0], ns))
.map(ns => new Promise(resolve => i18n.loadNamespaces(ns, () => resolve()))),
)
initialI18nStore = i18n.store.data
initialLanguage = i18n.language

}

// `pageProps` will get serialized automatically by NextJs
Expand Down
3 changes: 1 addition & 2 deletions src/hocs/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export { default as appWithTranslation } from './app-with-translation'
export { default as withNamespaces } from './with-namespaces'
export { default as appWithTranslation } from './app-with-translation' // eslint-disable-line import/prefer-default-export
6 changes: 0 additions & 6 deletions src/hocs/with-namespaces.js

This file was deleted.

5 changes: 3 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import createConfig from 'config/create-config'
import createI18NextClient from 'create-i18next-client'

import { appWithTranslation, withNamespaces } from 'hocs'
import { appWithTranslation } from 'hocs'
import { Link } from 'components'
import { withNamespaces } from 'react-i18next'

export default class NextI18Next {

constructor(userConfig) {
this.config = createConfig(userConfig)
this.i18n = createI18NextClient(this.config)
this.appWithTranslation = appWithTranslation.bind(this)
this.withNamespaces = withNamespaces.bind(this)
this.withNamespaces = withNamespaces

this.Link = Link.apply(this)
}
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3178,6 +3178,11 @@ react-is@^16.3.2:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.6.3.tgz#d2d7462fcfcbe6ec0da56ad69047e47e56e7eac0"
integrity sha512-u7FDWtthB4rWibG/+mFbVd5FvdI20yde86qKGx4lVUTWmPlSWQ4QxbBIrrs+HnXGbxOUlUzTAP/VDmvCwaP2yA==

react-tree-walker@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/react-tree-walker/-/react-tree-walker-4.3.0.tgz#b7cae498cebb490281e9e99a01bdb9c6b4926cd3"
integrity sha512-sO/pk+JQ2mbtPGdlKbeeo2aT4qXl5nPkGVO96yYQOdX9jYvRNXSnMWIydniLVEoiPvUbpfoc057blGbAQgMBRg==

react@^16.6.3:
version "16.6.3"
resolved "https://registry.yarnpkg.com/react/-/react-16.6.3.tgz#25d77c91911d6bbdd23db41e70fb094cc1e0871c"
Expand Down

0 comments on commit 2386bf2

Please sign in to comment.