diff --git a/.babelrc b/.babelrc
index 194df44f1..97242d46f 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,5 +1,6 @@
{
"plugins": [
+ "syntax-dynamic-import",
"transform-object-rest-spread",
["react-intl", {
"messagesDir": "./translations/messages/"
diff --git a/package.json b/package.json
index 7739f1afa..bb5cd437a 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,7 @@
"i18n:msgs": "./scripts/generate-locale-messages.js",
"i18n:src": "babel src > tmp.js && rimraf tmp.js && ./scripts/build-i18n-source.js ./translations/messages/ ./translations/",
"lint": "eslint . --ext .js,.jsx",
- "start": "webpack-dev-server",
+ "start": "npm run i18n:msgs && webpack-dev-server",
"test": "npm run lint && npm run build",
"watch": "webpack --progress --colors --watch"
},
@@ -32,6 +32,7 @@
"babel-eslint": "^7.1.1",
"babel-loader": "^7.0.0",
"babel-plugin-react-intl": "2.3.1",
+ "babel-plugin-syntax-dynamic-import": "6.18.0",
"babel-plugin-transform-object-rest-spread": "^6.22.0",
"babel-preset-es2015": "^6.22.0",
"babel-preset-react": "^6.22.0",
diff --git a/scripts/generate-locale-messages.js b/scripts/generate-locale-messages.js
index 1199b0dc5..6534d25e2 100755
--- a/scripts/generate-locale-messages.js
+++ b/scripts/generate-locale-messages.js
@@ -16,7 +16,7 @@ Translation files are in Chrome i18n json format:
'''
They are named by locale, for example: 'fr.json' or 'zh-cn.json'
-Current languages supported are listed in ../languages.json
+Current languages supported are listed in ../src/languages.json
Converts the collection of translation files to a single set of messages.
Example output:
@@ -42,7 +42,7 @@ Missing locales are ignored, react-intl will use the default messages for them.
const fs = require('fs');
const path = require('path');
const mkdirp = require('mkdirp');
-const languages = require('../languages.json');
+const languages = require('../src/languages.json');
const LANG_DIR = './translations/';
const MSGS_DIR = './locale/';
diff --git a/src/components/language-selector/language-icon.svg b/src/components/language-selector/language-icon.svg
new file mode 100644
index 000000000..3644ab6fd
--- /dev/null
+++ b/src/components/language-selector/language-icon.svg
@@ -0,0 +1,72 @@
+
+
+
diff --git a/src/components/language-selector/language-selector.css b/src/components/language-selector/language-selector.css
new file mode 100644
index 000000000..f5879335e
--- /dev/null
+++ b/src/components/language-selector/language-selector.css
@@ -0,0 +1,23 @@
+@import "../../css/units.css";
+
+.group {
+ display: inline-flex;
+ flex-direction: row; /* makes columns, for each label/form group */
+ align-items: center;
+ vertical-align: middle;
+}
+
+.language-icon {
+ height: 2rem;
+}
+
+.language-select {
+ width: 100%;
+ height: 1.85rem;
+ border: 1px solid #4c97ff;
+ user-select: none;
+ outline: none;
+ background: rgba(255, 255, 255, 0.2);
+ color: white;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
diff --git a/src/components/language-selector/language-selector.jsx b/src/components/language-selector/language-selector.jsx
new file mode 100644
index 000000000..6c6ffd829
--- /dev/null
+++ b/src/components/language-selector/language-selector.jsx
@@ -0,0 +1,44 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+
+import Box from '../box/box.jsx';
+import languages from '../../languages.json';
+import languageIcon from './language-icon.svg';
+import styles from './language-selector.css';
+
+const LanguageSelector = ({
+ currentLocale,
+ onChange,
+ ...props
+}) => (
+
+
+

+
+
+
+);
+
+
+LanguageSelector.propTypes = {
+ currentLocale: PropTypes.string,
+ onChange: PropTypes.func
+};
+
+module.exports = LanguageSelector;
diff --git a/src/components/menu-bar/menu-bar.jsx b/src/components/menu-bar/menu-bar.jsx
index c22ba3636..35ced7049 100644
--- a/src/components/menu-bar/menu-bar.jsx
+++ b/src/components/menu-bar/menu-bar.jsx
@@ -4,6 +4,7 @@ import React from 'react';
import Box from '../box/box.jsx';
import LoadButton from '../../containers/load-button.jsx';
import SaveButton from '../../containers/save-button.jsx';
+import LanguageSelector from '../../containers/language-selector.jsx';
import styles from './menu-bar.css';
import scratchLogo from './scratch-logo.svg';
@@ -23,6 +24,7 @@ const MenuBar = function MenuBar () {
+
);
};
diff --git a/src/containers/language-selector.jsx b/src/containers/language-selector.jsx
new file mode 100644
index 000000000..9412b0c53
--- /dev/null
+++ b/src/containers/language-selector.jsx
@@ -0,0 +1,20 @@
+import {connect} from 'react-redux';
+import {updateIntl} from '../reducers/intl.js';
+
+import LanguageSelectorComponent from '../components/language-selector/language-selector.jsx';
+
+const mapStateToProps = state => ({
+ currentLocale: state.intl.locale
+});
+
+const mapDispatchToProps = dispatch => ({
+ onChange: e => {
+ e.preventDefault();
+ dispatch(updateIntl(e.target.value));
+ }
+});
+
+module.exports = connect(
+ mapStateToProps,
+ mapDispatchToProps
+)(LanguageSelectorComponent);
diff --git a/src/index.jsx b/src/index.jsx
index 48f4a12da..35c761085 100644
--- a/src/index.jsx
+++ b/src/index.jsx
@@ -1,9 +1,9 @@
import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';
-import {createStore, applyMiddleware} from 'redux';
+import {createStore, applyMiddleware, compose} from 'redux';
import throttle from 'redux-throttle';
-import {intlInitialState, IntlProvider} from './lib/intl.jsx';
+import {intlInitialState, IntlProvider} from './reducers/intl.js';
import GUI from './containers/gui.jsx';
import log from './lib/log';
@@ -61,16 +61,14 @@ class App extends React.Component {
const appTarget = document.createElement('div');
appTarget.className = styles.app;
document.body.appendChild(appTarget);
-const store = applyMiddleware(
- throttle(300, {leading: true, trailing: true})
-)(createStore)(
- reducer,
- Object.assign(
- {},
- window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
- intlInitialState
+
+const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
+const enhancer = composeEnhancers(
+ applyMiddleware(
+ throttle(300, {leading: true, trailing: true})
)
);
+const store = createStore(reducer, intlInitialState, enhancer);
ReactDOM.render((
diff --git a/languages.json b/src/languages.json
similarity index 100%
rename from languages.json
rename to src/languages.json
diff --git a/src/lib/intl.jsx b/src/lib/intl.jsx
deleted file mode 100644
index 2c39f2ce3..000000000
--- a/src/lib/intl.jsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import {addLocaleData} from 'react-intl';
-import languages from '../../languages.json';
-import messages from '../../locale/messages.json';
-
-export {IntlProvider, intlReducer} from 'react-intl-redux';
-
-Object.keys(languages).forEach(locale => {
- // TODO: will need to handle locales not in the default intl - see www/custom-locales
- const data = require(`react-intl/locale-data/${locale}`);
- addLocaleData(data);
-});
-
-export const intlInitialState = {
- intl: {
- defaultLocale: 'en',
- locale: 'en',
- messages: messages.en
- }
-};
diff --git a/src/reducers/intl.js b/src/reducers/intl.js
index 12c4b35b5..14fa64ef5 100644
--- a/src/reducers/intl.js
+++ b/src/reducers/intl.js
@@ -1,5 +1,25 @@
+import {addLocaleData} from 'react-intl';
import {updateIntl as superUpdateIntl} from 'react-intl-redux';
-import {messages} from '../../locale/messages.json';
+import languages from '../languages.json';
+import messages from '../../locale/messages.json';
+import {IntlProvider, intlReducer} from 'react-intl-redux';
-export {intlReducer as default} from 'react-intl-redux';
-export const updateIntl = locale => superUpdateIntl(locale, messages[locale] || messages.en);
+Object.keys(languages).forEach(locale => {
+ // TODO: will need to handle locales not in the default intl - see www/custom-locales
+ import(`react-intl/locale-data/${locale}`).then(data => addLocaleData(data));
+});
+
+const intlInitialState = {
+ intl: {
+ defaultLocale: 'en',
+ locale: 'en',
+ messages: messages.en
+ }
+};
+
+const updateIntl = locale => superUpdateIntl({
+ locale: locale,
+ messages: messages[locale] || messages.en
+});
+
+export {intlReducer as default, IntlProvider, intlInitialState, updateIntl};
diff --git a/webpack.config.js b/webpack.config.js
index afb092497..44595ff2c 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -33,15 +33,7 @@ module.exports = {
rules: [{
test: /\.jsx?$/,
loader: 'babel-loader',
- include: path.resolve(__dirname, 'src'),
- options: {
- plugins: [
- 'transform-object-rest-spread',
- ['react-intl', {
- messagesDir: './translations/messages/'
- }]],
- presets: ['es2015', 'react']
- }
+ include: path.resolve(__dirname, 'src')
},
{
test: /\.css$/,