internationalization suppport

This commit is contained in:
Sérgio Ramos 2016-10-20 20:42:39 +01:00
parent e88864e201
commit 06f7b29fc3
21 changed files with 403 additions and 25 deletions

View File

@ -12,6 +12,9 @@
},
"dependencies": {
"express": "^4.14.0",
"locale": "^0.1.0",
"lodash.template": "^4.4.0",
"lodash.uniq": "^4.5.0",
"st": "^1.2.0"
},
"devDependencies": {

12
backend/src/index.html Normal file
View File

@ -0,0 +1,12 @@
<!doctype html>
<html lang='en-US'>
<head>
<title>Joyent Triton Dashboard</title>
</head>
<body>
<div id='root'></div>
<script src='/static/locales/<%= lang %>.js'></script>
<script src='/static/locales/<%= locale %>.js'></script>
<script src='/static/bundle.js'></script>
</body>
</html>

View File

@ -1,13 +1,19 @@
const template = require('lodash.template');
const locale = require('locale');
const path = require('path');
const express = require('express');
const st = require('st');
const fs = require('fs');
const app = express();
const index = path.join(__dirname, './index.html');
const html = template(fs.readFileSync(index, 'utf-8'));
var mount = st({
path: path.join(__dirname, '../static'),
url: 'static/',
index: 'index.html',
index: false,
dot: false,
passthrough: false,
gzip: true,
@ -15,11 +21,18 @@ var mount = st({
});
app.use(mount);
app.use(locale(require('./locales')));
app.get('/*', (req, res, next) => {
mount(Object.assign(req, {
sturl: '/static/index.html'
}), res, next);
const locale = (req.locale || '').toLowerCase();
const lang = locale.split(/\-/)[0];
res.header('Content-Type', 'text/html');
res.send(html({
locale,
lang
}));
});
app.listen(8000, (err, address) => {

11
backend/src/locales.js Normal file
View File

@ -0,0 +1,11 @@
const uniq = require('lodash.uniq');
const fs = require('fs');
const path = require('path');
const files = fs.readdirSync(path.join(__dirname, '../static/locales'));
module.exports = uniq(files.map((file) => {
return file.replace(/\.js$/, '');
}).filter((file) => {
return file.match(/.*?-.*?/);
}));

2
backend/static/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

View File

@ -26,6 +26,8 @@ npm run test
│   ├── store.js
│   └── thunks
├── static
├── locales
├── scripts
├── test
├── webpack
├── .babelrc
@ -38,6 +40,8 @@ npm run test
- **src/state/actions.js**: Not only exports all the actions available (declared in the file), but also goes through all the thunks and exports them.
- **src/state/thunks**: Directory to place thunks so that actions or reducers don't get too confusing.
- **src/state/reducers**: Each file here represents a reducer scope. So, `state.app` will be controlled in `reducers/app.js`.
- **locales**: Translation definitions for each locale supported.
- **scripts**: Utility scripts (e.g. building localizations).
- **test**: Self explanatory.
- **webpack**: Webpack configuration for multiple enviroments. Development configuration includes a dev-server and hot module replacement support.
- **.babelrc**: This babel configuration outputs ES2015 code, so it will produce code only for modern browsers.

View File

@ -0,0 +1,3 @@
{
"greetings": "Hello"
}

View File

@ -0,0 +1,3 @@
{
"greetings": "Olá"
}

View File

@ -8,9 +8,11 @@
"lint": "eslint .",
"test": "NODE_ENV=test nyc ava test/*.js --verbose",
"open": "nyc report --reporter=html & open coverage/index.html",
"coverage": "nyc check-coverage --statements 100 --functions 100 --lines 100 --branches 100"
"coverage": "nyc check-coverage --statements 100 --functions 100 --lines 100 --branches 100",
"build-locales": "NODE_ENV=test babel-node scripts/build-locales"
},
"dependencies": {
"babel-cli": "^6.16.0",
"babel-core": "^6.17.0",
"babel-loader": "^6.2.5",
"babel-plugin-add-module-exports": "^0.2.1",
@ -21,9 +23,13 @@
"constant-case": "^2.0.0",
"fast-async": "^6.1.1",
"json-loader": "^0.5.4",
"ncp": "^2.0.0",
"querystring": "^0.2.0",
"react": "^15.3.2",
"react-dom": "^15.3.2",
"react-hot-loader": "^3.0.0-beta.6",
"react-intl": "^2.1.5",
"react-intl-redux": "^0.1.0",
"react-redux": "^4.4.5",
"react-router": "^4.0.0-alpha.4",
"reduce-reducers": "^0.1.2",
@ -33,7 +39,9 @@
"redux-logger": "^2.7.0",
"redux-promise-middleware": "^4.1.0",
"redux-thunk": "^2.1.0",
"webpack": "^2.1.0-beta.25"
"thenify": "^3.2.1",
"webpack": "^2.1.0-beta.25",
"webpack-shell-plugin": "^0.4.3"
},
"devDependencies": {
"ava": "^0.16.0",
@ -52,7 +60,8 @@
"nyc": "^8.3.1",
"pre-commit": "^1.1.3",
"react-addons-test-utils": "^15.3.2",
"webpack-dev-server": "^1.16.2"
"webpack-dev-server": "^1.16.2",
"webpack-shell-plugin": "^0.4.3"
},
"ava": {
"failFast": true,

View File

@ -0,0 +1,74 @@
const path = require('path');
const thenify = require('thenify');
const fs = require('fs');
const Ncp = require('ncp');
const readdir = thenify(fs.readdir);
const writeFile = thenify(fs.writeFile);
const readFile = thenify(fs.readFile);
const ncp = thenify(Ncp.ncp);
const root = path.join(__dirname, '../locales');
const sttic = path.join(__dirname, '../static/locales');
const intl = path.join(__dirname, '../node_modules/react-intl/locale-data');
const source = ({
name,
json
}) => `
(() => {
const Locales = window.Locales || {};
Locales['${name}'] = ${json};
window.Locales = Locales;
})();
`;
const compile = async () => {
const files = await readdir(root);
const jsons = files.filter(filename => path.extname(filename) === '.json');
const locales = files.reduce((res, filename) => {
const name = path.parse(filename).name;
const json = JSON.stringify(require(path.join(root, filename)));
const lang = name.split(/\-/)[0];
return {
...res,
[name]: {
lang,
json,
filename
}
};
}, {});
await Promise.all(Object.keys(locales).map((name) => {
console.log(`Copying locale-data for ${name}`);
const locale = locales[name];
const source = path.join(intl, `${locale.lang}.js`);
const destination = path.join(sttic, `${locale.lang}.js`);
return ncp(source, destination);
}));
return await Promise.all(Object.keys(locales).map((name) => {
console.log(`Writing ${name}.js`);
const locale = locales[name];
return writeFile(path.join(sttic, `${name}.js`), source({
...locale,
name
}));
}));
};
console.log('Building Locales');
compile().then(() => {
console.log('Locales Built');
}, (err) => {
throw err;
});

View File

@ -28,6 +28,7 @@ const App = connect()(React.createClass({
// ugly hack needed because of a limitation of react-router api
// that doens't pass it's instance to matched routes
// wait for react-router-redux@5
dispatch(updateRouter(router));
},
render: function() {

View File

@ -1,9 +1,16 @@
const React = require('react');
const ReactIntl = require('react-intl');
const {
FormattedMessage
} = ReactIntl;
module.exports = () => {
return (
<div>
<h1>Home</h1>
<h1>
<FormattedMessage id='greetings' />
</h1>
</div>
);
};

38
frontend/src/intl.js Normal file
View File

@ -0,0 +1,38 @@
const qs = require('querystring');
const ReactIntl = require('react-intl');
const {
addLocaleData
} = ReactIntl;
module.exports = (({
Locales = {},
ReactIntlLocaleData = {}
}) => {
const en = Locales['en-us'] || {};
Object.keys(ReactIntlLocaleData).forEach((lang) => {
addLocaleData(ReactIntlLocaleData[lang] || []);
});
// http://stackoverflow.com/a/38150585
const detectedLocale = (
qs.parse((document.location.search || '').replace(/^\?/, '')).locale ||
navigator.languages && navigator.languages[0] || // Chrome / Firefox
navigator.language || // All browsers
navigator.userLanguage || // IE <= 10
'en-US'
).toLowerCase();
const lang = detectedLocale.split(/\-/)[0];
const locale = ReactIntlLocaleData[lang] ?
(Locales[detectedLocale] ? detectedLocale : 'en-us') : 'en-us';
return {
locale,
messages: {
...en,
...(Locales[locale] || {})
}
};
})(window);

View File

@ -1,4 +1,6 @@
const qs = require('querystring');
const React = require('react');
const ReactIntlRedux = require('react-intl-redux');
const ReactHotLoader = require('react-hot-loader');
const ReactRedux = require('react-redux');
const ReactRouter = require('react-router');
@ -6,6 +8,10 @@ const ReactRouter = require('react-router');
const App = require('./containers/app');
const store = require('./state/store');
const {
IntlProvider
} = ReactIntlRedux;
const {
AppContainer
} = ReactHotLoader;
@ -22,9 +28,11 @@ module.exports = () => {
return (
<AppContainer>
<Provider store={store()}>
<BrowserRouter>
{App}
</BrowserRouter>
<IntlProvider>
<BrowserRouter>
{App}
</BrowserRouter>
</IntlProvider>
</Provider>
</AppContainer>
);

View File

@ -6,6 +6,7 @@ const {
module.exports = () => {
return combineReducers({
app: require('./app.js')
app: require('./app.js'),
intl: require('./intl.js')
});
};

View File

@ -0,0 +1,7 @@
const ReduxActions = require('redux-actions');
const {
handleActions
} = ReduxActions;
module.exports = handleActions({}, require('../../intl'));

2
frontend/static/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

View File

@ -5,6 +5,10 @@
</head>
<body>
<div id='root'></div>
<script src='/static/locales/pt.js'></script>
<script src='/static/locales/pt-pt.js'></script>
<script src='/static/locales/en.js'></script>
<script src='/static/locales/en-us.js'></script>
<script src='/static/bundle.js'></script>
</body>
</html>

View File

@ -1,5 +1,6 @@
const pkg = require('../package.json');
const webpack = require('webpack');
const WebpackShellPlugin = require('webpack-shell-plugin');
const path = require('path');
module.exports = {
@ -17,6 +18,9 @@ module.exports = {
APP_NAME: JSON.stringify(pkg.name),
APP_VERSION: JSON.stringify(pkg.version)
}
}),
new WebpackShellPlugin({
onBuildStart: ['npm run build-locales']
})
],
module: {

View File

@ -66,7 +66,7 @@ ansi-regex@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.0.0.tgz#c5061b6e0ef8a81775e50f5d66151bf6bf371107"
ansi-styles@^2.2.1:
ansi-styles@^2.1.0, ansi-styles@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
@ -74,6 +74,10 @@ ansi-styles@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.0.0.tgz#cb102df1c56f5123eab8b67cd7b98027a0279178"
any-promise@^1.0.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
anymatch@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507"
@ -138,7 +142,7 @@ array-union@^1.0.1:
dependencies:
array-uniq "^1.0.1"
array-uniq@^1.0.1, array-uniq@^1.0.2:
array-uniq@^1.0.0, array-uniq@^1.0.1, array-uniq@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
@ -308,6 +312,32 @@ aws4@^1.2.1:
version "1.5.0"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.5.0.tgz#0a29ffb79c31c9e712eeb087e8e7a64b4a56d755"
babel-cli:
version "6.16.0"
resolved "https://registry.yarnpkg.com/babel-cli/-/babel-cli-6.16.0.tgz#4e0d1cf40442ef78330f7fef88eb3a0a1b16bd37"
dependencies:
babel-core "^6.16.0"
babel-polyfill "^6.16.0"
babel-register "^6.16.0"
babel-runtime "^6.9.0"
bin-version-check "^2.1.0"
chalk "1.1.1"
commander "^2.8.1"
convert-source-map "^1.1.0"
fs-readdir-recursive "^0.1.0"
glob "^5.0.5"
lodash "^4.2.0"
log-symbols "^1.0.2"
output-file-sync "^1.1.0"
path-exists "^1.0.0"
path-is-absolute "^1.0.0"
request "^2.65.0"
slash "^1.0.0"
source-map "^0.5.0"
v8flags "^2.0.10"
optionalDependencies:
chokidar "^1.0.0"
babel-code-frame@^6.16.0, babel-code-frame@^6.7.5:
version "6.16.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.16.0.tgz#f90e60da0862909d3ce098733b5d3987c97cb8de"
@ -316,7 +346,7 @@ babel-code-frame@^6.16.0, babel-code-frame@^6.7.5:
esutils "^2.0.2"
js-tokens "^2.0.0"
babel-core@^6.16.0, babel-core@^6.17.0, babel-core@^6.3.21:
babel-core, babel-core@^6.16.0, babel-core@^6.3.21:
version "6.17.0"
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.17.0.tgz#6c4576447df479e241e58c807e4bc7da4db7f425"
dependencies:
@ -848,6 +878,14 @@ babel-plugin-transform-strict-mode@^6.8.0:
babel-runtime "^6.0.0"
babel-types "^6.8.0"
babel-polyfill@^6.16.0:
version "6.16.0"
resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.16.0.tgz#2d45021df87e26a374b6d4d1a9c65964d17f2422"
dependencies:
babel-runtime "^6.9.1"
core-js "^2.4.0"
regenerator-runtime "^0.9.5"
babel-preset-es2015@^6.3.13:
version "6.16.0"
resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.16.0.tgz#59acecd1efbebaf48f89404840f2fe78c4d2ad5c"
@ -990,6 +1028,21 @@ big.js@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.1.3.tgz#4cada2193652eb3ca9ec8e55c9015669c9806978"
bin-version-check@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/bin-version-check/-/bin-version-check-2.1.0.tgz#e4e5df290b9069f7d111324031efc13fdd11a5b0"
dependencies:
bin-version "^1.0.0"
minimist "^1.1.0"
semver "^4.0.3"
semver-truncate "^1.0.0"
bin-version@^1.0.0:
version "1.0.4"
resolved "https://registry.yarnpkg.com/bin-version/-/bin-version-1.0.4.tgz#9eb498ee6fd76f7ab9a7c160436f89579435d78e"
dependencies:
find-versions "^1.0.0"
binary-extensions@^1.0.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.7.0.tgz#6c1610db163abfb34edfe42fa423343a1e01185d"
@ -1223,6 +1276,16 @@ chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3:
strip-ansi "^3.0.0"
supports-color "^2.0.0"
chalk@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.1.tgz#509afb67066e7499f7eb3535c77445772ae2d019"
dependencies:
ansi-styles "^2.1.0"
escape-string-regexp "^1.0.2"
has-ansi "^2.0.0"
strip-ansi "^3.0.0"
supports-color "^2.0.0"
cheerio@^0.22.0:
version "0.22.0"
resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e"
@ -1244,7 +1307,7 @@ cheerio@^0.22.0:
lodash.reject "^4.4.0"
lodash.some "^4.4.0"
chokidar@^1.4.2, chokidar@^1.4.3:
chokidar@^1.0.0, chokidar@^1.4.2, chokidar@^1.4.3:
version "1.6.1"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.6.1.tgz#2f4447ab5e96e50fb3d789fd90d4c72e0e4c70c2"
dependencies:
@ -1340,7 +1403,7 @@ combined-stream@^1.0.5, combined-stream@~1.0.5:
dependencies:
delayed-stream "~1.0.0"
commander@^2.9.0:
commander@^2.8.1, commander@^2.9.0:
version "2.9.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
dependencies:
@ -2181,6 +2244,15 @@ find-up@^1.0.0, find-up@^1.1.2:
path-exists "^2.0.0"
pinkie-promise "^2.0.0"
find-versions@^1.0.0:
version "1.2.1"
resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-1.2.1.tgz#cbde9f12e38575a0af1be1b9a2c5d5fd8f186b62"
dependencies:
array-uniq "^1.0.0"
get-stdin "^4.0.1"
meow "^3.5.0"
semver-regex "^1.0.0"
flat-cache@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.1.tgz#6c837d6225a7de5659323740b36d5361f71691ff"
@ -2235,6 +2307,10 @@ fresh@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.3.0.tgz#651f838e22424e7566de161d8358caa199f83d4f"
fs-readdir-recursive@^0.1.0:
version "0.1.2"
resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-0.1.2.tgz#315b4fb8c1ca5b8c47defef319d073dad3568059"
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
@ -2318,6 +2394,16 @@ glob-parent@^2.0.0:
dependencies:
is-glob "^2.0.0"
glob@^5.0.5:
version "5.0.15"
resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1"
dependencies:
inflight "^1.0.4"
inherits "2"
minimatch "2 || 3"
once "^1.3.0"
path-is-absolute "^1.0.0"
glob@^7.0.3, glob@^7.0.5, glob@^7.0.6:
version "7.1.1"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
@ -2376,7 +2462,7 @@ got@^5.0.0:
unzip-response "^1.0.0"
url-parse-lax "^1.0.0"
graceful-fs@^4.1.2:
graceful-fs@^4.1.2, graceful-fs@^4.1.4:
version "4.1.9"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.9.tgz#baacba37d19d11f9d146d3578bc99958c3787e29"
@ -2603,7 +2689,27 @@ interpret@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.1.tgz#d579fb7f693b858004947af39fa0db49f795602c"
invariant@^2.0.0, invariant@^2.2.0, invariant@^2.2.1:
intl-format-cache@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/intl-format-cache/-/intl-format-cache-2.0.5.tgz#b484cefcb9353f374f25de389a3ceea1af18d7c9"
intl-messageformat-parser@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/intl-messageformat-parser/-/intl-messageformat-parser-1.2.0.tgz#5906b7f953ab7470e0dc8549097b648b991892ff"
intl-messageformat@^1.3.0, intl-messageformat@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-1.3.0.tgz#f7d926aded7a3ab19b2dc601efd54e99a4bd4eae"
dependencies:
intl-messageformat-parser "1.2.0"
intl-relativeformat@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/intl-relativeformat/-/intl-relativeformat-1.3.0.tgz#893dc7076fccd380cf091a2300c380fa57ace45b"
dependencies:
intl-messageformat "1.3.0"
invariant@^2.0.0, invariant@^2.1.1, invariant@^2.2.0, invariant@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.1.tgz#b097010547668c7e337028ebe816ebe36c8a8d54"
dependencies:
@ -3114,6 +3220,12 @@ lodash@^4.0.0, lodash@^4.13.1, lodash@^4.15.0, lodash@^4.16.2, lodash@^4.2.0, lo
version "4.16.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.4.tgz#01ce306b9bad1319f2a5528674f88297aeb70127"
log-symbols@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
dependencies:
chalk "^1.0.0"
longest@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
@ -3181,7 +3293,7 @@ memory-fs@^0.3.0, memory-fs@~0.3.0:
errno "^0.1.3"
readable-stream "^2.0.1"
meow@^3.7.0:
meow@^3.5.0, meow@^3.7.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
dependencies:
@ -3253,7 +3365,7 @@ minimalistic-assert@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3"
minimatch@^3.0.0, minimatch@^3.0.2:
minimatch@^3.0.0, minimatch@^3.0.2, "minimatch@2 || 3":
version "3.0.3"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774"
dependencies:
@ -3302,6 +3414,10 @@ natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
ncp:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3"
negotiator@0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
@ -3593,6 +3709,14 @@ osenv@^0.1.0:
os-homedir "^1.0.0"
os-tmpdir "^1.0.0"
output-file-sync@^1.1.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/output-file-sync/-/output-file-sync-1.1.2.tgz#d0a33eefe61a205facb90092e826598d5245ce76"
dependencies:
graceful-fs "^4.1.4"
mkdirp "^0.5.1"
object-assign "^4.1.0"
package-hash@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-1.2.0.tgz#003e56cd57b736a6ed6114cc2b81542672770e44"
@ -3910,7 +4034,7 @@ querystring-es3@~0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
querystring@0.2.0:
querystring@^0.2.0, querystring@0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
@ -3971,6 +4095,24 @@ react-hot-loader@^3.0.0-beta.6:
redbox-react "^1.2.5"
source-map "^0.4.4"
react-intl, react-intl@^2.1.3:
version "2.1.5"
resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-2.1.5.tgz#f9795ea34b790dcb5d0d8ef7060dddbe85bf8763"
dependencies:
intl-format-cache "^2.0.5"
intl-messageformat "^1.3.0"
intl-relativeformat "^1.3.0"
invariant "^2.1.1"
react-intl-redux:
version "0.1.0"
resolved "https://registry.yarnpkg.com/react-intl-redux/-/react-intl-redux-0.1.0.tgz#94d9cef8214707ae0effa3e5113a35000c7b0baa"
dependencies:
react-intl "^2.1.3"
react-redux "^4.4.5"
redux "^3.5.2"
warning "^3.0.0"
react-proxy@^3.0.0-alpha.0:
version "3.0.0-alpha.1"
resolved "https://registry.yarnpkg.com/react-proxy/-/react-proxy-3.0.0-alpha.1.tgz#4400426bcfa80caa6724c7755695315209fa4b07"
@ -4108,7 +4250,7 @@ redux-thunk@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.1.0.tgz#c724bfee75dbe352da2e3ba9bc14302badd89a98"
redux@^3.6.0:
redux@^3.5.2, redux@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/redux/-/redux-3.6.0.tgz#887c2b3d0b9bd86eca2be70571c27654c19e188d"
dependencies:
@ -4182,7 +4324,7 @@ repeating@^2.0.0:
dependencies:
is-finite "^1.0.0"
request@2.x:
request@^2.65.0, request@2.x:
version "2.75.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.75.0.tgz#d2b8268a286da13eaa5d01adf5d18cc90f657d93"
dependencies:
@ -4292,7 +4434,21 @@ semver-diff@^2.0.0:
dependencies:
semver "^5.0.3"
semver@^5.0.3, semver@^5.1.0, semver@~5.3.0, "semver@2 || 3 || 4 || 5":
semver-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-1.0.0.tgz#92a4969065f9c70c694753d55248fc68f8f652c9"
semver-truncate@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/semver-truncate/-/semver-truncate-1.1.2.tgz#57f41de69707a62709a7e0104ba2117109ea47e8"
dependencies:
semver "^5.3.0"
semver@^4.0.3:
version "4.3.6"
resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da"
semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@~5.3.0, "semver@2 || 3 || 4 || 5":
version "5.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
@ -4652,6 +4808,12 @@ the-argv@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/the-argv/-/the-argv-1.0.0.tgz#0084705005730dd84db755253c931ae398db9522"
thenify@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.2.1.tgz#251fd1c80aff6e5cf57cb179ab1fcb724269bd11"
dependencies:
any-promise "^1.0.0"
through@^2.3.6:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
@ -4848,6 +5010,12 @@ uuid@^2.0.1, uuid@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a"
v8flags@^2.0.10:
version "2.0.11"
resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.0.11.tgz#bca8f30f0d6d60612cc2c00641e6962d42ae6881"
dependencies:
user-home "^1.1.1"
validate-npm-package-license@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"
@ -4912,6 +5080,10 @@ webpack-dev-server@^1.16.2:
supports-color "^3.1.1"
webpack-dev-middleware "^1.4.0"
webpack-shell-plugin:
version "0.4.3"
resolved "https://registry.yarnpkg.com/webpack-shell-plugin/-/webpack-shell-plugin-0.4.3.tgz#a633e98c16b3bed5b6963e98059ca783841f3043"
webpack-sources@^0.1.0:
version "0.1.2"
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-0.1.2.tgz#057a3f3255f8ba561b901d9150589aa103a57e65"