Skip to content

Commit 92d51a5

Browse files
authored
Merge pull request #3431 from chrisgarrity/issue/www2172-integrate-intl
Refactor IntlProvider in GUI to support integration with www
2 parents 8548051 + 2b28d0f commit 92d51a5

File tree

5 files changed

+71
-33
lines changed

5 files changed

+71
-33
lines changed

src/containers/gui.jsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {compose} from 'redux';
44
import {connect} from 'react-redux';
55
import ReactModal from 'react-modal';
66
import VM from 'scratch-vm';
7-
import {injectIntl, intlShape} from 'react-intl';
7+
import {defineMessages, injectIntl, intlShape} from 'react-intl';
88

99
import ErrorBoundaryHOC from '../lib/error-boundary-hoc.jsx';
1010
import {openExtensionLibrary} from '../reducers/modals';
@@ -25,14 +25,22 @@ import {
2525
} from '../reducers/modals';
2626

2727
import FontLoaderHOC from '../lib/font-loader-hoc.jsx';
28+
import LocalizationHOC from '../lib/localization-hoc.jsx';
2829
import ProjectFetcherHOC from '../lib/project-fetcher-hoc.jsx';
2930
import ProjectSaverHOC from '../lib/project-saver-hoc.jsx';
3031
import vmListenerHOC from '../lib/vm-listener-hoc.jsx';
3132
import vmManagerHOC from '../lib/vm-manager-hoc.jsx';
32-
import {defaultProjectTitleMessages} from '../reducers/project-title';
3333

3434
import GUIComponent from '../components/gui/gui.jsx';
3535

