mirror of
https://github.com/strapi/strapi.git
synced 2025-09-23 07:22:51 +00:00
Implement i18n
This commit is contained in:
parent
ed4586ee7a
commit
6de2503b9c
@ -18,6 +18,7 @@ const store = configureStore(initialState, browserHistory);
|
||||
// Set up the router, wrapping all Routes in the App component
|
||||
import App from 'containers/App';
|
||||
import createRoutes from './routes';
|
||||
import { translationMessages } from './i18n';
|
||||
|
||||
// Plugin identifier based on the package.json `name` value
|
||||
const pluginId = require('../package.json').name.replace(/^strapi-/i, '');
|
||||
@ -33,6 +34,22 @@ if (window.Strapi) {
|
||||
},
|
||||
mainComponent: App,
|
||||
routes: createRoutes(store),
|
||||
translationMessages,
|
||||
});
|
||||
}
|
||||
|
||||
// Hot reloadable translation json files
|
||||
if (module.hot) {
|
||||
// modules.hot.accept does not accept dynamic dependencies,
|
||||
// have to be constants at compile-time
|
||||
module.hot.accept('./i18n', () => {
|
||||
if (window.Strapi) {
|
||||
System.import('./i18n')
|
||||
.then(result => {
|
||||
const translationMessagesUpdated = result.translationMessages;
|
||||
window.Strapi.refresh(pluginId).translationMessages(translationMessagesUpdated);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -11,27 +11,21 @@ import styles from './styles.scss';
|
||||
|
||||
class LeftMenu extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||
links = [{
|
||||
label: 'General',
|
||||
value: 'general',
|
||||
to: '',
|
||||
}, {
|
||||
label: 'Languages',
|
||||
value: 'languages',
|
||||
to: 'languages',
|
||||
}, {
|
||||
label: 'Databases',
|
||||
value: 'databases',
|
||||
to: 'databases',
|
||||
}, {
|
||||
label: 'Security',
|
||||
value: 'security',
|
||||
to: 'security',
|
||||
}, {
|
||||
label: 'Server',
|
||||
value: 'server',
|
||||
to: 'server',
|
||||
}, {
|
||||
label: 'Advanced',
|
||||
value: 'advanced',
|
||||
to: 'advanced',
|
||||
}];
|
||||
|
@ -1,19 +1,27 @@
|
||||
/**
|
||||
*
|
||||
* LeftMenuLink
|
||||
*
|
||||
*/
|
||||
*
|
||||
* LeftMenuLink
|
||||
*
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import appMessages from 'containers/App/messages';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import styles from './styles.scss';
|
||||
console.log('styles', styles);
|
||||
|
||||
class LeftMenuLink extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||
render() {
|
||||
const messageKey = `${this.props.link.value}SectionTitle`;
|
||||
return (
|
||||
<li className={styles.leftMenuLink}>
|
||||
<Link className={styles.leftMenuLinkDestination} activeClassName={styles.leftMenuLinkDestinationActive} to={`/plugins/settings-manager/${this.props.link.to}`}>{this.props.link.label}
|
||||
<Link
|
||||
className={styles.leftMenuLinkDestination}
|
||||
activeClassName={styles.leftMenuLinkDestinationActive}
|
||||
to={`/plugins/settings-manager/${this.props.link.to}`}
|
||||
>
|
||||
<FormattedMessage {...appMessages[messageKey]} />
|
||||
<i className={`ion ion-arrow-right-c ${styles.leftMenuLinkIcon}`}></i>
|
||||
</Link>
|
||||
</li>
|
||||
|
@ -5,6 +5,8 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import messages from './messages';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import styles from './styles.scss';
|
||||
|
||||
@ -17,7 +19,7 @@ class PluginHeaderActions extends React.Component { // eslint-disable-line react
|
||||
className={`${styles.pluginHeaderActionsButton} btn btn-secondary`}
|
||||
onClick={this.props.onCancel}
|
||||
>
|
||||
Cancel
|
||||
<FormattedMessage {...messages.cancelLabel} />
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
@ -25,7 +27,7 @@ class PluginHeaderActions extends React.Component { // eslint-disable-line react
|
||||
disabled={this.props.loading}
|
||||
onClick={this.props.onFormSubmit}
|
||||
>
|
||||
Save
|
||||
<FormattedMessage {...messages.saveLabel} />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
17
public/app/components/PluginHeaderActions/messages.js
Normal file
17
public/app/components/PluginHeaderActions/messages.js
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* PluginHeaderActions Messages
|
||||
*
|
||||
* This contains all the text for the PluginHeaderActions component.
|
||||
*/
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
||||
export default defineMessages({
|
||||
cancelLabel: {
|
||||
id: 'settings-manager.components.PluginHeaderActions.cancelLabel',
|
||||
defaultMessage: 'Cancel',
|
||||
},
|
||||
saveLabel: {
|
||||
id: 'settings-manager.components.PluginHeaderActions.saveLabel',
|
||||
defaultMessage: 'Save',
|
||||
},
|
||||
});
|
@ -5,15 +5,21 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import messages from './messages';
|
||||
import styles from './styles.scss';
|
||||
|
||||
class PluginHeaderTitle extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||
render() {
|
||||
return (
|
||||
<div className={styles.pluginHeaderTitle}>
|
||||
<h1 className={styles.pluginHeaderTitleName}>Settings Manager</h1>
|
||||
<p className={styles.pluginHeaderTitleDescription}>Easily update your settings</p>
|
||||
<h1 className={styles.pluginHeaderTitleName}>
|
||||
<FormattedMessage {...messages.title} />
|
||||
</h1>
|
||||
<p className={styles.pluginHeaderTitleDescription}>
|
||||
<FormattedMessage {...messages.description} />
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
17
public/app/components/PluginHeaderTitle/messages.js
Normal file
17
public/app/components/PluginHeaderTitle/messages.js
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* PluginHeaderTitle Messages
|
||||
*
|
||||
* This contains all the text for the PluginHeaderTitle component.
|
||||
*/
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
||||
export default defineMessages({
|
||||
title: {
|
||||
id: 'settings-manager.components.PluginHeaderTitle.title',
|
||||
defaultMessage: 'Settings Manager',
|
||||
},
|
||||
description: {
|
||||
id: 'settings-manager.components.PluginHeaderTitle.description',
|
||||
defaultMessage: 'Easily configure your settings',
|
||||
},
|
||||
});
|
@ -10,26 +10,44 @@ import PluginHeader from 'components/PluginHeader';
|
||||
import Container from 'components/Container';
|
||||
import RightContentTitle from 'components/RightContentTitle';
|
||||
import RightContentSectionTitle from 'components/RightContentSectionTitle';
|
||||
import { injectIntl, intlShape } from 'react-intl';
|
||||
import appMessages from 'containers/App/messages';
|
||||
import messages from './messages';
|
||||
|
||||
import styles from './styles.scss';
|
||||
|
||||
export default class AdvancedPage extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||
export class AdvancedPage extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||
render() {
|
||||
const { formatMessage } = this.props.intl;
|
||||
|
||||
return (
|
||||
<div className={styles.advancedPage}>
|
||||
<Helmet
|
||||
title="Settings Manager - Advanced"
|
||||
meta={[
|
||||
{ name: 'description', content: 'Configure your Advanced settings.' },
|
||||
{ name: 'description', content: formatMessage(messages.rightSectionDescription) },
|
||||
]}
|
||||
/>
|
||||
<div className="container">
|
||||
<PluginHeader></PluginHeader>
|
||||
<PluginHeader />
|
||||
<Container>
|
||||
<RightContentTitle title="Advanced" description="Configure your advanced settings."></RightContentTitle>
|
||||
<RightContentSectionTitle title="Coming soon" description=""></RightContentSectionTitle>
|
||||
<RightContentTitle
|
||||
title={formatMessage(appMessages.advancedSectionTitle)}
|
||||
description={formatMessage(messages.rightSectionDescription)}
|
||||
/>
|
||||
<RightContentSectionTitle
|
||||
title={formatMessage(appMessages.comingSoon)}
|
||||
description=""
|
||||
/>
|
||||
</Container>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
AdvancedPage.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(AdvancedPage);
|
||||
|
13
public/app/containers/AdvancedPage/messages.js
Normal file
13
public/app/containers/AdvancedPage/messages.js
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* LanguagesPage Messages
|
||||
*
|
||||
* This contains all the text for the LanguagesPage component.
|
||||
*/
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
||||
export default defineMessages({
|
||||
rightSectionDescription: {
|
||||
id: 'settings-manager.components.AdvancedPage.rightSectionDescription',
|
||||
defaultMessage: 'Configure your advanced settings',
|
||||
},
|
||||
});
|
37
public/app/containers/App/messages.js
Normal file
37
public/app/containers/App/messages.js
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* App Messages
|
||||
*
|
||||
* This contains all the text use across the plugin.
|
||||
*/
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
||||
export default defineMessages({
|
||||
generalSectionTitle: {
|
||||
id: 'settings-manager.components.App.generalSectionTitle',
|
||||
defaultMessage: 'General',
|
||||
},
|
||||
languagesSectionTitle: {
|
||||
id: 'settings-manager.components.App.languagesSectionTitle',
|
||||
defaultMessage: 'Languages',
|
||||
},
|
||||
databasesSectionTitle: {
|
||||
id: 'settings-manager.components.App.databasesSectionTitle',
|
||||
defaultMessage: 'Databases',
|
||||
},
|
||||
securitySectionTitle: {
|
||||
id: 'settings-manager.components.App.securitySectionTitle',
|
||||
defaultMessage: 'Security',
|
||||
},
|
||||
serverSectionTitle: {
|
||||
id: 'settings-manager.components.App.serverSectionTitle',
|
||||
defaultMessage: 'Server',
|
||||
},
|
||||
advancedSectionTitle: {
|
||||
id: 'settings-manager.components.App.advancedSectionTitle',
|
||||
defaultMessage: 'Advanced',
|
||||
},
|
||||
comingSoon: {
|
||||
id: 'settings-manager.components.App.comingSoon',
|
||||
defaultMessage: 'Coming soon',
|
||||
},
|
||||
});
|
@ -8,28 +8,45 @@ import PluginHeader from 'components/PluginHeader';
|
||||
import Container from 'components/Container';
|
||||
import RightContentTitle from 'components/RightContentTitle';
|
||||
import RightContentSectionTitle from 'components/RightContentSectionTitle';
|
||||
import { injectIntl, intlShape } from 'react-intl';
|
||||
import appMessages from 'containers/App/messages';
|
||||
import messages from './messages';
|
||||
|
||||
import styles from './styles.scss';
|
||||
|
||||
export default class DatabasesPage extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||
export class DatabasesPage extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||
|
||||
render() {
|
||||
const { formatMessage } = this.props.intl;
|
||||
|
||||
return (
|
||||
<div className={styles.databasesPage}>
|
||||
<Helmet
|
||||
title="Settings Manager - Databases"
|
||||
meta={[
|
||||
{ name: 'description', content: 'Configure your Databases settings.' },
|
||||
{ name: 'description', content: formatMessage(messages.rightSectionDescription) },
|
||||
]}
|
||||
/>
|
||||
<div className="container">
|
||||
<PluginHeader></PluginHeader>
|
||||
<PluginHeader />
|
||||
<Container>
|
||||
<RightContentTitle title="Databases" description="Configure your databases settings."></RightContentTitle>
|
||||
<RightContentSectionTitle title="Coming soon" description=""></RightContentSectionTitle>
|
||||
<RightContentTitle
|
||||
title={formatMessage(appMessages.databasesSectionTitle)}
|
||||
description={formatMessage(messages.rightSectionDescription)}
|
||||
/>
|
||||
<RightContentSectionTitle
|
||||
title={formatMessage(appMessages.comingSoon)}
|
||||
description=""
|
||||
/>
|
||||
</Container>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DatabasesPage.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(DatabasesPage);
|
||||
|
@ -1,13 +1,13 @@
|
||||
/*
|
||||
* DatabasesPage Messages
|
||||
* LanguagesPage Messages
|
||||
*
|
||||
* This contains all the text for the DatabasesPage component.
|
||||
* This contains all the text for the LanguagesPage component.
|
||||
*/
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
||||
export default defineMessages({
|
||||
header: {
|
||||
id: 'app.components.DatabasesPage.header',
|
||||
defaultMessage: 'This is the Databases page of the Settings Manager plugin!',
|
||||
rightSectionDescription: {
|
||||
id: 'settings-manager.components.DatabasesPage.rightSectionDescription',
|
||||
defaultMessage: 'Configure your databases settings',
|
||||
},
|
||||
});
|
||||
|
@ -31,6 +31,9 @@ import {
|
||||
updateGeneralSettings,
|
||||
cancelGeneralSettings,
|
||||
} from 'containers/HomePage/actions';
|
||||
import { injectIntl, intlShape, FormattedMessage } from 'react-intl';
|
||||
import appMessages from 'containers/App/messages';
|
||||
import messages from './messages';
|
||||
|
||||
import styles from './styles.scss';
|
||||
|
||||
@ -41,21 +44,31 @@ export class HomePage extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { formatMessage } = this.props.intl;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="container">
|
||||
<PluginHeader {...this.props}></PluginHeader>
|
||||
<Container>
|
||||
<RightContentTitle title="General" description="Configure your general settings."></RightContentTitle>
|
||||
<RightContentSectionTitle title="Application" description="The general settings of your Strapi application."></RightContentSectionTitle>
|
||||
<RightContentTitle
|
||||
title={formatMessage(appMessages.generalSectionTitle)}
|
||||
description={formatMessage(messages.rightSectionDescription)}
|
||||
/>
|
||||
<RightContentSectionTitle
|
||||
title={formatMessage(messages.rightContentSectionTitle)}
|
||||
description={formatMessage(messages.rightContentSectionDescription)}
|
||||
/>
|
||||
<form onSubmit={this.props.onFormSubmit}>
|
||||
<div className={`form-group row ${styles.homePageRightContentFormGroup}`}>
|
||||
<label htmlFor="applicationName" className="col-xs-7 col-form-label">Name</label>
|
||||
<label htmlFor="applicationName" className="col-xs-7 col-form-label">
|
||||
<FormattedMessage {...messages.nameLabel} />
|
||||
</label>
|
||||
<div className="col-xs-5">
|
||||
<input
|
||||
className="form-control"
|
||||
type="text"
|
||||
placeholder="My Application"
|
||||
placeholder={formatMessage(messages.namePlaceholder)}
|
||||
id="applicationName"
|
||||
value={this.props.name || ''}
|
||||
onChange={this.props.onChangeName}
|
||||
@ -64,12 +77,14 @@ export class HomePage extends React.Component {
|
||||
</div>
|
||||
</div>
|
||||
<div className={`form-group row ${styles.homePageRightContentFormGroup}`}>
|
||||
<label htmlFor="applicationDescription" className="col-xs-7 col-form-label">Description</label>
|
||||
<label htmlFor="applicationDescription" className="col-xs-7 col-form-label">
|
||||
<FormattedMessage {...messages.descriptionLabel} />
|
||||
</label>
|
||||
<div className="col-xs-5">
|
||||
<input
|
||||
className="form-control"
|
||||
type="text"
|
||||
placeholder="A Strapi application"
|
||||
placeholder={formatMessage(messages.descriptionPlaceholder)}
|
||||
id="applicationDescription"
|
||||
value={this.props.description || ''}
|
||||
onChange={this.props.onChangeDescription}
|
||||
@ -77,12 +92,14 @@ export class HomePage extends React.Component {
|
||||
</div>
|
||||
</div>
|
||||
<div className={`form-group row ${styles.homePageRightContentFormGroup}`}>
|
||||
<label htmlFor="applicationVersion" className="col-xs-7 col-form-label">Version</label>
|
||||
<label htmlFor="applicationVersion" className="col-xs-7 col-form-label">
|
||||
<FormattedMessage {...messages.versionLabel} />
|
||||
</label>
|
||||
<div className="col-xs-5">
|
||||
<input
|
||||
className="form-control"
|
||||
type="text"
|
||||
placeholder="0.0.1"
|
||||
placeholder={formatMessage(messages.versionPlaceholder)}
|
||||
id="applicationVersion"
|
||||
value={this.props.version || ''}
|
||||
onChange={this.props.onChangeVersion}
|
||||
@ -108,6 +125,7 @@ HomePage.propTypes = {
|
||||
React.PropTypes.object,
|
||||
React.PropTypes.bool,
|
||||
]),
|
||||
intl: intlShape.isRequired,
|
||||
loading: React.PropTypes.bool,
|
||||
name: React.PropTypes.oneOfType([
|
||||
React.PropTypes.string,
|
||||
@ -123,7 +141,6 @@ HomePage.propTypes = {
|
||||
React.PropTypes.string,
|
||||
React.PropTypes.bool,
|
||||
]),
|
||||
|
||||
};
|
||||
|
||||
export function mapDispatchToProps(dispatch) {
|
||||
@ -153,4 +170,4 @@ const mapStateToProps = createStructuredSelector({
|
||||
});
|
||||
|
||||
// Wrap the component to inject dispatch and state into it
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(HomePage);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(injectIntl(HomePage));
|
||||
|
49
public/app/containers/HomePage/messages.js
Normal file
49
public/app/containers/HomePage/messages.js
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* HomePage Messages
|
||||
*
|
||||
* This contains all the text for the HomePage component.
|
||||
*/
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
||||
export default defineMessages({
|
||||
rightSectionDescription: {
|
||||
id: 'settings-manager.components.HomePage.rightSectionDescription',
|
||||
defaultMessage: 'Configure your general settings',
|
||||
},
|
||||
rightContentSectionTitle: {
|
||||
id: 'settings-manager.components.HomePage.rightContentSectionTitle',
|
||||
defaultMessage: 'Application',
|
||||
},
|
||||
rightContentSectionDescription: {
|
||||
id: 'settings-manager.components.HomePage.rightContentSectionDescription',
|
||||
defaultMessage: 'The general settings of your Strapi application.',
|
||||
},
|
||||
nameLabel: {
|
||||
id: 'settings-manager.components.HomePage.nameLabel',
|
||||
defaultMessage: 'Name',
|
||||
},
|
||||
namePlaceholder: {
|
||||
id: 'settings-manager.components.HomePage.namePlaceholder',
|
||||
defaultMessage: 'My Application',
|
||||
},
|
||||
descriptionLabel: {
|
||||
id: 'settings-manager.components.HomePage.descriptionLabel',
|
||||
defaultMessage: 'Description',
|
||||
},
|
||||
descriptionPlaceholder: {
|
||||
id: 'settings-manager.components.HomePage.descriptionPlaceholder',
|
||||
defaultMessage: 'A Strapi application',
|
||||
},
|
||||
versionLabel: {
|
||||
id: 'settings-manager.components.HomePage.versionLabel',
|
||||
defaultMessage: 'Version',
|
||||
},
|
||||
versionPlaceholder: {
|
||||
id: 'settings-manager.components.HomePage.versionPlaceholder',
|
||||
defaultMessage: '0.0.1',
|
||||
},
|
||||
submit: {
|
||||
id: 'settings-manager.components.HomePage.submit',
|
||||
defaultMessage: 'Submit',
|
||||
},
|
||||
});
|
@ -8,27 +8,45 @@ import PluginHeader from 'components/PluginHeader';
|
||||
import Container from 'components/Container';
|
||||
import RightContentTitle from 'components/RightContentTitle';
|
||||
import RightContentSectionTitle from 'components/RightContentSectionTitle';
|
||||
import { injectIntl, intlShape } from 'react-intl';
|
||||
import appMessages from 'containers/App/messages';
|
||||
import messages from './messages';
|
||||
|
||||
import styles from './styles.scss';
|
||||
|
||||
export default class LanguagesPage extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||
export class LanguagesPage extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||
|
||||
render() {
|
||||
const { formatMessage } = this.props.intl;
|
||||
|
||||
return (
|
||||
<div className={styles.languagesPage}>
|
||||
<Helmet
|
||||
title="Settings Manager - Languages"
|
||||
meta={[
|
||||
{ name: 'description', content: 'Configure your Languages settings.' },
|
||||
{ name: 'description', content: formatMessage(messages.rightSectionDescription) },
|
||||
]}
|
||||
/>
|
||||
<div className="container">
|
||||
<PluginHeader></PluginHeader>
|
||||
<PluginHeader />
|
||||
<Container>
|
||||
<RightContentTitle title="Languages" description="Configure your languages settings."></RightContentTitle>
|
||||
<RightContentSectionTitle title="Coming soon" description=""></RightContentSectionTitle>
|
||||
<RightContentTitle
|
||||
title={formatMessage(appMessages.languagesSectionTitle)}
|
||||
description={formatMessage(messages.rightSectionDescription)}
|
||||
/>
|
||||
<RightContentSectionTitle
|
||||
title={formatMessage(appMessages.comingSoon)}
|
||||
description=""
|
||||
/>
|
||||
</Container>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
LanguagesPage.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(LanguagesPage);
|
||||
|
13
public/app/containers/LanguagesPage/messages.js
Normal file
13
public/app/containers/LanguagesPage/messages.js
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* LanguagesPage Messages
|
||||
*
|
||||
* This contains all the text for the LanguagesPage component.
|
||||
*/
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
||||
export default defineMessages({
|
||||
rightSectionDescription: {
|
||||
id: 'settings-manager.components.LanguagesPage.rightSectionDescription',
|
||||
defaultMessage: 'Configure your languages settings',
|
||||
},
|
||||
});
|
@ -8,27 +8,44 @@ import PluginHeader from 'components/PluginHeader';
|
||||
import Container from 'components/Container';
|
||||
import RightContentTitle from 'components/RightContentTitle';
|
||||
import RightContentSectionTitle from 'components/RightContentSectionTitle';
|
||||
import { injectIntl, intlShape } from 'react-intl';
|
||||
import appMessages from 'containers/App/messages';
|
||||
import messages from './messages';
|
||||
|
||||
import styles from './styles.scss';
|
||||
|
||||
export default class SecurityPage extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||
export class SecurityPage extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||
render() {
|
||||
const { formatMessage } = this.props.intl;
|
||||
|
||||
return (
|
||||
<div className={styles.securityPage}>
|
||||
<Helmet
|
||||
title="Settings Manager - Security"
|
||||
meta={[
|
||||
{ name: 'description', content: 'Configure your security settings.' },
|
||||
{ name: 'description', content: formatMessage(messages.rightSectionDescription) },
|
||||
]}
|
||||
/>
|
||||
<div className="container">
|
||||
<PluginHeader></PluginHeader>
|
||||
<PluginHeader />
|
||||
<Container>
|
||||
<RightContentTitle title="Security" description="Configure your security settings."></RightContentTitle>
|
||||
<RightContentSectionTitle title="Coming soon" description=""></RightContentSectionTitle>
|
||||
<RightContentTitle
|
||||
title={formatMessage(appMessages.securitySectionTitle)}
|
||||
description={formatMessage(messages.rightSectionDescription)}
|
||||
/>
|
||||
<RightContentSectionTitle
|
||||
title={formatMessage(appMessages.comingSoon)}
|
||||
description=""
|
||||
/>
|
||||
</Container>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SecurityPage.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(SecurityPage);
|
||||
|
13
public/app/containers/SecurityPage/messages.js
Normal file
13
public/app/containers/SecurityPage/messages.js
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* LanguagesPage Messages
|
||||
*
|
||||
* This contains all the text for the LanguagesPage component.
|
||||
*/
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
||||
export default defineMessages({
|
||||
rightSectionDescription: {
|
||||
id: 'settings-manager.components.SecurityPage.rightSectionDescription',
|
||||
defaultMessage: 'Configure your security settings',
|
||||
},
|
||||
});
|
@ -8,27 +8,44 @@ import PluginHeader from 'components/PluginHeader';
|
||||
import Container from 'components/Container';
|
||||
import RightContentTitle from 'components/RightContentTitle';
|
||||
import RightContentSectionTitle from 'components/RightContentSectionTitle';
|
||||
import { injectIntl, intlShape } from 'react-intl';
|
||||
import appMessages from 'containers/App/messages';
|
||||
import messages from './messages';
|
||||
|
||||
import styles from './styles.scss';
|
||||
|
||||
export default class ServerPage extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||
export class ServerPage extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||
render() {
|
||||
const { formatMessage } = this.props.intl;
|
||||
|
||||
return (
|
||||
<div className={styles.serverPage}>
|
||||
<Helmet
|
||||
title="Settings Manager - Server"
|
||||
meta={[
|
||||
{ name: 'description', content: 'Configure your Server settings.' },
|
||||
{ name: 'description', content: formatMessage(messages.rightSectionDescription) },
|
||||
]}
|
||||
/>
|
||||
<div className="container">
|
||||
<PluginHeader></PluginHeader>
|
||||
<PluginHeader />
|
||||
<Container>
|
||||
<RightContentTitle title="Server" description="Configure your server settings."></RightContentTitle>
|
||||
<RightContentSectionTitle title="Coming soon" description=""></RightContentSectionTitle>
|
||||
<RightContentTitle
|
||||
title={formatMessage(appMessages.serverSectionTitle)}
|
||||
description={formatMessage(messages.rightSectionDescription)}
|
||||
/>
|
||||
<RightContentSectionTitle
|
||||
title={formatMessage(appMessages.comingSoon)}
|
||||
description=""
|
||||
/>
|
||||
</Container>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ServerPage.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(ServerPage);
|
||||
|
13
public/app/containers/ServerPage/messages.js
Normal file
13
public/app/containers/ServerPage/messages.js
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* LanguagesPage Messages
|
||||
*
|
||||
* This contains all the text for the LanguagesPage component.
|
||||
*/
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
||||
export default defineMessages({
|
||||
rightSectionDescription: {
|
||||
id: 'settings-manager.components.ServerPage.rightSectionDescription',
|
||||
defaultMessage: 'Configure your server settings',
|
||||
},
|
||||
});
|
@ -4,17 +4,22 @@
|
||||
* This will setup the i18n language files and locale data for your plugin.
|
||||
*
|
||||
*/
|
||||
import { addLocaleData } from 'react-intl';
|
||||
// import { addLocaleData } from 'react-intl';
|
||||
|
||||
import enLocaleData from 'react-intl/locale-data/en';
|
||||
// import enLocaleData from 'react-intl/locale-data/en';
|
||||
// import frLocaleData from 'react-intl/locale-data/fr';
|
||||
|
||||
export const appLocales = [
|
||||
'en',
|
||||
];
|
||||
// export const appLocales = [
|
||||
// 'en',
|
||||
// 'fr',
|
||||
//
|
||||
// ];
|
||||
|
||||
import enTranslationMessages from './translations/en.json';
|
||||
import frTranslationMessages from './translations/fr.json';
|
||||
|
||||
addLocaleData(enLocaleData);
|
||||
// addLocaleData(enLocaleData);
|
||||
// addLocaleData(frLocaleData);
|
||||
|
||||
const formatTranslationMessages = (messages) => {
|
||||
const formattedMessages = {};
|
||||
@ -27,4 +32,5 @@ const formatTranslationMessages = (messages) => {
|
||||
|
||||
export const translationMessages = {
|
||||
en: formatTranslationMessages(enTranslationMessages),
|
||||
fr: formatTranslationMessages(frTranslationMessages),
|
||||
};
|
||||
|
@ -1,2 +1,2 @@
|
||||
// Import variables
|
||||
@import "variables/variables";
|
||||
@import 'variables/variables';
|
||||
|
@ -1 +1,16 @@
|
||||
[]
|
||||
[
|
||||
{
|
||||
"id": "app.components.DatabasesPage.header",
|
||||
"defaultMessage": "This is the Databases page of the Settings Manager plugin!",
|
||||
"message": ""
|
||||
},
|
||||
{
|
||||
"id": "app.components.NotFoundPage.pageNotFound",
|
||||
"defaultMessage": "Page not found.",
|
||||
"message": ""
|
||||
},
|
||||
{
|
||||
"id": "settings-manager.components.HomePage.header",
|
||||
"defaultMessage": "This is HomePage components !"
|
||||
}
|
||||
]
|
||||
|
16
public/app/translations/fr.json
Normal file
16
public/app/translations/fr.json
Normal file
@ -0,0 +1,16 @@
|
||||
[
|
||||
{
|
||||
"id": "app.components.DatabasesPage.header",
|
||||
"defaultMessage": "This is the Databases page of the Settings Manager plugin!",
|
||||
"message": ""
|
||||
},
|
||||
{
|
||||
"id": "app.components.NotFoundPage.pageNotFound",
|
||||
"defaultMessage": "Page not found.",
|
||||
"message": ""
|
||||
},
|
||||
{
|
||||
"id": "settings-manager.components.HomePage.header",
|
||||
"defaultMessage": "Ceci est la page d'accueil!"
|
||||
}
|
||||
]
|
@ -11,7 +11,7 @@ import { FormattedMessage } from 'react-intl';
|
||||
import messages from './messages';
|
||||
{{/if}}
|
||||
{{#if wantCSS}}
|
||||
import styles from './styles.scss';
|
||||
import styles from './styles.css';
|
||||
{{/if}}
|
||||
|
||||
class {{ properCase name }} extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||
|
@ -49,12 +49,12 @@ module.exports = {
|
||||
abortOnFail: true,
|
||||
}];
|
||||
|
||||
// If they want a CSS file, add styles.scss
|
||||
// If they want a CSS file, add styles.css
|
||||
if (data.wantCSS) {
|
||||
actions.push({
|
||||
type: 'add',
|
||||
path: '../../app/components/{{properCase name}}/styles.scss',
|
||||
templateFile: './component/styles.scss.hbs',
|
||||
path: '../../app/components/{{properCase name}}/styles.css',
|
||||
templateFile: './component/styles.css.hbs',
|
||||
abortOnFail: true,
|
||||
});
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import messages from './messages';
|
||||
{{/if}}
|
||||
|
||||
{{#if wantCSS}}
|
||||
import styles from './styles.scss';
|
||||
import styles from './styles.css';
|
||||
{{/if}}
|
||||
|
||||
function {{ properCase name }}() {
|
||||
|
@ -58,12 +58,12 @@ module.exports = {
|
||||
abortOnFail: true,
|
||||
}];
|
||||
|
||||
// If they want a CSS file, add styles.scss
|
||||
// If they want a CSS file, add styles.css
|
||||
if (data.wantCSS) {
|
||||
actions.push({
|
||||
type: 'add',
|
||||
path: '../../app/containers/{{properCase name}}/styles.scss',
|
||||
templateFile: './container/styles.scss.hbs',
|
||||
path: '../../app/containers/{{properCase name}}/styles.css',
|
||||
templateFile: './container/styles.css.hbs',
|
||||
abortOnFail: true,
|
||||
});
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import { FormattedMessage } from 'react-intl';
|
||||
import messages from './messages';
|
||||
{{/if}}
|
||||
{{#if wantCSS}}
|
||||
import styles from './styles.scss';
|
||||
import styles from './styles.css';
|
||||
{{/if}}
|
||||
|
||||
export class {{ properCase name }} extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||
|
@ -8,11 +8,13 @@ const fs = require('fs');
|
||||
const componentGenerator = require('./component/index.js');
|
||||
const containerGenerator = require('./container/index.js');
|
||||
const routeGenerator = require('./route/index.js');
|
||||
const languageGenerator = require('./language/index.js');
|
||||
|
||||
module.exports = (plop) => {
|
||||
plop.setGenerator('component', componentGenerator);
|
||||
plop.setGenerator('container', containerGenerator);
|
||||
plop.setGenerator('route', routeGenerator);
|
||||
plop.setGenerator('language', languageGenerator);
|
||||
plop.addHelper('directory', (comp) => {
|
||||
try {
|
||||
fs.accessSync(`app/containers/${comp}`, fs.F_OK);
|
||||
|
1
public/internals/generators/language/add-locale-data.hbs
Normal file
1
public/internals/generators/language/add-locale-data.hbs
Normal file
@ -0,0 +1 @@
|
||||
$1addLocaleData({{language}}LocaleData);
|
2
public/internals/generators/language/app-locale.hbs
Normal file
2
public/internals/generators/language/app-locale.hbs
Normal file
@ -0,0 +1,2 @@
|
||||
$1
|
||||
'{{language}}',
|
@ -0,0 +1 @@
|
||||
$1 {{language}}: formatTranslationMessages({{language}}TranslationMessages),
|
80
public/internals/generators/language/index.js
Normal file
80
public/internals/generators/language/index.js
Normal file
@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Language Generator
|
||||
*/
|
||||
const exec = require('child_process').exec;
|
||||
|
||||
module.exports = {
|
||||
description: 'Add a langauge',
|
||||
prompts: [{
|
||||
type: 'input',
|
||||
name: 'language',
|
||||
message: 'What is the language you want to add i18n support for (e.g. "fr", "de")?',
|
||||
default: 'fr',
|
||||
validate: value => {
|
||||
if ((/.+/).test(value) && value.length === 2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return '2 character language specifier is required';
|
||||
},
|
||||
}],
|
||||
|
||||
actions: () => {
|
||||
const actions = [];
|
||||
actions.push({
|
||||
type: 'modify',
|
||||
path: '../../app/i18n.js',
|
||||
pattern: /('react-intl\/locale-data\/[a-z]+';\n)(?!.*'react-intl\/locale-data\/[a-z]+';)/g,
|
||||
templateFile: './language/intl-locale-data.hbs',
|
||||
});
|
||||
actions.push({
|
||||
type: 'modify',
|
||||
path: '../../app/i18n.js',
|
||||
pattern: /([\n\s'[a-z]+',)(?!.*[\n\s'[a-z]+',)/g,
|
||||
templateFile: './language/app-locale.hbs',
|
||||
});
|
||||
actions.push({
|
||||
type: 'modify',
|
||||
path: '../../app/i18n.js',
|
||||
pattern: /(from\s'.\/translations\/[a-z]+.json';\n)(?!.*from\s'.\/translations\/[a-z]+.json';)/g,
|
||||
templateFile: './language/translation-messages.hbs',
|
||||
});
|
||||
actions.push({
|
||||
type: 'modify',
|
||||
path: '../../app/i18n.js',
|
||||
pattern: /(addLocaleData\([a-z]+LocaleData\);\n)(?!.*addLocaleData\([a-z]+LocaleData\);)/g,
|
||||
templateFile: './language/add-locale-data.hbs',
|
||||
});
|
||||
actions.push({
|
||||
type: 'modify',
|
||||
path: '../../app/i18n.js',
|
||||
pattern: /([a-z]+:\sformatTranslationMessages\([a-z]+TranslationMessages\),\n)(?!.*[a-z]+:\sformatTranslationMessages\([a-z]+TranslationMessages\),)/g,
|
||||
templateFile: './language/format-translation-messages.hbs',
|
||||
});
|
||||
actions.push({
|
||||
type: 'add',
|
||||
path: '../../app/translations/{{language}}.json',
|
||||
templateFile: './language/translations-json.hbs',
|
||||
abortOnFail: true,
|
||||
});
|
||||
actions.push({
|
||||
type: 'modify',
|
||||
path: '../../app/app.js',
|
||||
pattern: /(System\.import\('intl\/locale-data\/jsonp\/[a-z]+\.js'\),\n)(?!.*System\.import\('intl\/locale-data\/jsonp\/[a-z]+\.js'\),)/g,
|
||||
templateFile: './language/polyfill-intl-locale.hbs',
|
||||
});
|
||||
actions.push(
|
||||
() => {
|
||||
const cmd = 'npm run extract-intl';
|
||||
exec(cmd, (err, result, stderr) => {
|
||||
if (err || stderr) {
|
||||
throw err || stderr;
|
||||
}
|
||||
process.stdout.write(result);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
return actions;
|
||||
},
|
||||
};
|
@ -0,0 +1 @@
|
||||
$1import {{language}}LocaleData from 'react-intl/locale-data/{{language}}';
|
@ -0,0 +1 @@
|
||||
$1 System.import('intl/locale-data/jsonp/{{language}}.js'),
|
@ -0,0 +1 @@
|
||||
$1import {{language}}TranslationMessages from './translations/{{language}}.json';
|
@ -0,0 +1 @@
|
||||
[]
|
@ -28,10 +28,10 @@
|
||||
"start:production": "npm run build && npm run start:prod",
|
||||
"start:prod": "cross-env NODE_ENV=production node server",
|
||||
"generate": "plop --plopfile internals/generators/index.js",
|
||||
"lint": "npm run lint:js && npm run lint:css",
|
||||
"lint": "npm run lint:js && npm run lint:scss",
|
||||
"lint:eslint": "eslint --ignore-path .gitignore --ignore-pattern internals/scripts",
|
||||
"lint:js": "npm run lint:eslint -- . ",
|
||||
"lint:css": "stylelint ./app/**/*.css",
|
||||
"lint:scss": "stylelint ./app/**/*.scss",
|
||||
"lint:staged": "lint-staged",
|
||||
"pretest": "npm run test:clean && npm run lint",
|
||||
"test:clean": "rimraf ./coverage",
|
||||
@ -44,7 +44,7 @@
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.js": "lint:eslint",
|
||||
"*.css": "stylelint"
|
||||
"*.scss": "stylelint"
|
||||
},
|
||||
"pre-commit": "lint:staged",
|
||||
"babel": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user