Explorar el Código

added i18n for translation

Skylsmoi hace 7 años
padre
commit
a291aa3366

+ 2 - 0
jsonserver/server.js Ver fichero

39
 //   res.jsonp('gg')
39
 //   res.jsonp('gg')
40
 // })
40
 // })
41
 
41
 
42
+server.get('/lang', (req, res) => res.jsonp(jsonDb.lang))
43
+
42
 server.post('/user/login', (req, res) => {
44
 server.post('/user/login', (req, res) => {
43
   if (req.body.login !== '' && req.body.password !== '') return res.jsonp(jsonDb.user_logged)
45
   if (req.body.login !== '' && req.body.password !== '') return res.jsonp(jsonDb.user_logged)
44
   else return res.jsonp('error')
46
   else return res.jsonp('error')

+ 11 - 0
jsonserver/static_db.json Ver fichero

1
 {
1
 {
2
+  "lang": [{
3
+    "id": "fr",
4
+    "name": "Français",
5
+    "src": "https://upload.wikimedia.org/wikipedia/commons/c/c3/Flag_of_France.svg",
6
+    "active": true
7
+  }, {
8
+    "id": "en",
9
+    "name": "English",
10
+    "src": "https://upload.wikimedia.org/wikipedia/commons/a/ae/Flag_of_the_United_Kingdom.svg",
11
+    "active": false
12
+  }],
2
   "user_logged": {
13
   "user_logged": {
3
     "logged": true,
14
     "logged": true,
4
     "user": {
15
     "user": {

+ 2 - 0
package.json Ver fichero

26
     "classnames": "^2.2.5",
26
     "classnames": "^2.2.5",
27
     "css-loader": "^0.28.7",
27
     "css-loader": "^0.28.7",
28
     "file-loader": "^1.1.5",
28
     "file-loader": "^1.1.5",
29
+    "i18next": "^10.5.0",
29
     "prop-types": "^15.6.0",
30
     "prop-types": "^15.6.0",
30
     "react": "^16.0.0",
31
     "react": "^16.0.0",
31
     "react-animate-height": "^0.10.10",
32
     "react-animate-height": "^0.10.10",
32
     "react-dom": "^16.0.0",
33
     "react-dom": "^16.0.0",
34
+    "react-i18next": "^7.4.0",
33
     "react-redux": "^5.0.6",
35
     "react-redux": "^5.0.6",
34
     "react-router-dom": "^4.2.2",
36
     "react-router-dom": "^4.2.2",
35
     "redux": "^3.7.2",
37
     "redux": "^3.7.2",

+ 13 - 1
src/action-creator.async.js Ver fichero

1
 import { FETCH_CONFIG } from './helper.js'
1
 import { FETCH_CONFIG } from './helper.js'
2
 import {
2
 import {
3
+  LANG,
4
+  updateLangList,
3
   USER_LOGIN,
5
   USER_LOGIN,
4
   USER_DATA,
6
   USER_DATA,
5
   USER_CONNECTED,
7
   USER_CONNECTED,
59
   return fetchResult
61
   return fetchResult
60
 }
62
 }
61
 
63
 
64
+export const getLangList = () => async dispatch => {
65
+  const fetchGetLangList = await fetchWrapper({
66
+    url: `${FETCH_CONFIG.apiUrl}/lang`,
67
+    param: {...FETCH_CONFIG.header, method: 'GET'},
68
+    actionName: LANG,
69
+    dispatch
70
+  })
71
+  if (fetchGetLangList.status === 200) dispatch(updateLangList(fetchGetLangList.json))
72
+}
73
+
62
 export const userLogin = (login, password, rememberMe) => async dispatch => {
74
 export const userLogin = (login, password, rememberMe) => async dispatch => {
63
   const fetchUserLogin = await fetchWrapper({
75
   const fetchUserLogin = await fetchWrapper({
64
     url: `${FETCH_CONFIG.apiUrl}/user/login`,
76
     url: `${FETCH_CONFIG.apiUrl}/user/login`,
87
   if (fetchUserLogged.status === 200) dispatch(updateUserConnected(fetchUserLogged.json))
99
   if (fetchUserLogged.status === 200) dispatch(updateUserConnected(fetchUserLogged.json))
88
 }
100
 }
89
 
101
 
90
-export const updateUserLang = newLang => async dispatch => {
102
+export const updateUserLang = newLang => async dispatch => { // unused
91
   const fetchUpdateUserLang = await fetchWrapper({
103
   const fetchUpdateUserLang = await fetchWrapper({
92
     url: `${FETCH_CONFIG.apiUrl}/user`,
104
     url: `${FETCH_CONFIG.apiUrl}/user`,
93
     param: {...FETCH_CONFIG.header, method: 'PATCH', body: JSON.stringify({lang: newLang})},
105
     param: {...FETCH_CONFIG.header, method: 'PATCH', body: JSON.stringify({lang: newLang})},

+ 5 - 1
src/action-creator.sync.js Ver fichero

10
 
10
 
11
 export const WORKSPACE_LIST = 'WorkspaceList'
11
 export const WORKSPACE_LIST = 'WorkspaceList'
12
 export const updateWorkspaceListData = workspaceList => ({ type: `Update/${WORKSPACE_LIST}`, workspaceList })
12
 export const updateWorkspaceListData = workspaceList => ({ type: `Update/${WORKSPACE_LIST}`, workspaceList })
13
-export const updateWorkspaceListIsOpen = (workspaceId, isOpen) => ({ type: `Update/${WORKSPACE_LIST}/isOpen`, workspaceId, isOpen })
13
+export const setWorkspaceListIsOpen = (workspaceId, isOpen) => ({ type: `Set/${WORKSPACE_LIST}/isOpen`, workspaceId, isOpen })
14
 
14
 
15
 export const FILE_CONTENT = 'FileContent'
15
 export const FILE_CONTENT = 'FileContent'
16
 export const setActiveFileContent = file => ({ type: `Set/${FILE_CONTENT}/Active`, file })
16
 export const setActiveFileContent = file => ({ type: `Set/${FILE_CONTENT}/Active`, file })
18
 
18
 
19
 export const APP_LIST = 'App/List'
19
 export const APP_LIST = 'App/List'
20
 export const setAppList = appList => ({ type: `Set/${APP_LIST}`, appList })
20
 export const setAppList = appList => ({ type: `Set/${APP_LIST}`, appList })
21
+
22
+export const LANG = 'Lang'
23
+export const updateLangList = langList => ({ type: `Update/${LANG}`, langList })
24
+export const setLangActive = langId => ({ type: `Set/${LANG}/Active`, langId })

+ 1 - 2
src/component/Header/MenuActionListItem/DropdownLang.jsx Ver fichero

1
 import React from 'react'
1
 import React from 'react'
2
 import PropTypes from 'prop-types'
2
 import PropTypes from 'prop-types'
3
-import flagFr from '../../../img/flagFr.png' // for default lang
4
 
3
 
5
 const DropdownLang = props => {
4
 const DropdownLang = props => {
6
-  const activeLang = props.langList.find(l => l.active) || {id: 'fr', name: 'Français', src: flagFr, active: true}
5
+  const activeLang = props.langList.find(l => l.active) || {id: 'fr', name: 'Français', src: '', active: true}
7
   return (
6
   return (
8
     <li className='header__menu__rightside__itemlanguage'>
7
     <li className='header__menu__rightside__itemlanguage'>
9
       <div className='header__menu__rightside__itemlanguage__languagedropdown dropdown'>
8
       <div className='header__menu__rightside__itemlanguage__languagedropdown dropdown'>

+ 3 - 2
src/component/Header/MenuActionListItem/Search.jsx Ver fichero

1
 import React from 'react'
1
 import React from 'react'
2
 import PropTypes from 'prop-types'
2
 import PropTypes from 'prop-types'
3
+import { translate } from 'react-i18next'
3
 
4
 
4
 const Search = props => {
5
 const Search = props => {
5
   return (
6
   return (
8
         <input
9
         <input
9
           type='text'
10
           type='text'
10
           className='search__input form-control'
11
           className='search__input form-control'
11
-          placeholder='Rechercher un dossier ..'
12
+          placeholder={`${props.t('Header.Search')}...`}
12
           aria-describedby='headerInputSearch'
13
           aria-describedby='headerInputSearch'
13
           onChange={props.onChangeInput}
14
           onChange={props.onChangeInput}
14
         />
15
         />
23
     </li>
24
     </li>
24
   )
25
   )
25
 }
26
 }
26
-export default Search
27
+export default translate()(Search)
27
 
28
 
28
 Search.propTypes = {
29
 Search.propTypes = {
29
   onChangeInput: PropTypes.func.isRequired,
30
   onChangeInput: PropTypes.func.isRequired,

+ 4 - 3
src/component/Workspace/FileItemHeader.jsx Ver fichero

1
 import React from 'react'
1
 import React from 'react'
2
+import { translate } from 'react-i18next'
2
 
3
 
3
 const FileItemHeader = props => {
4
 const FileItemHeader = props => {
4
   return (
5
   return (
10
       </div>
11
       </div>
11
       <div className='col-8 col-sm-8 col-md-8 col-lg-8 col-xl-10'>
12
       <div className='col-8 col-sm-8 col-md-8 col-lg-8 col-xl-10'>
12
         <div className='file__header__name'>
13
         <div className='file__header__name'>
13
-          Nom du document ou fichier
14
+          {props.t('FileItemHeader.document_name')}
14
         </div>
15
         </div>
15
       </div>
16
       </div>
16
       <div className='col-2 col-sm-2 col-md-2 col-lg-2 col-xl-1'>
17
       <div className='col-2 col-sm-2 col-md-2 col-lg-2 col-xl-1'>
17
         <div className='file__header__status'>
18
         <div className='file__header__status'>
18
-          Statut
19
+          {props.t('FileItemHeader.status')}
19
         </div>
20
         </div>
20
       </div>
21
       </div>
21
     </div>
22
     </div>
22
   )
23
   )
23
 }
24
 }
24
 
25
 
25
-export default FileItemHeader
26
+export default translate()(FileItemHeader)

+ 7 - 6
src/component/Workspace/Folder.jsx Ver fichero

1
-import React, { Component } from 'react'
1
+import React from 'react'
2
+import { translate } from 'react-i18next'
2
 import PropTypes from 'prop-types'
3
 import PropTypes from 'prop-types'
3
 import classnames from 'classnames'
4
 import classnames from 'classnames'
4
 import FileItem from './FileItem.jsx'
5
 import FileItem from './FileItem.jsx'
5
 
6
 
6
 // @TODO set Folder as a component, state open will come from parent container (which will come from redux) // update: or not ?
7
 // @TODO set Folder as a component, state open will come from parent container (which will come from redux) // update: or not ?
7
 
8
 
8
-class Folder extends Component {
9
+class Folder extends React.Component {
9
   constructor (props) {
10
   constructor (props) {
10
     super(props)
11
     super(props)
11
     this.state = {
12
     this.state = {
12
       open: false
13
       open: false
13
     }
14
     }
14
-    this.handleClickToggleFolder = this.handleClickToggleFolder.bind(this)
15
   }
15
   }
16
 
16
 
17
   handleClickToggleFolder = () => this.setState({open: !this.state.open})
17
   handleClickToggleFolder = () => this.setState({open: !this.state.open})
18
+
18
   handleClickNewFile = e => {
19
   handleClickNewFile = e => {
19
     e.stopPropagation() // because we have a link inside a link (togler and newFile)
20
     e.stopPropagation() // because we have a link inside a link (togler and newFile)
20
     console.log('new file') // @TODO
21
     console.log('new file') // @TODO
21
   }
22
   }
22
 
23
 
23
   render () {
24
   render () {
24
-    const { app, folderData: { title, content }, isLast } = this.props
25
+    const { app, folderData: { title, content }, isLast, t } = this.props
25
     return (
26
     return (
26
       <div className={classnames('folder', {'active': this.state.open, 'item-last': isLast})}>
27
       <div className={classnames('folder', {'active': this.state.open, 'item-last': isLast})}>
27
         <div className='folder__header' onClick={this.handleClickToggleFolder}>
28
         <div className='folder__header' onClick={this.handleClickToggleFolder}>
37
             </div>
38
             </div>
38
             <div className='folder__header__name__addbtn' onClick={this.handleClickNewFile}>
39
             <div className='folder__header__name__addbtn' onClick={this.handleClickNewFile}>
39
               <div className='folder__header__name__addbtn__text btn btn-primary'>
40
               <div className='folder__header__name__addbtn__text btn btn-primary'>
40
-                créer ...
41
+                {t('Folder.create')} ...
41
               </div>
42
               </div>
42
             </div>
43
             </div>
43
           </div>
44
           </div>
72
   }
73
   }
73
 }
74
 }
74
 
75
 
75
-export default Folder
76
+export default translate()(Folder)
76
 
77
 
77
 Folder.propTypes = {
78
 Folder.propTypes = {
78
   folderData: PropTypes.shape({
79
   folderData: PropTypes.shape({

+ 12 - 27
src/container/Header.jsx Ver fichero

1
 import React from 'react'
1
 import React from 'react'
2
 import { connect } from 'react-redux'
2
 import { connect } from 'react-redux'
3
+import i18n from '../i18n.js'
3
 import Logo from '../component/Header/Logo.jsx'
4
 import Logo from '../component/Header/Logo.jsx'
4
 import NavbarToggler from '../component/Header/NavbarToggler.jsx'
5
 import NavbarToggler from '../component/Header/NavbarToggler.jsx'
5
 import MenuLinkList from '../component/Header/MenuLinkList.jsx'
6
 import MenuLinkList from '../component/Header/MenuLinkList.jsx'
9
 import MenuActionListItemHelp from '../component/Header/MenuActionListItem/Help.jsx'
10
 import MenuActionListItemHelp from '../component/Header/MenuActionListItem/Help.jsx'
10
 import MenuActionListItemMenuProfil from '../component/Header/MenuActionListItem/MenuProfil.jsx'
11
 import MenuActionListItemMenuProfil from '../component/Header/MenuActionListItem/MenuProfil.jsx'
11
 import logoHeader from '../img/logoHeader.svg'
12
 import logoHeader from '../img/logoHeader.svg'
12
-import flagFr from '../img/flagFr.png'
13
-import flagEn from '../img/flagEn.png'
14
-// import { updateUserLang } from '../action-creator.async.js'
13
+import { setLangActive } from '../action-creator.sync.js'
15
 
14
 
16
 class Header extends React.Component {
15
 class Header extends React.Component {
17
-  // handleChangeLang = newLang => this.props.dispatch(updateUserLang(newLang))
18
-  // handleSubmitSearch = search => console.log('search submited : ', search)
19
-
20
   handleClickLogo = () => {}
16
   handleClickLogo = () => {}
21
 
17
 
22
   handleClickFeature = () => {}
18
   handleClickFeature = () => {}
26
   handleChangeInput = e => this.setState({inputSearchValue: e.target.value})
22
   handleChangeInput = e => this.setState({inputSearchValue: e.target.value})
27
   handleClickSubmit = () => {}
23
   handleClickSubmit = () => {}
28
 
24
 
29
-  handleChangeLang = langId => {}
25
+  handleChangeLang = langId => {
26
+    this.props.dispatch(setLangActive(langId))
27
+    i18n.changeLanguage(langId)
28
+  }
30
 
29
 
31
   handleClickHelp = () => {}
30
   handleClickHelp = () => {}
32
 
31
 
34
   handleClickLogout = () => {}
33
   handleClickLogout = () => {}
35
 
34
 
36
   render () {
35
   render () {
37
-    const { user } = this.props
38
-    const langList = [{ // @TODO this should come from API
39
-      id: 'fr',
40
-      name: 'Français',
41
-      src: flagFr,
42
-      active: true
43
-    }, {
44
-      id: 'en',
45
-      name: 'English',
46
-      src: flagEn,
47
-      active: false
48
-    }]
49
-    // const userLogged = {
50
-    //   name: 'MrLapin',
51
-    //   avatar: 'https://photos-5.dropbox.com/t/2/AABmH38-9J0wawQdkSbEd757WfRA411L4h1eGtK0MLbWhA/' +
52
-    //   '12/14775898/png/32x32/1/_/1/2/avatar.png/ELyA_woY8SUgBygH/f3VzTEnU5OWqjkWwGyHOrJA2vYQKb3j' +
53
-    //   'S_zkvxpAJO0g?size=800x600&size_mode=3'
54
-    // }
36
+    const { lang, user } = this.props
55
 
37
 
56
     const HeaderWrapper = props => <header><nav className='header navbar navbar-expand-md navbar-light bg-light'>{props.children}</nav></header>
38
     const HeaderWrapper = props => <header><nav className='header navbar navbar-expand-md navbar-light bg-light'>{props.children}</nav></header>
57
     const HeaderMenuRightWrapper = props => <div className='header__menu collapse navbar-collapse justify-content-end' id='navbarSupportedContent'>{props.children}</div>
39
     const HeaderMenuRightWrapper = props => <div className='header__menu collapse navbar-collapse justify-content-end' id='navbarSupportedContent'>{props.children}</div>
58
     const MenuActionListWrapper = props => <ul className='header__menu__rightside'>{ props.children }</ul>
40
     const MenuActionListWrapper = props => <ul className='header__menu__rightside'>{ props.children }</ul>
41
+
59
     return (
42
     return (
60
       <HeaderWrapper>
43
       <HeaderWrapper>
61
         <Logo logoSrc={logoHeader} onClickImg={this.handleClickLogo} />
44
         <Logo logoSrc={logoHeader} onClickImg={this.handleClickLogo} />
73
               onClickSubmit={this.handleClickSubmit}
56
               onClickSubmit={this.handleClickSubmit}
74
             />
57
             />
75
             <MenuActionListItemDropdownLang
58
             <MenuActionListItemDropdownLang
76
-              langList={langList}
59
+              langList={lang}
77
               onChangeLang={this.handleChangeLang}
60
               onChangeLang={this.handleChangeLang}
78
             />
61
             />
79
             <MenuActionListItemHelp
62
             <MenuActionListItemHelp
90
     )
73
     )
91
   }
74
   }
92
 }
75
 }
93
-export default connect(({ user }) => ({ user }))(Header)
76
+
77
+const mapStateToProps = ({ lang, user }) => ({ lang, user })
78
+export default connect(mapStateToProps)(Header)

+ 2 - 2
src/container/Sidebar.jsx Ver fichero

3
 import { withRouter } from 'react-router'
3
 import { withRouter } from 'react-router'
4
 import WorkspaceListItem from '../component/Sidebar/WorkspaceListItem.jsx'
4
 import WorkspaceListItem from '../component/Sidebar/WorkspaceListItem.jsx'
5
 import { getWorkspaceList } from '../action-creator.async.js'
5
 import { getWorkspaceList } from '../action-creator.async.js'
6
-import { updateWorkspaceListIsOpen } from '../action-creator.sync.js'
6
+import { setWorkspaceListIsOpen } from '../action-creator.sync.js'
7
 import { PAGE_NAME } from '../helper.js'
7
 import { PAGE_NAME } from '../helper.js'
8
 
8
 
9
 class Sidebar extends React.Component {
9
 class Sidebar extends React.Component {
24
     user.id !== 0 && prevProps.user.id !== user.id && dispatch(getWorkspaceList(user.id))
24
     user.id !== 0 && prevProps.user.id !== user.id && dispatch(getWorkspaceList(user.id))
25
   }
25
   }
26
 
26
 
27
-  handleClickWorkspace = (wsId, newIsOpen) => this.props.dispatch(updateWorkspaceListIsOpen(wsId, newIsOpen))
27
+  handleClickWorkspace = (wsId, newIsOpen) => this.props.dispatch(setWorkspaceListIsOpen(wsId, newIsOpen))
28
 
28
 
29
   handleClickAllContent = wsId => {
29
   handleClickAllContent = wsId => {
30
     this.props.history.push(`${PAGE_NAME.WS_CONTENT}/${wsId}`)
30
     this.props.history.push(`${PAGE_NAME.WS_CONTENT}/${wsId}`)

+ 5 - 1
src/container/Tracim.jsx Ver fichero

14
 } from 'react-router-dom'
14
 } from 'react-router-dom'
15
 import PrivateRoute from './PrivateRoute.jsx'
15
 import PrivateRoute from './PrivateRoute.jsx'
16
 import { PAGE_NAME } from '../helper.js'
16
 import { PAGE_NAME } from '../helper.js'
17
-import { getIsUserConnected } from '../action-creator.async.js'
17
+import {
18
+  getLangList,
19
+  getIsUserConnected
20
+} from '../action-creator.async.js'
18
 
21
 
19
 class Tracim extends React.Component {
22
 class Tracim extends React.Component {
20
   componentDidMount = () => {
23
   componentDidMount = () => {
21
     this.props.dispatch(getIsUserConnected())
24
     this.props.dispatch(getIsUserConnected())
25
+    this.props.dispatch(getLangList())
22
   }
26
   }
23
 
27
 
24
   render () {
28
   render () {

+ 2 - 0
src/css/Header.styl Ver fichero

53
               padding 0
53
               padding 0
54
               min-width 0
54
               min-width 0
55
               .subdropdown
55
               .subdropdown
56
+                &__link
57
+                  cursor pointer
56
                 &__flag
58
                 &__flag
57
                   width 25px
59
                   width 25px
58
                   height 18px
60
                   height 18px

+ 26 - 0
src/i18n.js Ver fichero

1
+import i18n from 'i18next'
2
+import { reactI18nextModule } from 'react-i18next'
3
+import fr from './translate/fr.js'
4
+import en from './translate/en.js'
5
+
6
+i18n
7
+  .use(reactI18nextModule)
8
+  .init({
9
+    fallbackLng: 'fr',
10
+    // have a common namespace used around the full app
11
+    ns: ['translation'], // namespace
12
+    defaultNS: 'translation',
13
+    debug: true,
14
+    // interpolation: {
15
+    //   escapeValue: false, // not needed for react!!
16
+    // },
17
+    react: {
18
+      wait: true
19
+    },
20
+    resources: {
21
+      en,
22
+      fr
23
+    }
24
+  })
25
+
26
+export default i18n

BIN
src/img/flagEn.png Ver fichero


BIN
src/img/flagFr.png Ver fichero


+ 5 - 1
src/index.js Ver fichero

4
 import { store } from './store.js'
4
 import { store } from './store.js'
5
 import Tracim from './container/Tracim.jsx'
5
 import Tracim from './container/Tracim.jsx'
6
 import { BrowserRouter } from 'react-router-dom'
6
 import { BrowserRouter } from 'react-router-dom'
7
+import { I18nextProvider } from 'react-i18next'
8
+import i18n from './i18n.js'
7
 
9
 
8
 require('./css/index.styl')
10
 require('./css/index.styl')
9
 
11
 
10
 ReactDOM.render(
12
 ReactDOM.render(
11
   <Provider store={store}>
13
   <Provider store={store}>
12
     <BrowserRouter>
14
     <BrowserRouter>
13
-      <Tracim />
15
+      <I18nextProvider i18n={i18n}>
16
+        <Tracim />
17
+      </I18nextProvider>
14
     </BrowserRouter>
18
     </BrowserRouter>
15
   </Provider>
19
   </Provider>
16
   , document.getElementById('content')
20
   , document.getElementById('content')

+ 16 - 0
src/reducer/lang.js Ver fichero

1
+import { LANG } from '../action-creator.sync.js'
2
+
3
+export function lang (state = [], action) {
4
+  switch (action.type) {
5
+    case `Update/${LANG}`:
6
+      return action.langList
7
+
8
+    case `Set/${LANG}/Active`:
9
+      return state.map(l => ({...l, active: l.id === action.langId}))
10
+
11
+    default:
12
+      return state
13
+  }
14
+}
15
+
16
+export default lang

+ 2 - 1
src/reducer/root.js Ver fichero

1
 import { combineReducers } from 'redux'
1
 import { combineReducers } from 'redux'
2
+import lang from './lang.js'
2
 import user from './user.js'
3
 import user from './user.js'
3
 import workspace from './workspace.js'
4
 import workspace from './workspace.js'
4
 import workspaceList from './workspaceList.js'
5
 import workspaceList from './workspaceList.js'
5
 import activeFileContent from './activeFileContent.js'
6
 import activeFileContent from './activeFileContent.js'
6
 import app from './app.js'
7
 import app from './app.js'
7
 
8
 
8
-const rootReducer = combineReducers({ user, workspace, workspaceList, activeFileContent, app })
9
+const rootReducer = combineReducers({ lang, user, workspace, workspaceList, activeFileContent, app })
9
 
10
 
10
 export default rootReducer
11
 export default rootReducer

+ 1 - 1
src/reducer/workspaceList.js Ver fichero

10
         isOpen: false
10
         isOpen: false
11
       }))
11
       }))
12
 
12
 
13
-    case `Update/${WORKSPACE_LIST}/isOpen`:
13
+    case `Set/${WORKSPACE_LIST}/isOpen`:
14
       return state.map(ws => ws.id === action.workspaceId
14
       return state.map(ws => ws.id === action.workspaceId
15
         ? {...ws, isOpen: action.isOpen}
15
         ? {...ws, isOpen: action.isOpen}
16
         : ws
16
         : ws

+ 16 - 0
src/translate/en.js Ver fichero

1
+const en = {
2
+  translation: { // 'en' in the namespace 'translation'
3
+    Header: {
4
+      Search: 'Search'
5
+    },
6
+    FileItemHeader: {
7
+      document_name: "Document's name",
8
+      status: 'Status'
9
+    },
10
+    Folder: {
11
+      create: 'Create'
12
+    }
13
+  }
14
+}
15
+
16
+export default en

+ 16 - 0
src/translate/fr.js Ver fichero

1
+const fr = {
2
+  translation: { // 'fr' in the namespace 'translation'
3
+    Header: {
4
+      Search: 'Rechercher'
5
+    },
6
+    FileItemHeader: {
7
+      document_name: 'Nom du document',
8
+      status: 'Status'
9
+    },
10
+    Folder: {
11
+      create: 'Créer'
12
+    }
13
+  }
14
+}
15
+
16
+export default fr