36+
const messages = defineMessages({
37+
defaultProjectTitle: {
38+
id: 'gui.gui.defaultProjectTitle',
39+
description: 'Default title for project',
40+
defaultMessage: 'Scratch Project'
41+
}
42+
});
43+
3644
class GUI extends React.Component {
3745
componentDidMount () {
3846
this.setReduxTitle(this.props.projectTitle);
@@ -48,7 +56,7 @@ class GUI extends React.Component {
4856
setReduxTitle (newTitle) {
4957
if (newTitle === null || typeof newTitle === 'undefined') {
5058
this.props.onUpdateReduxProjectTitle(
51-
this.props.intl.formatMessage(defaultProjectTitleMessages.defaultProjectTitle)
59+
this.props.intl.formatMessage(messages.defaultProjectTitle)
5260
);
5361
} else {
5462
this.props.onUpdateReduxProjectTitle(newTitle);
@@ -163,6 +171,7 @@ const ConnectedGUI = injectIntl(connect(
163171
// the hierarchy of HOC constructor calls clearer here; it has nothing to do with redux's
164172
// ability to compose reducers.
165173
const WrappedGui = compose(
174+
LocalizationHOC,
166175
ErrorBoundaryHOC('Top Level App'),
167176
FontLoaderHOC,
168177
ProjectFetcherHOC,

src/lib/app-state-hoc.jsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import React from 'react';
22
import PropTypes from 'prop-types';
33
import {Provider} from 'react-redux';
44
import {createStore, combineReducers, compose} from 'redux';
5-
import ConnectedIntlProvider from './connected-intl-provider.jsx';
65

76
import localesReducer, {initLocale, localesInitialState} from '../reducers/locales';
87

@@ -108,9 +107,7 @@ const AppStateHOC = function (WrappedComponent, localesOnly) {
108107
} = this.props;
109108
return (
110109
<Provider store={this.store}>
111-
<ConnectedIntlProvider>
112-
<WrappedComponent {...componentProps} />
113-
</ConnectedIntlProvider>
110+
<WrappedComponent {...componentProps} />
114111
</Provider>
115112
);
116113
}

src/lib/localization-hoc.jsx

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import {connect} from 'react-redux';
4+
5+
import ConnectedIntlProvider from './connected-intl-provider.jsx';
6+
7+
/*
8+
* Higher Order Component to provide localiztion state. Creates a nested IntlProvider
9+
* to handle Gui intl context. The component accepts an onSetLanguage callback that is
10+
* called when the locale chagnes.
11+
* @param {React.Component} WrappedComponent - component to provide state for
12+
* @returns {React.Component} component with intl state provided from redux
13+
*/
14+
const LocalizationHOC = function (WrappedComponent) {
15+
class LocalizationWrapper extends React.Component {
16+
componentDidUpdate (prevProps) {
17+
if (prevProps.locale !== this.props.locale) {
18+
this.props.onSetLanguage(this.props.locale);
19+
}
20+
}
21+
render () {
22+
const {
23+
locale, // eslint-disable-line no-unused-vars
24+
onSetLanguage, // eslint-disable-line no-unused-vars
25+
...componentProps
26+
} = this.props;
27+
return (
28+
<ConnectedIntlProvider>
29+
<WrappedComponent {...componentProps} />
30+
</ConnectedIntlProvider>
31+
);
32+
}
33+
}
34+
LocalizationWrapper.propTypes = {
35+
locale: PropTypes.string,
36+
onSetLanguage: PropTypes.func
37+
};
38+
39+
LocalizationWrapper.defaultProps = {
40+
onSetLanguage: () => {}
41+
};
42+
43+
const mapStateToProps = state => ({
44+
locale: state.locales.locale
45+
});
46+
47+
const mapDispatchToProps = () => ({});
48+
49+
return connect(
50+
mapStateToProps,
51+
mapDispatchToProps
52+
)(LocalizationWrapper);
53+
};
54+
55+
export default LocalizationHOC;

src/lib/titled-hoc.jsx

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import React from 'react';
22
import bindAll from 'lodash.bindall';
3-
import {intlShape, injectIntl} from 'react-intl';
4-
import {defaultProjectTitleMessages} from '../reducers/project-title';
53

64
/* Higher Order Component to get and set the project title
75
* @param {React.Component} WrappedComponent component to receive project title related props
@@ -15,34 +13,24 @@ const TitledHOC = function (WrappedComponent) {
1513
'handleUpdateProjectTitle'
1614
]);
1715
this.state = {
18-
projectTitle: this.props.intl.formatMessage(defaultProjectTitleMessages.defaultProjectTitle)
16+
projectTitle: null
1917
};
2018
}
2119
handleUpdateProjectTitle (newTitle) {
2220
this.setState({projectTitle: newTitle});
2321
}
2422
render () {
25-
const {
26-
/* eslint-disable no-unused-vars */
27-
intl,
28-
/* eslint-enable no-unused-vars */
29-
...componentProps
30-
} = this.props;
3123
return (
3224
<WrappedComponent
3325
projectTitle={this.state.projectTitle}
3426
onUpdateProjectTitle={this.handleUpdateProjectTitle}
35-
{...componentProps}
27+
{...this.props}
3628
/>
3729
);
3830
}
3931
}
4032

41-
TitledComponent.propTypes = {
42-
intl: intlShape.isRequired
43-
};
44-
45-
return injectIntl(TitledComponent);
33+
return TitledComponent;
4634
};
4735

4836
export {

src/reducers/project-title.js

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,9 @@
1-
import {defineMessages} from 'react-intl';
2-
31
const SET_PROJECT_TITLE = 'projectTitle/SET_PROJECT_TITLE';
42

53
// we are initializing to a blank string instead of an actual title,
64
// because it would be hard to localize here
75
const initialState = '';
86

9-
const defaultProjectTitleMessages = defineMessages({
10-
defaultProjectTitle: {
11-
id: 'gui.gui.defaultProjectTitle',
12-
description: 'Default title for project',
13-
defaultMessage: 'Scratch Project'
14-
}
15-
});
16-
177
const reducer = function (state, action) {
188
if (typeof state === 'undefined') state = initialState;
199
switch (action.type) {
@@ -31,6 +21,5 @@ const setProjectTitle = title => ({
3121
export {
3222
reducer as default,
3323
initialState as projectTitleInitialState,
34-
defaultProjectTitleMessages,
3524
setProjectTitle
3625
};

0 commit comments

Comments
 (0)