Skip to content

Commit

Permalink
Merge pull request #523 from nicolasschabram/feature/520_dynamicNsPro…
Browse files Browse the repository at this point in the history
…pOnI18nComponent

Load missing namespaces when updating ns prop on I18n component
  • Loading branch information
jamuhl committed Sep 25, 2018
2 parents 59c2608 + 154b206 commit c4f8806
Showing 1 changed file with 43 additions and 30 deletions.
73 changes: 43 additions & 30 deletions src/I18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ export default class I18n extends Component {
super(props, context);

this.i18n = props.i18n || context.i18n || getI18n();
this.namespaces = props.ns || (this.i18n.options && this.i18n.options.defaultNS);
if (typeof this.namespaces === 'string') this.namespaces = [this.namespaces];

const i18nOptions = (this.i18n && this.i18n.options && this.i18n.options.react) || {};
this.options = { ...getDefaults(), ...i18nOptions, ...props };
Expand All @@ -30,7 +28,7 @@ export default class I18n extends Component {
}

const language = this.i18n.languages && this.i18n.languages[0];
const ready = !!language && this.namespaces.every(ns => this.i18n.hasResourceBundle(language, ns));
const ready = !!language && this.getNamespaces().every(ns => this.i18n.hasResourceBundle(language, ns));

this.state = {
i18nLoadedAt: null,
Expand All @@ -41,6 +39,7 @@ export default class I18n extends Component {

this.onI18nChanged = this.onI18nChanged.bind(this);
this.getI18nTranslate = this.getI18nTranslate.bind(this);
this.namespaces = this.getNamespaces.bind(this);
}

getChildContext() {
Expand All @@ -51,13 +50,53 @@ export default class I18n extends Component {
}

componentDidMount() {
this.loadNamespaces();
}

componentDidUpdate(prevProps) {
// Note that dynamically loading additional namespaces after the initial mount will not block rendering – even if the `wait` option is true.
if (this.props.ns && prevProps.ns !== this.props.ns) this.loadNamespaces();
}

componentWillUnmount() {
this.mounted = false;
if (this.onI18nChanged) {
if (this.options.bindI18n) {
const p = this.options.bindI18n.split(' ');
p.forEach(f => this.i18n.off(f, this.onI18nChanged));
}
if (this.options.bindStore) {
const p = this.options.bindStore.split(' ');
p.forEach(f => this.i18n.store && this.i18n.store.off(f, this.onI18nChanged));
}
}
}

onI18nChanged() {
if (!this.mounted) return;
if (!this.state.ready && this.options.omitBoundRerender) return;

this.t = this.getI18nTranslate();
this.setState({ i18nLoadedAt: new Date() }); // rerender
}

getI18nTranslate() {
return this.i18n.getFixedT(null, this.options.nsMode === 'fallback' ? this.getNamespaces() : this.getNamespaces()[0]);
}

getNamespaces() {
const ns = this.props.ns || (this.i18n.options && this.i18n.options.defaultNS);
return typeof ns === 'string' ? [ns] : ns;
}

loadNamespaces() {
const bind = () => {
if (this.options.bindI18n && this.i18n) this.i18n.on(this.options.bindI18n, this.onI18nChanged);
if (this.options.bindStore && this.i18n.store) this.i18n.store.on(this.options.bindStore, this.onI18nChanged);
};

this.mounted = true;
this.i18n.loadNamespaces(this.namespaces, () => {
this.i18n.loadNamespaces(this.getNamespaces(), () => {
const ready = () => {
if (this.mounted && !this.state.ready) this.setState({ ready: true });
if (this.options.wait && this.mounted) bind();
Expand All @@ -81,32 +120,6 @@ export default class I18n extends Component {
if (!this.options.wait) bind();
}

componentWillUnmount() {
this.mounted = false;
if (this.onI18nChanged) {
if (this.options.bindI18n) {
const p = this.options.bindI18n.split(' ');
p.forEach(f => this.i18n.off(f, this.onI18nChanged));
}
if (this.options.bindStore) {
const p = this.options.bindStore.split(' ');
p.forEach(f => this.i18n.store && this.i18n.store.off(f, this.onI18nChanged));
}
}
}

onI18nChanged() {
if (!this.mounted) return;
if (!this.state.ready && this.options.omitBoundRerender) return;

this.t = this.getI18nTranslate();
this.setState({ i18nLoadedAt: new Date() }); // rerender
}

getI18nTranslate() {
return this.i18n.getFixedT(null, this.options.nsMode === 'fallback' ? this.namespaces : this.namespaces[0]);
}

render() {
const { children } = this.props;
const { ready } = this.state;
Expand Down

0 comments on commit c4f8806

Please sign in to comment.