Skip to content

Commit ce12818

Browse files
committed
Implemented translate provider, consumer and HOC
1 parent 4babc77 commit ce12818

File tree

4 files changed

+101
-0
lines changed

4 files changed

+101
-0
lines changed

src/Context.jsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import React from 'react';
2+
3+
export default React.createContext();

src/Provider.jsx

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import React, { Component } from 'react';
2+
import PropTypes from 'prop-types';
3+
import _get from 'lodash/get';
4+
import TrContext from './Context';
5+
6+
export default class Provider extends Component {
7+
static propTypes = {
8+
defaultLanguage: PropTypes.string.isRequired,
9+
dictionaries: PropTypes.shape().isRequired,
10+
children: PropTypes.node.isRequired,
11+
}
12+
13+
state = {
14+
language: null,
15+
}
16+
17+
componentDidMount() {
18+
const { dictionaries, defaultLanguage } = this.props;
19+
const dictionaryOpen = dictionaries[defaultLanguage];
20+
21+
if (dictionaryOpen) {
22+
dictionaryOpen().then((dictionary) => {
23+
this.setState({
24+
language: defaultLanguage,
25+
[defaultLanguage]: dictionary,
26+
});
27+
});
28+
}
29+
}
30+
31+
componentDidUpdate(prevProps, prevState) {
32+
const { language, ...readDictionaries } = this.state;
33+
34+
if (prevState.language !== language && !readDictionaries[language]) {
35+
const dictionaryOpen = this.props.dictionaries[language];
36+
37+
if (dictionaryOpen) {
38+
dictionaryOpen().then((dictionary) => {
39+
this.setState({
40+
language,
41+
[language]: dictionary,
42+
});
43+
});
44+
}
45+
}
46+
}
47+
48+
handleChangeLanguage = (language) => {
49+
const { dictionaries } = this.props;
50+
const nameDictionaries = Object.keys(dictionaries);
51+
52+
if (nameDictionaries.includes(language)) {
53+
this.setState({ language });
54+
}
55+
}
56+
57+
handleGetTranslate = (path, options) => {
58+
const { language, ...dictionaries } = this.state;
59+
const dictionary = dictionaries[language];
60+
61+
return _get(dictionary, path, '').replace(
62+
/{([^{}]+)}/g,
63+
(_, option) => options[option] || `{${option}}`,
64+
);
65+
}
66+
67+
render() {
68+
const { language, ...dictionaries } = this.state;
69+
const value = {
70+
dictionary: dictionaries[language] || {},
71+
getTranslate: this.handleGetTranslate,
72+
changeLanguage: this.handleChangeLanguage,
73+
};
74+
75+
return (
76+
<TrContext.Provider value={value}>
77+
{ this.props.children }
78+
</TrContext.Provider>
79+
);
80+
}
81+
}

src/index.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import TrContext from './Context';
2+
3+
export default TrContext;
4+
export { default as withTranslate } from './withTranslate';
5+
export { default as TrProvider } from './Provider';
6+
export const TrConsumer = TrContext.Consumer;

src/withTranslate.jsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import React from 'react';
2+
import TrContext from './Context';
3+
4+
export default function withTranslate(Component) {
5+
// eslint-disable-next-line react/display-name
6+
return props => (
7+
<TrContext.Consumer>
8+
{ tr => <Component tr={tr} { ...props } /> }
9+
</TrContext.Consumer>
10+
);
11+
}

0 commit comments

Comments
 (0)