Beginning of translation using react-intl

This commit is contained in:
Lucas Verney 2016-07-28 01:22:48 +02:00
parent a13f87b5c0
commit e6b9c3bf07
21 changed files with 166 additions and 12184 deletions

View File

@ -1,3 +1,9 @@
{ {
"presets": ["es2015", "react"] "presets": ["es2015", "react"],
"plugins": [
["react-intl", {
"messagesDir": "./app/dist/i18n/",
"enforceDescriptions": true
}]
]
} }

2
.gitignore vendored
View File

@ -3,3 +3,5 @@ app/dist/eventsourcePolyfill.js
app/dist/webpackHotMiddlewareClient.js app/dist/webpackHotMiddlewareClient.js
app/dist/*.hot-update.json app/dist/*.hot-update.json
app/dist/*.hot-update.js app/dist/*.hot-update.js
app/dist/i18n/
app/dist/3.3.js

5
TODO
View File

@ -1,9 +1,11 @@
4. Refactor API + Handle failures
5. Web player 5. Web player
6. Homepage 6. Homepage
7. Settings 7. Settings
8. Search 8. Search
9. Discover 9. Discover
# CSS # CSS
* Sidebar responsiveness * Sidebar responsiveness
* Move CSS in modules * Move CSS in modules
@ -24,5 +26,4 @@
## Miscellaneous ## Miscellaneous
* See TODOs in the code * See TODOs in the code
* Uncaught TypeError: this.props.tracks.forEach is not a function * Babel transform runtime
=> Be more robust, else, getHostNode is null after

View File

@ -1,4 +1,5 @@
import React, { Component, PropTypes } from "react"; import React, { Component, PropTypes } from "react";
import { FormattedMessage } from "react-intl";
export class LoginForm extends Component { export class LoginForm extends Component {
constructor (props) { constructor (props) {
@ -89,7 +90,7 @@ export class LoginForm extends Component {
<div className="row"> <div className="row">
<div className="col-sm-6 col-xs-12 checkbox"> <div className="col-sm-6 col-xs-12 checkbox">
<label id="rememberMeLabel"> <label id="rememberMeLabel">
<input type="checkbox" ref="rememberMe" defaultChecked={this.props.rememberMe} aria-labelledby="rememberMeLabel" /> Remember me <input type="checkbox" ref="rememberMe" defaultChecked={this.props.rememberMe} aria-labelledby="rememberMeLabel" /> <FormattedMessage id="app.login.rememberMe" description="Remember me checkbox label" defaultMessage="Remember me" />
</label> </label>
</div> </div>
<div className="col-sm-6 col-sm-12 submit text-right"> <div className="col-sm-6 col-sm-12 submit text-right">
@ -123,7 +124,7 @@ export default class Login extends Component {
<div className="login text-center container-fluid"> <div className="login text-center container-fluid">
<h1><img src="./app/assets/img/ampache-blue.png" alt="A"/>mpache</h1> <h1><img src="./app/assets/img/ampache-blue.png" alt="A"/>mpache</h1>
<hr/> <hr/>
<p>Welcome back on Ampache, let"s go!</p> <p><FormattedMessage id="app.login.greeting" description="Greeting to welcome the user to the app" defaultMessage="Welcome back on Ampache, let's go!" /></p>
<div className="col-sm-9 col-sm-offset-2 col-md-6 col-md-offset-3"> <div className="col-sm-9 col-sm-offset-2 col-md-6 col-md-offset-3">
<LoginForm onSubmit={this.props.onSubmit} username={this.props.username} endpoint={this.props.endpoint} rememberMe={this.props.rememberMe} isAuthenticating={this.props.isAuthenticating} error={this.props.error} info={this.props.info} /> <LoginForm onSubmit={this.props.onSubmit} username={this.props.username} endpoint={this.props.endpoint} rememberMe={this.props.rememberMe} isAuthenticating={this.props.isAuthenticating} error={this.props.error} info={this.props.info} />
</div> </div>

View File

@ -1,15 +1,18 @@
import React, { Component, PropTypes } from "react"; import React, { Component, PropTypes } from "react";
import { Provider } from "react-redux"; import { Provider } from "react-redux";
import { Router } from "react-router"; import { Router } from "react-router";
import { IntlProvider } from "react-intl";
import routes from "../routes"; import routes from "../routes";
export default class Root extends Component { export default class Root extends Component {
render() { render() {
const { store, history } = this.props; const { locale, messages, defaultLocale, store, history } = this.props;
return ( return (
<Provider store={store}> <Provider store={store}>
<Router history={history} routes={routes} /> <IntlProvider locale={locale} messages={messages} defaultLocale={defaultLocale}>
<Router history={history} routes={routes} />
</IntlProvider>
</Provider> </Provider>
); );
} }
@ -17,5 +20,8 @@ export default class Root extends Component {
Root.propTypes = { Root.propTypes = {
store: PropTypes.object.isRequired, store: PropTypes.object.isRequired,
history: PropTypes.object.isRequired history: PropTypes.object.isRequired,
locale: PropTypes.string.isRequired,
messages: PropTypes.object.isRequired,
defaultLocale: PropTypes.string.isRequired
}; };

4
app/dist/1.1.js vendored Normal file

File diff suppressed because one or more lines are too long

1
app/dist/1.1.js.map vendored Normal file

File diff suppressed because one or more lines are too long

598
app/dist/fix.ie9.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4574
app/dist/index.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
app/dist/reactIntlMessages.json vendored Normal file
View File

@ -0,0 +1 @@
[]

7002
app/dist/style.css vendored

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,7 @@
module.exports = {
"app": {
"login": {
"greeting": "TODO"
}
}
};

View File

@ -0,0 +1,3 @@
module.exports = {
"app.login.greeting": "TODO",
};

4
app/locales/index.js Normal file
View File

@ -0,0 +1,4 @@
module.exports = {
"en-US": require("./en-US"),
"fr-FR": require("./fr-FR")
};

View File

@ -1,4 +1,5 @@
export * from "./jquery"; export * from "./jquery";
export * from "./locale";
export * from "./misc"; export * from "./misc";
export * from "./reducers"; export * from "./reducers";
export * from "./string"; export * from "./string";

21
app/utils/locale.js Normal file
View File

@ -0,0 +1,21 @@
export function getBrowserLocale () {
var lang;
if (navigator.languages) {
// chrome does not currently set navigator.language correctly https://code.google.com/p/chromium/issues/detail?id=101138
// but it does set the first element of navigator.languages correctly
lang = navigator.languages[0];
} else if (navigator.userLanguage) {
// IE only
lang = navigator.userLanguage;
} else {
// as of this writing the latest version of firefox + safari set this correctly
lang = navigator.language;
}
// Some browsers does not return uppercase for second part
var locale = lang.split("-");
locale = locale[1] ? `${locale[0]}-${locale[1].toUpperCase()}` : lang;
return locale;
}

View File

@ -9,42 +9,73 @@ import ReactDOM from "react-dom";
import { hashHistory } from "react-router"; import { hashHistory } from "react-router";
import { syncHistoryWithStore } from "react-router-redux"; import { syncHistoryWithStore } from "react-router-redux";
// i18n
import { addLocaleData } from "react-intl";
import en from "react-intl/locale-data/en";
import fr from "react-intl/locale-data/fr";
import configureStore from "./app/store/configureStore"; import configureStore from "./app/store/configureStore";
import { getBrowserLocale } from "./app/utils";
import rawMessages from "./app/locales";
const store = configureStore(); const store = configureStore();
const history = syncHistoryWithStore(hashHistory, store); const history = syncHistoryWithStore(hashHistory, store);
const rootElement = document.getElementById("root"); const rootElement = document.getElementById("root");
let render = () => { // i18n
const Root = require("./app/containers/Root").default; const onWindowIntl = () => {
ReactDOM.render( addLocaleData([...en, ...fr]);
<Root store={store} history={history} />, const locale = getBrowserLocale();
rootElement var strings = rawMessages[locale] ? rawMessages[locale] : rawMessages["en-US"];
); strings = Object.assign(rawMessages["en-US"], strings);
};
if (module.hot) { let render = () => {
// Support hot reloading of components const Root = require("./app/containers/Root").default;
// and display an overlay for runtime errors
const renderApp = render;
const renderError = (error) => {
const RedBox = require("redbox-react");
ReactDOM.render( ReactDOM.render(
<RedBox error={error} />, <Root store={store} history={history} locale={locale} defaultLocale="en-US" messages={strings} />,
rootElement rootElement
); );
}; };
render = () => {
try {
renderApp();
} catch (error) {
renderError(error);
}
};
module.hot.accept("./app/containers/Root", () => {
setTimeout(render);
});
}
render(); if (module.hot) {
// Support hot reloading of components
// and display an overlay for runtime errors
const renderApp = render;
const renderError = (error) => {
const RedBox = require("redbox-react");
ReactDOM.render(
<RedBox error={error} />,
rootElement
);
};
render = () => {
try {
renderApp();
} catch (error) {
renderError(error);
}
};
module.hot.accept("./app/containers/Root", () => {
setTimeout(render);
});
}
render();
};
if (!window.Intl) {
require.ensure([
"intl",
"intl/locale-data/jsonp/en.js",
"intl/locale-data/jsonp/fr.js"
], function (require) {
require("intl");
require("intl/locale-data/jsonp/en.js");
require("intl/locale-data/jsonp/fr.js");
onWindowIntl();
});
} else {
onWindowIntl();
}

View File

@ -13,11 +13,13 @@
"dependencies": { "dependencies": {
"babel-polyfill": "^6.9.1", "babel-polyfill": "^6.9.1",
"babel-preset-es2015": "^6.9.0", "babel-preset-es2015": "^6.9.0",
"babel-runtime": "^6.11.6",
"bootstrap": "^3.3.6", "bootstrap": "^3.3.6",
"fuse.js": "^2.3.0", "fuse.js": "^2.3.0",
"html5shiv": "^3.7.3", "html5shiv": "^3.7.3",
"humps": "^1.1.0", "humps": "^1.1.0",
"imagesloaded": "^4.1.0", "imagesloaded": "^4.1.0",
"intl": "^1.2.4",
"isomorphic-fetch": "^2.2.1", "isomorphic-fetch": "^2.2.1",
"isotope-layout": "^3.0.1", "isotope-layout": "^3.0.1",
"jquery": "^3.1.0", "jquery": "^3.1.0",
@ -26,6 +28,7 @@
"lodash": "^4.13.1", "lodash": "^4.13.1",
"react": "^15.2.0", "react": "^15.2.0",
"react-dom": "^15.2.0", "react-dom": "^15.2.0",
"react-intl": "^2.1.3",
"react-redux": "^4.4.5", "react-redux": "^4.4.5",
"react-router": "^2.5.2", "react-router": "^2.5.2",
"react-router-redux": "^4.0.5", "react-router-redux": "^4.0.5",
@ -37,6 +40,8 @@
"autoprefixer": "^6.3.7", "autoprefixer": "^6.3.7",
"babel-core": "^6.10.4", "babel-core": "^6.10.4",
"babel-loader": "^6.2.4", "babel-loader": "^6.2.4",
"babel-plugin-react-intl": "^2.1.3",
"babel-plugin-transform-runtime": "^6.12.0",
"babel-preset-react": "^6.11.1", "babel-preset-react": "^6.11.1",
"css-loader": "^0.23.1", "css-loader": "^0.23.1",
"doiuse": "^2.4.1", "doiuse": "^2.4.1",
@ -51,6 +56,7 @@
"postcss-reporter": "^1.4.1", "postcss-reporter": "^1.4.1",
"precss": "^1.4.0", "precss": "^1.4.0",
"react-a11y": "^0.3.3", "react-a11y": "^0.3.3",
"react-intl-webpack-plugin": "0.0.3",
"redbox-react": "^1.2.10", "redbox-react": "^1.2.10",
"redux-logger": "^2.6.1", "redux-logger": "^2.6.1",
"style-loader": "^0.13.1", "style-loader": "^0.13.1",

View File

@ -1,6 +1,7 @@
var path = require("path"); var path = require("path");
var webpack = require("webpack"); var webpack = require("webpack");
var ReactIntlPlugin=require("react-intl-webpack-plugin");
var ExtractTextPlugin = require("extract-text-webpack-plugin"); var ExtractTextPlugin = require("extract-text-webpack-plugin");
var postcssReporter = require("postcss-reporter"); var postcssReporter = require("postcss-reporter");
var doiuse = require("doiuse"); var doiuse = require("doiuse");
@ -11,7 +12,7 @@ var browsers = ["ie >= 9", "> 1%", "last 3 versions", "not op_mini all"];
module.exports = { module.exports = {
entry: { entry: {
"index": "./index.js", "index": ["babel-polyfill", "./index.js"],
"fix.ie9": "./fix.ie9.js" "fix.ie9": "./fix.ie9.js"
}, },
@ -34,7 +35,10 @@ module.exports = {
{ {
test: /\.jsx?$/, test: /\.jsx?$/,
exclude: /node_modules/, exclude: /node_modules/,
loaders: ["babel"], loader: "babel",
query: {
"cacheDirectory": true
},
include: __dirname include: __dirname
}, },
// Do not postcss vendor modules // Do not postcss vendor modules
@ -76,6 +80,7 @@ module.exports = {
}, },
plugins: [ plugins: [
new ReactIntlPlugin(),
new webpack.ProvidePlugin({ new webpack.ProvidePlugin({
$: "jquery", $: "jquery",
jQuery: "jquery" jQuery: "jquery"