Skip to content

Commit

Permalink
feat(DeleteResource): Add wording & i18n (#1243)
Browse files Browse the repository at this point in the history
  • Loading branch information
romainseb committed Apr 11, 2018
1 parent a9c75f1 commit 52522ac
Show file tree
Hide file tree
Showing 11 changed files with 181 additions and 40 deletions.
19 changes: 19 additions & 0 deletions I18n.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,25 @@ e.g:
LIST_DISPLAY
HEADERBAR_GO_PORTAL

### Specific translation cases

In some cases, you want to add some html markup or style to your translations. For this case, you can use Trans component
https://react.i18next.com/components/trans-component.html

```jsx
import { Trans } from 'react-i18next';

<Trans i18nKey="DELETE_RESOURCE_MESSAGE">
Are you sure you want to remove the {{ resourceLabel: resourceInfo.resourceTypeLabel }}
<strong> {{ resourceName: resourceInfo.label }} </strong> ?
</Trans>
```
For this case, the translation json value is :
`Are you sure you want to remove the <1>{{ resourceLabel }}</1> <2><1>{{ resourceName }}</1></2>?`
More infos in the react-i18next's documentation
## Use i18n with UI in your App
### Create an instance of i18n
Expand Down
39 changes: 12 additions & 27 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,65 +25,50 @@
"build-storybook": "npm run test:demo && export ACTION='test:demo' && export TRAVIS_BRANCH='master' && export TRAVIS_BUILD_DIR=`pwd` && .travis/after_success_static.sh && .travis/after_success_demo.sh && .travis/after_success_coverage.sh",
"publish-storybook": "npm run build-storybook && cd .static && surge",
"changelog": "git log --pretty=\"format:%C(bold green)%ad%C(reset) %<(70,trunc)%s\" --date=short --color",
"extract-i18n": "npm run extract-i18n-components && npm run extract-i18n-forms",
"extract-i18n": "npm run extract-i18n-components && npm run extract-i18n-forms && npm run extract-i18n-containers",
"extract-i18n-components": "i18next packages/components/src -r --default-values -o i18n/components -n tui-components -l en --write-old false --fileFilter '*.js' --directoryFilter '!__snapshots__'",
"extract-i18n-forms": "i18next packages/forms/src -r --default-values -o i18n/forms -n tui-forms -l en --write-old false --fileFilter '*.js' --directoryFilter '!__snapshots__'"
"extract-i18n-forms": "i18next packages/forms/src -r --default-values -o i18n/forms -n tui-forms -l en --write-old false --fileFilter '*.js' --directoryFilter '!__snapshots__'",
"extract-i18n-containers": "i18next packages/containers/src -r --default-values -o i18n/containers -n tui-containers -l en --write-old false --fileFilter '*.js' --directoryFilter '!__snapshots__'"
},
"watch": {
"build-cmf": {
"patterns": [
"packages/cmf/src/**/*"
],
"patterns": ["packages/cmf/src/**/*"],
"extensions": "js"
},
"build-components": {
"patterns": [
"packages/components/src/**/*"
],
"patterns": ["packages/components/src/**/*"],
"extensions": "js,css,scss,svg"
},
"build-sagas": {
"patterns": [
"packages/sagas/src/**/*"
],
"patterns": ["packages/sagas/src/**/*"],
"extensions": "js"
},
"build-containers": {
"patterns": [
"packages/containers/src/**/*"
],
"patterns": ["packages/containers/src/**/*"],
"extensions": "js,css,scss,svg"
},
"build-forms": {
"patterns": [
"packages/forms/src/**/*"
],
"patterns": ["packages/forms/src/**/*"],
"extensions": "js,scss"
},
"build-icons": {
"patterns": [
"packages/icons/src/svg/*"
],
"patterns": ["packages/icons/src/svg/*"],
"extensions": "svg"
},
"build-logging": {
"patterns": [
"packages/logging/src/**/*"
],
"patterns": ["packages/logging/src/**/*"],
"extensions": "js"
},
"build-theme": {
"patterns": [
"packages/theme/src/**/*"
],
"patterns": ["packages/theme/src/**/*"],
"extensions": "css,scss"
}
},
"repository": {
"type": "git",
"url": "https://github.com/Talend/ui.git"
},
"engines" : { "node" : ">=8.10.0 <9.0.0" },
"engines": { "node": ">=8.10.0 <9.0.0" },
"version": "0.0.0",
"private": true,
"workspaces": [
Expand Down
22 changes: 19 additions & 3 deletions packages/containers/examples/ExampleDeleteResource.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import React from 'react';
import { I18nextProvider } from 'react-i18next';
import i18n, { LanguageSwitcher } from './config/i18n';
import { DeleteResource } from '../src';

/*
Expand Down Expand Up @@ -32,10 +34,12 @@ Also require two fields, uri it contains the uri to call and resourceType, the t
const views = {
uri: '/myEndpoint',
resourceType: 'myResourceType',
resourceTypeLabel: 'resource',
header: 'My header title',
'cancel-action': 'dialog:delete:cancel',
'validate-action': 'dialog:delete:validate',
routeParams: { id: 'myID' },
female: true,
};

const params = {
Expand All @@ -47,6 +51,18 @@ const props = {
params,
};

export default function ExampleAction() {
return <DeleteResource {...props} />;
}
export default {
default: () => (
<div>
<DeleteResource {...props} />;
</div>
),
translated: () => (
<I18nextProvider i18n={i18n}>
<div>
<LanguageSwitcher />
<DeleteResource {...props} />
</div>
</I18nextProvider>
),
};
50 changes: 49 additions & 1 deletion packages/containers/examples/config/i18n.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
import React from 'react';
import i18n from 'i18next';
import { I18N_DOMAIN_COMPONENTS } from '@talend/react-components';
import I18N_DOMAIN_CONTAINERS from '../../src/constant';

i18n.init({
lng: 'en',
resources: {
en: {
[I18N_DOMAIN_CONTAINERS]: {
DELETE_RESOURCE_MESSAGE:
'Are you sure you want to remove the <1>{{ resourceLabel }}</1> <2><1>{{ resourceName }}</1></2>?',
DELETE_RESOURCE_MESSAGE_female:
'Are you sure you want to remove the <1>{{ resourceLabel }}</1> <2><1>{{ resourceName }}</1></2>?',
},
},
fr: {
[I18N_DOMAIN_COMPONENTS]: {
LIST_TOOLBAR_DISPLAY: 'Affichage :',
Expand All @@ -17,6 +28,12 @@ i18n.init({
LIST_FILTER_REMOVE: 'Supprimer le filtre',
VIRTUALIZEDLIST_NO_RESULT: 'Pas de résultat',
},
[I18N_DOMAIN_CONTAINERS]: {
DELETE_RESOURCE_MESSAGE:
'Êtes-vous sûr(e) de vouloir supprimer le <1>{{ resourceLabel }}</1> <2><1>{{ resourceName }}</1></2> ?',
DELETE_RESOURCE_MESSAGE_female:
'Êtes-vous sûr(e) de vouloir supprimer la <1>{{ resourceLabel }}</1> <2><1>{{ resourceName }}</1></2> ?',
},
},
it: {
[I18N_DOMAIN_COMPONENTS]: {
Expand All @@ -32,10 +49,41 @@ i18n.init({
LIST_FILTER_REMOVE: 'Rimuova il filtro',
VIRTUALIZEDLIST_NO_RESULT: 'Nessun risultato',
},
[I18N_DOMAIN_CONTAINERS]: {
DELETE_RESOURCE_MESSAGE: 'Sei sicuro di voler eliminare {{resourceLabel}} ',
},
},
},
debug: false,
saveMissing: true,
debug: true,
wait: true, // globally set to wait for loaded translations in translate hoc
});

export const LanguageSwitcher = () => {
const style = {
position: 'fixed',
bottom: 0,
width: '100vw',
textAlign: 'center',
zIndex: 100000,
};

function renderBtn(locale, isDefault) {
return (
<button className="btn" onClick={() => i18n.changeLanguage(locale)}>
{locale} {isDefault && '(default)'}
</button>
);
}

return (
<nav style={style}>
<div className="btn-group">
{renderBtn('en', true)}
{renderBtn('fr')}
</div>
</nav>
);
};

export default i18n;
2 changes: 2 additions & 0 deletions packages/containers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,14 @@
"bson-objectid": "1.1.5",
"classnames": "2.2.5",
"immutable": "3.8.1",
"i18next": "^9.0.0",
"invariant": "2.2.2",
"keycode": "2.2.0",
"lodash": "4.17.4",
"prop-types": "15.5.10",
"react": "^15.6.2",
"react-bootstrap": "0.31.5",
"react-i18next": "^5.2.0",
"react-redux": "5.0.5",
"reselect": "^2.5.4"
},
Expand Down
25 changes: 23 additions & 2 deletions packages/containers/src/DeleteResource/DeleteResource.container.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ import React from 'react';
import PropTypes from 'prop-types';
import { componentState } from '@talend/react-cmf';
import { ConfirmDialog } from '@talend/react-components';
import { translate, Trans } from 'react-i18next';
import { getActionsProps } from '../actionAPI';
import deleteResourceConst from './deleteResource.constants';
import DEFAULT_I18N from '../translate';
import I18N_DOMAIN_CONTAINERS from '../constant';

/**
* DeleteResource is used to delete a specific resource.
* When the component is mounted, it opens a confirm dialog.
* It uses the saga matching pattern to launch a race between the cancel and validate action.
*/
export default class DeleteResource extends React.Component {
export class DeleteResource extends React.Component {
static displayName = 'Container(DeleteResource)';
static propTypes = {
...componentState.propTypes,
Expand All @@ -19,11 +22,16 @@ export default class DeleteResource extends React.Component {
header: PropTypes.string,
uri: PropTypes.string.isRequired,
resourceType: PropTypes.string.isRequired,
resourceTypeLabel: PropTypes.string,
female: PropTypes.string,
};
static contextTypes = {
registry: PropTypes.object.isRequired,
store: PropTypes.object.isRequired,
};
static defaultProps = {
t: DEFAULT_I18N.t.bind(DEFAULT_I18N),
};

constructor(props, context) {
super(props, context);
Expand All @@ -49,6 +57,9 @@ export default class DeleteResource extends React.Component {
getResourceInfo() {
return {
resourceType: this.props.resourceType,
resourceTypeLabel: this.props.resourceTypeLabel
? this.props.resourceTypeLabel
: this.props.resourceType,
uri: this.props.uri,
...this.getLabel(),
id: this.props.params.id,
Expand All @@ -70,15 +81,25 @@ export default class DeleteResource extends React.Component {
const resourceInfo = this.getResourceInfo();
const validateAction = this.getActions(deleteResourceConst.VALIDATE_ACTION, resourceInfo);
const cancelAction = this.getActions(deleteResourceConst.CANCEL_ACTION, resourceInfo);
const i18nKey = this.props.female
? 'DELETE_RESOURCE_MESSAGE_female'
: 'DELETE_RESOURCE_MESSAGE';
return (
<ConfirmDialog
show
header={this.props.header}
cancelAction={cancelAction}
validateAction={validateAction}
>
<div>{resourceInfo.label}</div>
<div>
<Trans i18nKey={i18nKey}>
Are you sure you want to remove the {{ resourceLabel: resourceInfo.resourceTypeLabel }}
<strong> {{ resourceName: resourceInfo.label }} </strong> ?
</Trans>
</div>
</ConfirmDialog>
);
}
}

export default translate(I18N_DOMAIN_CONTAINERS, { i18n: DEFAULT_I18N })(DeleteResource);
12 changes: 7 additions & 5 deletions packages/containers/src/DeleteResource/DeleteResource.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { shallow } from 'enzyme';
import { store } from '@talend/react-cmf/lib/mock';
import Immutable from 'immutable';

import Container from './DeleteResource.container';
import { DeleteResource } from './DeleteResource.container';
import Connected from './DeleteResource.connect';

const state = store.state();
Expand Down Expand Up @@ -40,10 +40,12 @@ describe('Container DeleteResource', () => {
resource: new Immutable.Map({ label: 'myLabel' }),
header: 'My header title',
params: { id: 'myResourceID' },
resourceTypeLabel: 'resourceLabel',
female: true,
'validate-action': 'dialog:delete:validate',
'cancel-action': 'dialog:delete:cancel',
};
const wrapper = shallow(<Container {...props} />, { context });
const wrapper = shallow(<DeleteResource {...props} />, { context });
expect(wrapper.getElement()).toMatchSnapshot();
});
it('should render with wrong resourceInfo params', () => {
Expand All @@ -55,14 +57,14 @@ describe('Container DeleteResource', () => {
'validate-action': 'dialog:delete:validate',
'cancel-action': 'dialog:delete:cancel',
};
const wrapper = shallow(<Container {...props} />, { context });
const wrapper = shallow(<DeleteResource {...props} />, { context });
expect(wrapper.getElement()).toMatchSnapshot();
});
});

describe('Connected DeleteResource', () => {
it('should connect TestGenerator', () => {
expect(Connected.displayName).toBe(`Connect(CMF(${Container.displayName}))`);
expect(Connected.WrappedComponent).toBe(Container);
expect(Connected.displayName).toBe('Connect(CMF(Translate(Container(DeleteResource))))');
expect(Connected.WrappedComponent).toBe(DeleteResource);
});
});
2 changes: 2 additions & 0 deletions packages/containers/src/DeleteResource/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,11 @@ Required :
* **redirectUrl** : is the url to redirect when delete is complete or cancel action is triggered

Optional :
* **resourceLabel** : is the parameter to show the type to remove if the resourceType is not readable by the user
* **routerParamAttribute** : is the attribute defined in the route to give the resource id
* **resourcePath** : array of string, is appended to resourceType key to deep location of a subset of a collection element
the delete service will use it to check if the resource exist in your application state tree
* **female** : Only for i18n, allow to set the i18nkey to tell of the resource type if female or not

example with resourceType only
```javascript
Expand Down
Loading

0 comments on commit 52522ac

Please sign in to comment.