Skip to content

Commit

Permalink
adds wait flag
Browse files Browse the repository at this point in the history
  • Loading branch information
jamuhl committed Jun 13, 2016
1 parent 50ca7e8 commit ca0e7c2
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 80 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,6 @@
### 1.5.0
- adds wait option, which delays initial rendering until translations are loaded

### 1.4.2
- possible fix for HRM issues

Expand Down
33 changes: 28 additions & 5 deletions README.md
Expand Up @@ -73,22 +73,45 @@ export default translate(['defaultNamespace', 'anotherNamespace'])(TranslatableV

```

__getWrappedInstance()__: allows you to access to the component instance, wrapped into `translate()`.
You can set options.wait to true if you want to delay rendering until translation files are loaded:

```javascript
import React from 'react';
import { translate } from 'react-i18next';

function TranslatableView(props) {
const { t } = props;

return (
<div>
<h1>{t('keyFromDefault')}</h1>
<p>{t('anotherNamespace:key.from.another.namespace', { /* options t options */ })}</p>
</div>
)
}

export default translate(['defaultNamespace', 'anotherNamespace'], { wait: true })(TranslatableView);

```



__getWrappedInstance()__: allows you to access to the component instance, wrapped into `translate()`.
Only available if you pass `{ withRef: true }` to the `translate()` options.

```javascript
import React, { Component } from 'react';
import { translate } from 'react-i18next';

class TranslatableView extends Component {

foo() {
// do something important
}

render() {
const { t } = this.props;

return (
<div>
<h1>{t('keyFromDefault')}</h1>
Expand Down Expand Up @@ -198,7 +221,7 @@ app.use((req, res) => {
<App />
</I18nextProvider>
);

// render as desired now ...
});
```
Expand Down
2 changes: 1 addition & 1 deletion example/app/components/AnotherComponent.js
Expand Up @@ -5,4 +5,4 @@ function Component({t}) {
return <p>{t('content.text', { /* options t options */ })}</p>
}

export default translate('view')(Component);
export default translate('view', { wait: true })(Component);
2 changes: 1 addition & 1 deletion example/app/components/View.js
Expand Up @@ -4,7 +4,7 @@ import AnotherComponent from './AnotherComponent';
import YetAnotherComponent from './YetAnotherComponent';


@translate(['view', 'nav'])
@translate(['view', 'nav'], { wait: true })
class TranslatableView extends React.Component {
render() {
const { t } = this.props;
Expand Down
31 changes: 18 additions & 13 deletions react-i18next.js
Expand Up @@ -123,6 +123,8 @@
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
var _options$withRef = options.withRef;
var withRef = _options$withRef === undefined ? false : _options$withRef;
var _options$wait = options.wait;
var wait = _options$wait === undefined ? false : _options$wait;


return function Wrapper(WrappedComponent) {
Expand All @@ -140,8 +142,11 @@
namespaces = namespaces || i18n.options.defaultNS;

_this.state = {
i18nLoadedAt: null
i18nLoadedAt: null,
ready: false
};

_this.onI18nChanged = _this.onI18nChanged.bind(_this);
return _this;
}

Expand All @@ -153,21 +158,17 @@
}, {
key: 'componentWillMount',
value: function componentWillMount() {
var _this2 = this;

this.mounted = true;
i18n.loadNamespaces(namespaces);
i18n.loadNamespaces(namespaces, function () {
_this2.setState({ ready: true });
});
this.t = i18n.getFixedT(null, namespaces);
}
}, {
key: 'componentDidMount',
value: function componentDidMount() {
var _this2 = this;

this.onI18nChanged = function () {
if (!_this2.mounted) return;

_this2.setState({ i18nLoadedAt: new Date() });
};

i18n.on('languageChanged loaded', this.onI18nChanged);
}
}, {
Expand All @@ -180,8 +181,8 @@
}
}
}, {
key: 'onI18nChange',
value: function onI18nChange() {
key: 'onI18nChanged',
value: function onI18nChanged() {
if (!this.mounted) return;

this.setState({ i18nLoadedAt: new Date() });
Expand All @@ -199,14 +200,18 @@
}, {
key: 'render',
value: function render() {
var i18nLoadedAt = this.state.i18nLoadedAt;
var _state = this.state;
var i18nLoadedAt = _state.i18nLoadedAt;
var ready = _state.ready;

var extraProps = { i18nLoadedAt: i18nLoadedAt, t: this.t };

if (withRef) {
extraProps.ref = 'wrappedInstance';
}

if (!ready && wait) return null;

return React__default.createElement(WrappedComponent, babelHelpers.extends({}, this.props, extraProps));
}
}]);
Expand Down
2 changes: 1 addition & 1 deletion react-i18next.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

119 changes: 60 additions & 59 deletions src/translate.js
Expand Up @@ -5,81 +5,82 @@ function getDisplayName(component) {
}

export default function translate(namespaces, options = {}) {
const { withRef = false } = options;
const { withRef = false, wait = false } = options;

return function Wrapper(WrappedComponent) {
let i18n;

class Translate extends Component {
constructor(props, context) {
super(props, context);
i18n = context.i18n;
namespaces = namespaces || i18n.options.defaultNS;

this.state = {
i18nLoadedAt: null
};
constructor(props, context) {
super(props, context);
i18n = context.i18n;
namespaces = namespaces || i18n.options.defaultNS;

this.state = {
i18nLoadedAt: null,
ready: false
};

this.onI18nChanged = this.onI18nChanged.bind(this);
}

getChildContext() {
return { t: this.t };
}

componentWillMount() {
this.mounted = true;
i18n.loadNamespaces(namespaces, () => {
this.setState({ ready: true });
});
this.t = i18n.getFixedT(null, namespaces);
}

componentDidMount() {
i18n.on('languageChanged loaded', this.onI18nChanged);
}

componentWillUnmount() {
this.mounted = false;
if (this.onI18nChanged) {
i18n.off('languageChanged', this.onI18nChanged);
i18n.off('loaded', this.onI18nChanged);
}
}

getChildContext() {
return { t: this.t };
}

componentWillMount() {
this.mounted = true;
i18n.loadNamespaces(namespaces);
this.t = i18n.getFixedT(null, namespaces);
}
onI18nChanged() {
if (!this.mounted) return;

componentDidMount() {
this.onI18nChanged = () => {
if (!this.mounted) return;

this.setState({ i18nLoadedAt: new Date() });
};

i18n.on('languageChanged loaded', this.onI18nChanged);
}
this.setState({ i18nLoadedAt: new Date() });
}

componentWillUnmount() {
this.mounted = false;
if (this.onI18nChanged) {
i18n.off('languageChanged', this.onI18nChanged);
i18n.off('loaded', this.onI18nChanged);
}
getWrappedInstance() {
if (!withRef) {
// eslint-disable-next-line no-console
console.error(
'To access the wrapped instance, you need to specify ' +
'{ withRef: true } as the second argument of the translate() call.'
);
}

onI18nChange() {
if (!this.mounted) return;

this.setState({ i18nLoadedAt: new Date() });
}
return this.refs.wrappedInstance;
}

getWrappedInstance() {
if (!withRef) {
// eslint-disable-next-line no-console
console.error(
'To access the wrapped instance, you need to specify ' +
'{ withRef: true } as the second argument of the translate() call.'
);
}
render() {
const { i18nLoadedAt, ready } = this.state;
const extraProps = { i18nLoadedAt, t: this.t };

return this.refs.wrappedInstance;
if (withRef) {
extraProps.ref = 'wrappedInstance';
}

render() {
const { i18nLoadedAt } = this.state;
const extraProps = { i18nLoadedAt, t: this.t };
if (!ready && wait) return null;

if (withRef) {
extraProps.ref = 'wrappedInstance';
}

return React.createElement(
WrappedComponent,
{ ...this.props, ...extraProps }
);
}
return React.createElement(
WrappedComponent,
{ ...this.props, ...extraProps }
);
}
}

Translate.WrappedComponent = WrappedComponent;
Expand Down

0 comments on commit ca0e7c2

Please sign in to comment.