Browse Source

[https://github.com/tracim/tracim/issues/637] added translation mecanism on all frontend folder

Skylsmoi 5 years ago
parent
commit
88b8d58176
42 changed files with 286 additions and 66 deletions
  1. 9 0
      build_full_frontend.sh
  2. 16 0
      frontend/i18next.scanner.js
  3. 13 0
      frontend/i18next.scanner/en/translation.json
  4. 13 0
      frontend/i18next.scanner/fr/translation.json
  5. 2 0
      frontend/package.json
  6. 5 1
      frontend/src/appFactory.js
  7. 1 1
      frontend/src/component/FlashMessage.jsx
  8. 1 1
      frontend/src/component/Footer.jsx
  9. 1 1
      frontend/src/component/Header/MenuActionListItem/Search.jsx
  10. 3 3
      frontend/src/component/Workspace/ContentItemHeader.jsx
  11. 1 1
      frontend/src/component/Workspace/Folder.jsx
  12. 1 1
      frontend/src/container/Header.jsx
  13. 1 1
      frontend/src/container/Login.jsx
  14. 1 1
      frontend/src/container/Sidebar.jsx
  15. 19 9
      frontend/src/i18n.js
  16. 17 0
      frontend_app_html-document/build_html-document.sh
  17. 14 0
      frontend_app_html-document/i18next.scanner.js
  18. 3 0
      frontend_app_html-document/i18next.scanner/en/translation.json
  19. 3 0
      frontend_app_html-document/i18next.scanner/fr/translation.json
  20. 3 1
      frontend_app_html-document/package.json
  21. 0 13
      frontend_app_html-document/rebuild_html-document.sh
  22. 10 4
      frontend_app_html-document/src/container/HtmlDocument.jsx
  23. 5 0
      frontend_app_html-document/src/container/PopupCreateHtmlDocument.jsx
  24. 13 1
      frontend_app_html-document/src/helper.js
  25. 1 11
      frontend_app_html-document/src/i18n.js
  26. 17 0
      frontend_app_thread/build_thread.sh
  27. 14 0
      frontend_app_thread/i18next.scanner.js
  28. 1 0
      frontend_app_thread/i18next.scanner/en/translation.json
  29. 1 0
      frontend_app_thread/i18next.scanner/fr/translation.json
  30. 2 0
      frontend_app_thread/package.json
  31. 0 13
      frontend_app_thread/rebuild_thread.sh
  32. 12 0
      frontend_app_thread/src/container/PopupCreateThread.jsx
  33. 4 0
      frontend_app_thread/src/container/Thread.jsx
  34. 9 0
      frontend_lib/i18next.scanner.js
  35. 3 0
      frontend_lib/i18next.scanner/en/translation.json
  36. 3 0
      frontend_lib/i18next.scanner/fr/translation.json
  37. 1 0
      frontend_lib/package.json
  38. 2 2
      frontend_lib/src/component/Input/SelectStatus/SelectStatus.jsx
  39. 8 0
      frontend_lib/src/helper.js
  40. 5 1
      frontend_lib/src/index.js
  41. 40 0
      i18next.option.js
  42. 8 0
      install_frontend_dependencies.sh

+ 9 - 0
build_full_frontend.sh View File

21
 npm run build$windoz
21
 npm run build$windoz
22
 log "cp dist/html-document.app.js"
22
 log "cp dist/html-document.app.js"
23
 cp dist/html-document.app.js ../frontend/dist/app
23
 cp dist/html-document.app.js ../frontend/dist/app
24
+log "cp i18next.scanner/en/translation.json ../frontend/dist/app/tml-document_en_translation.json"
25
+cp i18next.scanner/en/translation.json ../frontend/dist/app/html-document_en_translation.json
26
+log "cp i18next.scanner/fr/translation.json ../frontend/dist/app/html-document_fr_translation.json"
27
+cp i18next.scanner/fr/translation.json ../frontend/dist/app/html-document_fr_translation.json
24
 cd -
28
 cd -
25
 
29
 
26
 log "cd frontend_app_thread"
30
 log "cd frontend_app_thread"
29
 npm run build$windoz
33
 npm run build$windoz
30
 log "cp dist/thread.app.js"
34
 log "cp dist/thread.app.js"
31
 cp dist/thread.app.js ../frontend/dist/app
35
 cp dist/thread.app.js ../frontend/dist/app
36
+log "cp i18next.scanner/en/translation.json ../frontend/dist/app/thread_en_translation.json"
37
+cp i18next.scanner/en/translation.json ../frontend/dist/app/thread_en_translation.json
38
+log "cp i18next.scanner/fr/translation.json ../frontend/dist/app/thread_fr_translation.json"
39
+cp i18next.scanner/fr/translation.json ../frontend/dist/app/thread_fr_translation.json
40
+cd -

+ 16 - 0
frontend/i18next.scanner.js View File

1
+const scanner = require('i18next-scanner')
2
+const vfs = require('vinyl-fs')
3
+
4
+const option = require('../i18next.option.js')
5
+
6
+// this script is run by npm run build-translation and generate i18next.scanner/**/*.json
7
+
8
+// --------------------
9
+// 2018/07/27 - currently, last version is 2.6.5 but a bug is spaming log with errors. So I'm using 2.6.1
10
+// this issue seems related : https://github.com/i18next/i18next-scanner/issues/88
11
+// --------------------
12
+
13
+vfs.src(['./src/**/*.jsx'])
14
+  // .pipe(sort()) // Sort files in stream by path
15
+  .pipe(scanner(option))
16
+  .pipe(vfs.dest('./i18next.scanner'))

+ 13 - 0
frontend/i18next.scanner/en/translation.json View File

1
+{
2
+  "Create your own collaborative workspaces on trac.im": "Create your own collaborative workspaces on trac.im",
3
+  "Copyright 2013 - 2017": "Copyright 2013 - 2017",
4
+  "Disconnection error": "Disconnection error",
5
+  "Create new workspace": "Create new workspace",
6
+  "Error": "Error",
7
+  "Email or password invalid": "Email or password invalid",
8
+  "Type": "Type",
9
+  "Document's name": "Document's name",
10
+  "Status": "Status",
11
+  "Create in folder...": "Create in folder...",
12
+  "Search...": "Search..."
13
+}

+ 13 - 0
frontend/i18next.scanner/fr/translation.json View File

1
+{
2
+  "Create your own collaborative workspaces on trac.im": "Créer votre propre espace de travail sur trac.im",
3
+  "Copyright 2013 - 2017": "Copyright 2013 - 2017",
4
+  "Disconnection error": "Erreur de déconnexion",
5
+  "Create new workspace": "Créer un espace de travail",
6
+  "Error": "Erreur",
7
+  "Email or password invalid": "Email ou mot de passe invalid",
8
+  "Type": "Type",
9
+  "Document's name": "Nom du document",
10
+  "Status": "Statut",
11
+  "Create in folder...": "Créer dans le dossier ...",
12
+  "Search...": "Rechercher ..."
13
+}

+ 2 - 0
frontend/package.json View File

10
     "servdev-dashboard": "NODE_ENV=development webpack-dashboard -m -- webpack-dev-server --watch --colors --inline --hot --progress",
10
     "servdev-dashboard": "NODE_ENV=development webpack-dashboard -m -- webpack-dev-server --watch --colors --inline --hot --progress",
11
     "buildwindoz": "set NODE_ENV=production&& webpack -p",
11
     "buildwindoz": "set NODE_ENV=production&& webpack -p",
12
     "build": "NODE_ENV=production webpack -p",
12
     "build": "NODE_ENV=production webpack -p",
13
+    "build-translation": "node i18next.scanner.js",
13
     "test": "echo \"Error: no test specified\" && exit 1"
14
     "test": "echo \"Error: no test specified\" && exit 1"
14
   },
15
   },
15
   "author": "",
16
   "author": "",
52
     "whatwg-fetch": "^2.0.3"
53
     "whatwg-fetch": "^2.0.3"
53
   },
54
   },
54
   "devDependencies": {
55
   "devDependencies": {
56
+    "i18next-scanner": "^2.6.1",
55
     "json-server": "^0.12.0",
57
     "json-server": "^0.12.0",
56
     "webpack-dashboard": "^1.0.2",
58
     "webpack-dashboard": "^1.0.2",
57
     "webpack-dev-server": "^2.9.2"
59
     "webpack-dev-server": "^2.9.2"

+ 5 - 1
frontend/src/appFactory.js View File

1
 import React from 'react'
1
 import React from 'react'
2
 import { FETCH_CONFIG } from './helper.js'
2
 import { FETCH_CONFIG } from './helper.js'
3
+import i18n from './i18n.js'
4
+
5
+console.log('appFactory', i18n)
3
 
6
 
4
 export function appFactory (WrappedComponent) {
7
 export function appFactory (WrappedComponent) {
5
   return class AppFactory extends React.Component {
8
   return class AppFactory extends React.Component {
10
         domContainer: 'appContainer',
13
         domContainer: 'appContainer',
11
         apiUrl: FETCH_CONFIG.apiUrl,
14
         apiUrl: FETCH_CONFIG.apiUrl,
12
         mockApiUrl: FETCH_CONFIG.mockApiUrl,
15
         mockApiUrl: FETCH_CONFIG.mockApiUrl,
13
-        apiHeader: FETCH_CONFIG.headers
16
+        apiHeader: FETCH_CONFIG.headers,
17
+        translation: i18n.store.data
14
       },
18
       },
15
       content
19
       content
16
     })
20
     })

+ 1 - 1
frontend/src/component/FlashMessage.jsx View File

22
 
22
 
23
               <div className='flashmessage__container__content__text'>
23
               <div className='flashmessage__container__content__text'>
24
                 <div className='flashmessage__container__content__text__title'>
24
                 <div className='flashmessage__container__content__text__title'>
25
-                  {props.t('FlashMessage.error')}
25
+                  {props.t('Error')}
26
                 </div>
26
                 </div>
27
                 <div className='flashmessage__container__content__text__paragraph'>
27
                 <div className='flashmessage__container__content__text__paragraph'>
28
                   {props.flashMessage[0].message}
28
                   {props.flashMessage[0].message}

+ 1 - 1
frontend/src/component/Footer.jsx View File

7
   return (
7
   return (
8
     <footer className='footer text-right'>
8
     <footer className='footer text-right'>
9
       <div className='footer__text'>
9
       <div className='footer__text'>
10
-        {t('Footer.marketing_msg')} - {t('Footer.copyright')}
10
+        {t('Create your own collaborative workspaces on trac.im')} - {t('Copyright 2013 - 2017')}
11
       </div>
11
       </div>
12
       <img className='footer__logo' src={logoFooter} />
12
       <img className='footer__logo' src={logoFooter} />
13
     </footer>
13
     </footer>

+ 1 - 1
frontend/src/component/Header/MenuActionListItem/Search.jsx View File

9
         <input
9
         <input
10
           type='text'
10
           type='text'
11
           className='search__input form-control'
11
           className='search__input form-control'
12
-          placeholder={`${props.t('Header.Search')}...`}
12
+          placeholder={`${props.t('Search...')}`}
13
           aria-describedby='headerInputSearch'
13
           aria-describedby='headerInputSearch'
14
           onChange={props.onChangeInput}
14
           onChange={props.onChangeInput}
15
         />
15
         />

+ 3 - 3
frontend/src/component/Workspace/ContentItemHeader.jsx View File

5
   return (
5
   return (
6
     <div className='content__header'>
6
     <div className='content__header'>
7
       <div className='content__header__type'>
7
       <div className='content__header__type'>
8
-        {props.t('FileItemHeader.type')}
8
+        {props.t('Type')}
9
       </div>
9
       </div>
10
       <div className='content__header__name'>
10
       <div className='content__header__name'>
11
-        {props.t('FileItemHeader.document_name')}
11
+        {props.t("Document's name")}
12
       </div>
12
       </div>
13
       <div className='content__header__status'>
13
       <div className='content__header__status'>
14
-        {props.t('FileItemHeader.status')}
14
+        {props.t('Status')}
15
       </div>
15
       </div>
16
     </div>
16
     </div>
17
   )
17
   )

+ 1 - 1
frontend/src/component/Workspace/Folder.jsx View File

65
                 aria-expanded='false'
65
                 aria-expanded='false'
66
                 onClick={e => e.stopPropagation()}
66
                 onClick={e => e.stopPropagation()}
67
               >
67
               >
68
-                {t('Folder.create')} ...
68
+                {t('Create in folder...')}
69
               </button>
69
               </button>
70
 
70
 
71
               <div className='addbtn__subdropdown dropdown-menu' aria-labelledby='dropdownMenuButton'>
71
               <div className='addbtn__subdropdown dropdown-menu' aria-labelledby='dropdownMenuButton'>

+ 1 - 1
frontend/src/container/Header.jsx View File

49
 
49
 
50
       dispatch(setUserDisconnected())
50
       dispatch(setUserDisconnected())
51
     } else {
51
     } else {
52
-      dispatch(newFlashMessage(t('Login.logout_error', 'danger')))
52
+      dispatch(newFlashMessage(t('Disconnection error', 'danger')))
53
     }
53
     }
54
   }
54
   }
55
 
55
 

+ 1 - 1
frontend/src/container/Login.jsx View File

57
 
57
 
58
       history.push(PAGE.HOME)
58
       history.push(PAGE.HOME)
59
     } else if (fetchPostUserLogin.status === 400) {
59
     } else if (fetchPostUserLogin.status === 400) {
60
-      dispatch(newFlashMessage(t('Login.fail'), 'danger'))
60
+      dispatch(newFlashMessage(t('Email or password invalid'), 'danger'))
61
     }
61
     }
62
   }
62
   }
63
 
63
 

+ 1 - 1
frontend/src/container/Sidebar.jsx View File

86
 
86
 
87
             <div className='sidebar__btnnewworkspace'>
87
             <div className='sidebar__btnnewworkspace'>
88
               <button className='sidebar__btnnewworkspace__btn btn btn-primary primaryColorBg primaryColorBorder primaryColorBorderDarkenHover mb-5'>
88
               <button className='sidebar__btnnewworkspace__btn btn btn-primary primaryColorBg primaryColorBorder primaryColorBorderDarkenHover mb-5'>
89
-                {t('Sidebar.create_new_workspace')}
89
+                {t('Create new workspace')}
90
               </button>
90
               </button>
91
             </div>
91
             </div>
92
 
92
 

+ 19 - 9
frontend/src/i18n.js View File

1
 import i18n from 'i18next'
1
 import i18n from 'i18next'
2
 import { reactI18nextModule } from 'react-i18next'
2
 import { reactI18nextModule } from 'react-i18next'
3
-import { langFr, langEn } from 'tracim_frontend_lib'
4
-import fr from './translate/fr.js'
5
-import en from './translate/en.js'
3
+import { frLib, enLib } from 'tracim_frontend_lib'
4
+import en from '../i18next.scanner/en/translation.json'
5
+import fr from '../i18next.scanner/fr/translation.json'
6
+
7
+// get translation files of apps
8
+// theses files are generated by build_appname.sh
9
+const htmlDocEnTranslation = require('../dist/app/html-document_en_translation.json')
10
+const htmlDocFrTranslation = require('../dist/app/html-document_fr_translation.json')
6
 
11
 
7
 i18n
12
 i18n
8
   .use(reactI18nextModule)
13
   .use(reactI18nextModule)
9
   .init({
14
   .init({
10
-    fallbackLng: 'fr',
15
+    fallbackLng: 'en',
11
     // have a common namespace used around the full app
16
     // have a common namespace used around the full app
12
     ns: ['translation'], // namespace
17
     ns: ['translation'], // namespace
13
     defaultNS: 'translation',
18
     defaultNS: 'translation',
14
     debug: true,
19
     debug: true,
15
-    // interpolation: {
16
-    //   escapeValue: false, // not needed for react!!
17
-    // },
18
     react: {
20
     react: {
19
       wait: true
21
       wait: true
20
     },
22
     },
21
     resources: {
23
     resources: {
22
       en: {
24
       en: {
23
-        translation: {...langEn.translation, ...en.translation}
25
+        translation: {
26
+          ...enLib, // fronted_lib
27
+          ...en, // frontend
28
+          ...htmlDocEnTranslation // html-document
29
+        }
24
       },
30
       },
25
       fr: {
31
       fr: {
26
-        translation: {...langFr.translation, ...fr.translation}
32
+        translation: {
33
+          ...frLib, // fronted_lib
34
+          ...fr, // frontend
35
+          ...htmlDocFrTranslation // html-document
36
+        }
27
       }
37
       }
28
     }
38
     }
29
   })
39
   })

+ 17 - 0
frontend_app_html-document/build_html-document.sh View File

1
+#!/bin/bash
2
+
3
+. ../bash_library.sh # source bash_library.sh
4
+
5
+windoz=""
6
+if [[ $1 = "-w" ]]; then
7
+    windoz="windoz"
8
+fi
9
+
10
+log "npm run build$windoz"
11
+npm run build$windoz
12
+log "cp dist/html-document.app.js ../frontend/dist/app"
13
+cp dist/html-document.app.js ../frontend/dist/app
14
+log "cp i18next.scanner/en/translation.json ../frontend/dist/app/html-document_en_translation.json"
15
+cp i18next.scanner/en/translation.json ../frontend/dist/app/html-document_en_translation.json
16
+log "cp i18next.scanner/fr/translation.json ../frontend/dist/app/html-document_fr_translation.json"
17
+cp i18next.scanner/fr/translation.json ../frontend/dist/app/html-document_fr_translation.json

+ 14 - 0
frontend_app_html-document/i18next.scanner.js View File

1
+const scanner = require('i18next-scanner')
2
+const vfs = require('vinyl-fs')
3
+
4
+const option = require('../i18next.option.js')
5
+
6
+// --------------------
7
+// 2018/07/27 - currently, last version is 2.6.5 but a bug is spaming log with errors. So I'm using 2.6.1
8
+// this issue seems related : https://github.com/i18next/i18next-scanner/issues/88
9
+// --------------------
10
+
11
+vfs.src(['./src/**/*.jsx'])
12
+// .pipe(sort()) // Sort files in stream by path
13
+  .pipe(scanner(option))
14
+  .pipe(vfs.dest('./i18next.scanner'))

+ 3 - 0
frontend_app_html-document/i18next.scanner/en/translation.json View File

1
+{
2
+  "Last version": "Last version"
3
+}

+ 3 - 0
frontend_app_html-document/i18next.scanner/fr/translation.json View File

1
+{
2
+  "Last version": "Dernière version"
3
+}

+ 3 - 1
frontend_app_html-document/package.json View File

7
     "servdev": "NODE_ENV=development webpack-dev-server --watch --colors --inline --hot --progress",
7
     "servdev": "NODE_ENV=development webpack-dev-server --watch --colors --inline --hot --progress",
8
     "servdevwindoz": "set NODE_ENV=development&& webpack-dev-server --watch --colors --inline --hot --progress",
8
     "servdevwindoz": "set NODE_ENV=development&& webpack-dev-server --watch --colors --inline --hot --progress",
9
     "servdev-dashboard": "NODE_ENV=development webpack-dashboard -m -p 9871 -- webpack-dev-server --watch --colors --inline --hot --progress",
9
     "servdev-dashboard": "NODE_ENV=development webpack-dashboard -m -p 9871 -- webpack-dev-server --watch --colors --inline --hot --progress",
10
-    "buildwindoz": "set NODE_ENV=production&& webpack -p",
11
     "build": "NODE_ENV=production webpack -p",
10
     "build": "NODE_ENV=production webpack -p",
11
+    "build-translation": "node i18next.scanner.js",
12
+    "buildwindoz": "set NODE_ENV=production&& webpack -p",
12
     "test": "echo \"Error: no test specified\" && exit 1"
13
     "test": "echo \"Error: no test specified\" && exit 1"
13
   },
14
   },
14
   "author": "",
15
   "author": "",
41
     "whatwg-fetch": "^2.0.3"
42
     "whatwg-fetch": "^2.0.3"
42
   },
43
   },
43
   "devDependencies": {
44
   "devDependencies": {
45
+    "i18next-scanner": "^2.6.1",
44
     "webpack-dashboard": "^1.1.1",
46
     "webpack-dashboard": "^1.1.1",
45
     "webpack-dev-server": "^2.9.2"
47
     "webpack-dev-server": "^2.9.2"
46
   },
48
   },

+ 0 - 13
frontend_app_html-document/rebuild_html-document.sh View File

1
-#!/bin/bash
2
-
3
-. ../bash_library.sh # source bash_library.sh
4
-
5
-windoz=""
6
-if  [[ $1 = "-w" ]]; then
7
-    windoz="windoz"
8
-fi
9
-
10
-log "npm run build$windoz"
11
-npm run build$windoz
12
-log "cp dist/html-document.app.js ../frontend/dist/app"
13
-cp dist/html-document.app.js ../frontend/dist/app

+ 10 - 4
frontend_app_html-document/src/container/HtmlDocument.jsx View File

1
 import React from 'react'
1
 import React from 'react'
2
 import HtmlDocumentComponent from '../component/HtmlDocument.jsx'
2
 import HtmlDocumentComponent from '../component/HtmlDocument.jsx'
3
+import { translate } from 'react-i18next'
4
+import i18n from '../i18n.js'
3
 import {
5
 import {
6
+  addAllResourceI18n,
4
   handleFetchResult,
7
   handleFetchResult,
5
   PopinFixed,
8
   PopinFixed,
6
   PopinFixedHeader,
9
   PopinFixedHeader,
20
   putHtmlDocContent,
23
   putHtmlDocContent,
21
   putHtmlDocStatus
24
   putHtmlDocStatus
22
 } from '../action.async.js'
25
 } from '../action.async.js'
23
-import i18n from '../i18n.js'
24
 
26
 
25
 class HtmlDocument extends React.Component {
27
 class HtmlDocument extends React.Component {
26
   constructor (props) {
28
   constructor (props) {
27
     super(props)
29
     super(props)
28
     this.state = {
30
     this.state = {
29
-      appName: 'html-documents',
31
+      appName: 'html-document',
30
       isVisible: true,
32
       isVisible: true,
31
       config: props.data ? props.data.config : debug.config,
33
       config: props.data ? props.data.config : debug.config,
32
       loggedUser: props.data ? props.data.loggedUser : debug.loggedUser,
34
       loggedUser: props.data ? props.data.loggedUser : debug.loggedUser,
38
       mode: MODE.VIEW
40
       mode: MODE.VIEW
39
     }
41
     }
40
 
42
 
43
+    // i18n has been init, add resources from frontend
44
+    addAllResourceI18n(i18n, props.data ? props.data.config.translation : debug.config.translation)
45
+
41
     document.addEventListener('appCustomEvent', this.customEventReducer)
46
     document.addEventListener('appCustomEvent', this.customEventReducer)
42
   }
47
   }
43
 
48
 
284
 
289
 
285
   render () {
290
   render () {
286
     const { isVisible, loggedUser, content, timeline, newComment, timelineWysiwyg, config, mode } = this.state
291
     const { isVisible, loggedUser, content, timeline, newComment, timelineWysiwyg, config, mode } = this.state
292
+    const { t } = this.props
287
 
293
 
288
     if (!isVisible) return null
294
     if (!isVisible) return null
289
 
295
 
321
                   style={{backgroundColor: config.hexcolor, color: '#fdfdfd'}}
327
                   style={{backgroundColor: config.hexcolor, color: '#fdfdfd'}}
322
                 >
328
                 >
323
                   <i className='fa fa-code-fork' />
329
                   <i className='fa fa-code-fork' />
324
-                  Dernière version
330
+                  {t('Last version')}
325
                 </button>
331
                 </button>
326
               }
332
               }
327
             </div>
333
             </div>
381
   }
387
   }
382
 }
388
 }
383
 
389
 
384
-export default HtmlDocument
390
+export default translate()(HtmlDocument)

+ 5 - 0
frontend_app_html-document/src/container/PopupCreateHtmlDocument.jsx View File

3
   CardPopupCreateContent, handleFetchResult
3
   CardPopupCreateContent, handleFetchResult
4
 } from 'tracim_frontend_lib'
4
 } from 'tracim_frontend_lib'
5
 import { postHtmlDocContent } from '../action.async.js'
5
 import { postHtmlDocContent } from '../action.async.js'
6
+import {addAllResourceForI18n, addAllResourceI18n} from '../../../frontend_lib'
7
+import i18n from '../i18n.js'
6
 
8
 
7
 const debug = { // outdated
9
 const debug = { // outdated
8
   config: {
10
   config: {
42
       idFolder: props.data ? props.data.idFolder : debug.idFolder,
44
       idFolder: props.data ? props.data.idFolder : debug.idFolder,
43
       newContentName: ''
45
       newContentName: ''
44
     }
46
     }
47
+
48
+    // i18n has been init, add resources from frontend
49
+    addAllResourceI18n(i18n, props.data ? props.data.config.translation : debug.config.translation)
45
   }
50
   }
46
 
51
 
47
   handleChangeNewContentName = e => this.setState({newContentName: e.target.value})
52
   handleChangeNewContentName = e => this.setState({newContentName: e.target.value})

+ 13 - 1
frontend_app_html-document/src/helper.js View File

51
       faIcon: 'warning',
51
       faIcon: 'warning',
52
       hexcolor: '#ababab',
52
       hexcolor: '#ababab',
53
       globalStatus: 'closed'
53
       globalStatus: 'closed'
54
-    }]
54
+    }],
55
+    translation: {
56
+      en: {
57
+        translation: {
58
+          'Last version': 'Last version debug en'
59
+        }
60
+      },
61
+      fr: {
62
+        translation: {
63
+          'Last version': 'Dernière version debug fr'
64
+        }
65
+      }
66
+    }
55
   },
67
   },
56
   loggedUser: { // @FIXME this object is outdated
68
   loggedUser: { // @FIXME this object is outdated
57
     user_id: 5,
69
     user_id: 5,

+ 1 - 11
frontend_app_html-document/src/i18n.js View File

1
 import i18n from 'i18next'
1
 import i18n from 'i18next'
2
 import { reactI18nextModule } from 'react-i18next'
2
 import { reactI18nextModule } from 'react-i18next'
3
-import { langFr, langEn } from 'tracim_frontend_lib'
4
-import fr from './translate/fr.js'
5
-import en from './translate/en.js'
6
 
3
 
7
 i18n
4
 i18n
8
   .use(reactI18nextModule)
5
   .use(reactI18nextModule)
18
     react: {
15
     react: {
19
       wait: true
16
       wait: true
20
     },
17
     },
21
-    resources: {
22
-      en: {
23
-        translation: {...langEn.translation, ...en.translation}
24
-      },
25
-      fr: {
26
-        translation: {...langFr.translation, ...fr.translation}
27
-      }
28
-    }
18
+    resources: {} // init with empty resources, they will come from frontend in app constructor
29
   })
19
   })
30
 
20
 
31
 export default i18n
21
 export default i18n

+ 17 - 0
frontend_app_thread/build_thread.sh View File

1
+#!/bin/bash
2
+
3
+. ../bash_library.sh # source bash_library.sh
4
+
5
+windoz=""
6
+if  [[ $1 = "-w" ]]; then
7
+    windoz="windoz"
8
+fi
9
+
10
+log "npm run build$windoz"
11
+npm run build$windoz
12
+log "cp dist/thread.app.js ../frontend/dist/app"
13
+cp dist/thread.app.js ../frontend/dist/app
14
+log "cp i18next.scanner/en/translation.json ../frontend/dist/app/thread_en_translation.json"
15
+cp i18next.scanner/en/translation.json ../frontend/dist/app/thread_en_translation.json
16
+log "cp i18next.scanner/fr/translation.json ../frontend/dist/app/thread_fr_translation.json"
17
+cp i18next.scanner/fr/translation.json ../frontend/dist/app/thread_fr_translation.json

+ 14 - 0
frontend_app_thread/i18next.scanner.js View File

1
+const scanner = require('i18next-scanner')
2
+const vfs = require('vinyl-fs')
3
+
4
+const option = require('../i18next.option.js')
5
+
6
+// --------------------
7
+// 2018/07/27 - currently, last version is 2.6.5 but a bug is spaming log with errors. So I'm using 2.6.1
8
+// this issue seems related : https://github.com/i18next/i18next-scanner/issues/88
9
+// --------------------
10
+
11
+vfs.src(['./src/**/*.jsx'])
12
+// .pipe(sort()) // Sort files in stream by path
13
+  .pipe(scanner(option))
14
+  .pipe(vfs.dest('./i18next.scanner'))

+ 1 - 0
frontend_app_thread/i18next.scanner/en/translation.json View File

1
+{}

+ 1 - 0
frontend_app_thread/i18next.scanner/fr/translation.json View File

1
+{}

+ 2 - 0
frontend_app_thread/package.json View File

8
     "servdevwindoz": "set NODE_ENV=development&& webpack-dev-server --watch --colors --inline --hot --progress",
8
     "servdevwindoz": "set NODE_ENV=development&& webpack-dev-server --watch --colors --inline --hot --progress",
9
     "servdev-dashboard": "NODE_ENV=development webpack-dashboard -m -p 9872 -- webpack-dev-server --watch --colors --inline --hot --progress",
9
     "servdev-dashboard": "NODE_ENV=development webpack-dashboard -m -p 9872 -- webpack-dev-server --watch --colors --inline --hot --progress",
10
     "build": "NODE_ENV=production webpack -p",
10
     "build": "NODE_ENV=production webpack -p",
11
+    "build-translation": "node i18next.scanner.js",
11
     "buildwindoz": "set NODE_ENV=production&& webpack -p",
12
     "buildwindoz": "set NODE_ENV=production&& webpack -p",
12
     "test": "echo \"Error: no test specified\" && exit 1"
13
     "test": "echo \"Error: no test specified\" && exit 1"
13
   },
14
   },
41
     "whatwg-fetch": "^2.0.3"
42
     "whatwg-fetch": "^2.0.3"
42
   },
43
   },
43
   "devDependencies": {
44
   "devDependencies": {
45
+    "i18next-scanner": "^2.6.1",
44
     "webpack-dashboard": "^1.1.1",
46
     "webpack-dashboard": "^1.1.1",
45
     "webpack-dev-server": "^2.9.2"
47
     "webpack-dev-server": "^2.9.2"
46
   },
48
   },

+ 0 - 13
frontend_app_thread/rebuild_thread.sh View File

1
-#!/bin/bash
2
-
3
-. ../bash_library.sh # source bash_library.sh
4
-
5
-windoz=""
6
-if  [[ $1 = "-w" ]]; then
7
-    windoz="windoz"
8
-fi
9
-
10
-log "npm run build$windoz"
11
-npm run build$windoz
12
-log "cp dist/thread.app.js ../frontend/dist/app"
13
-cp dist/thread.app.js ../frontend/dist/app

+ 12 - 0
frontend_app_thread/src/container/PopupCreateThread.jsx View File

1
 import React from 'react'
1
 import React from 'react'
2
 import {
2
 import {
3
+  addAllResourceI18n,
3
   CardPopupCreateContent,
4
   CardPopupCreateContent,
4
   handleFetchResult
5
   handleFetchResult
5
 } from 'tracim_frontend_lib'
6
 } from 'tracim_frontend_lib'
19
       'Accept': 'application/json',
20
       'Accept': 'application/json',
20
       'Content-Type': 'application/json',
21
       'Content-Type': 'application/json',
21
       'Authorization': 'Basic ' + btoa(`${'admin@admin.admin'}:${'admin@admin.admin'}`)
22
       'Authorization': 'Basic ' + btoa(`${'admin@admin.admin'}:${'admin@admin.admin'}`)
23
+    },
24
+    translation: {
25
+      en: {
26
+        translation: {}
27
+      },
28
+      fr: {
29
+        translation: {}
30
+      }
22
     }
31
     }
23
   },
32
   },
24
   loggedUser: {
33
   loggedUser: {
44
       idFolder: props.data ? props.data.idFolder : debug.idFolder,
53
       idFolder: props.data ? props.data.idFolder : debug.idFolder,
45
       newContentName: ''
54
       newContentName: ''
46
     }
55
     }
56
+
57
+    // i18n has been init, add resources from frontend
58
+    addAllResourceI18n(i18n, props.data ? props.data.config.translation : debug.config.translation)
47
   }
59
   }
48
 
60
 
49
   handleChangeNewContentName = e => this.setState({newContentName: e.target.value})
61
   handleChangeNewContentName = e => this.setState({newContentName: e.target.value})

+ 4 - 0
frontend_app_thread/src/container/Thread.jsx View File

2
 import i18n from '../i18n.js'
2
 import i18n from '../i18n.js'
3
 import { debug } from '../helper.js'
3
 import { debug } from '../helper.js'
4
 import {
4
 import {
5
+  addAllResourceI18n,
5
   handleFetchResult,
6
   handleFetchResult,
6
   PopinFixed,
7
   PopinFixed,
7
   PopinFixedHeader,
8
   PopinFixedHeader,
33
       timelineWysiwyg: false
34
       timelineWysiwyg: false
34
     }
35
     }
35
 
36
 
37
+    // i18n has been init, add resources from frontend
38
+    addAllResourceI18n(i18n, props.data ? props.data.config.translation : debug.config.translation)
39
+
36
     document.addEventListener('appCustomEvent', this.customEventReducer)
40
     document.addEventListener('appCustomEvent', this.customEventReducer)
37
   }
41
   }
38
 
42
 

+ 9 - 0
frontend_lib/i18next.scanner.js View File

1
+const scanner = require('i18next-scanner')
2
+const vfs = require('vinyl-fs')
3
+
4
+const option = require('../i18next.option.js')
5
+
6
+vfs.src(['./src/**/*.jsx'])
7
+// .pipe(sort()) // Sort files in stream by path
8
+  .pipe(scanner(option))
9
+  .pipe(vfs.dest('./i18next.scanner'))

+ 3 - 0
frontend_lib/i18next.scanner/en/translation.json View File

1
+{
2
+  "File status": "File status"
3
+}

+ 3 - 0
frontend_lib/i18next.scanner/fr/translation.json View File

1
+{
2
+  "File status": "__NOT_TRANSLATED__"
3
+}

+ 1 - 0
frontend_lib/package.json View File

44
     "whatwg-fetch": "^2.0.3"
44
     "whatwg-fetch": "^2.0.3"
45
   },
45
   },
46
   "devDependencies": {
46
   "devDependencies": {
47
+    "i18next-scanner": "^2.6.1",
47
     "webpack-dashboard": "^1.1.1",
48
     "webpack-dashboard": "^1.1.1",
48
     "webpack-dev-server": "^2.9.2"
49
     "webpack-dev-server": "^2.9.2"
49
   },
50
   },

+ 2 - 2
frontend_lib/src/component/Input/SelectStatus/SelectStatus.jsx View File

27
       </button>
27
       </button>
28
 
28
 
29
       <div className='selectStatus__submenu dropdown-menu' aria-labelledby='dropdownMenu2'>
29
       <div className='selectStatus__submenu dropdown-menu' aria-labelledby='dropdownMenu2'>
30
-        <h6 className='dropdown-header'>{props.t('Input.SelectStatus.file_status')}</h6>
30
+        <h6 className='dropdown-header'>{props.t('File status')}</h6>
31
 
31
 
32
         <div className='dropdown-divider' />
32
         <div className='dropdown-divider' />
33
 
33
 
39
             key={`status_${s.slug}`}
39
             key={`status_${s.slug}`}
40
             style={{color: s.hexcolor}}
40
             style={{color: s.hexcolor}}
41
           >
41
           >
42
-            {s.label /* props.t('Input.SelectStatus.ongoing') */}
42
+            {s.label}
43
             <div className='selectStatus__submenu__item__icon'>
43
             <div className='selectStatus__submenu__item__icon'>
44
               <i className={`fa fa-fw fa-${s.faIcon}`} />
44
               <i className={`fa fa-fw fa-${s.faIcon}`} />
45
             </div>
45
             </div>

+ 8 - 0
frontend_lib/src/helper.js View File

20
       return new Promise((resolve, reject) => reject(fetchResult)) // @TODO : handle errors from api result
20
       return new Promise((resolve, reject) => reject(fetchResult)) // @TODO : handle errors from api result
21
   }
21
   }
22
 }
22
 }
23
+
24
+export const libAddAllResourceI18n = (i18n, translation) => {
25
+  Object.keys(translation).forEach(lang =>
26
+    Object.keys(translation[lang]).forEach(namespace =>
27
+      i18n.addResources(lang, namespace, translation[lang][namespace])
28
+    )
29
+  )
30
+}

+ 5 - 1
frontend_lib/src/index.js View File

1
-import { libHandleFetchResult } from './helper.js'
1
+import { libAddAllResourceI18n, libHandleFetchResult } from './helper.js'
2
+
3
+// fr and en are deprecated
2
 import fr from './translate/fr.js'
4
 import fr from './translate/fr.js'
3
 import en from './translate/en.js'
5
 import en from './translate/en.js'
4
 
6
 
24
 export const langFr = fr
26
 export const langFr = fr
25
 export const langEn = en
27
 export const langEn = en
26
 
28
 
29
+export const addAllResourceI18n = libAddAllResourceI18n
30
+
27
 export const handleFetchResult = libHandleFetchResult
31
 export const handleFetchResult = libHandleFetchResult
28
 
32
 
29
 export const PopinFixed = libPopinFixed
33
 export const PopinFixed = libPopinFixed

+ 40 - 0
i18next.option.js View File

1
+module.exports = {
2
+  debug: true,
3
+  removeUnusedKeys: true,
4
+  func: {
5
+    list: ['t', 'props.t', 'this.props.t'],
6
+    extensions: ['.js', '.jsx']
7
+  },
8
+  lngs: ['en', 'fr'],
9
+  defaultLng: 'en',
10
+  keySeparator: false, // false means "keyBasedFallback"
11
+  nsSeparator: false, // false means "keyBasedFallback"
12
+  fallbackLng: false,
13
+
14
+  ns: ['translation'], // namespace
15
+  defaultNS: 'translation',
16
+
17
+  // @param {string} lng The language currently used.
18
+  // @param {string} ns The namespace currently used.
19
+  // @param {string} key The translation key.
20
+  // @return {string} Returns a default value for the translation key.
21
+  // Return key as the default value for English language. Otherwise, returns '__NOT_TRANSLATED__'
22
+  defaultValue: (lng, ns, key) => lng === 'en' ? key : '__NOT_TRANSLATED__',
23
+
24
+  react: {wait: true},
25
+
26
+  resource: {
27
+    // The path where resources get loaded from.
28
+    // /!\ /!\ /!\ Relative to CURRENT working directory. /!\
29
+    loadPath: 'i18next.scanner/{{lng}}/{{ns}}.json',
30
+    // The path to store resources.
31
+    // /!\ /!\ /!\ Relative to the path specified by `vfs.dest('./i18next.scanner')`. /!\
32
+    savePath: '{{lng}}/{{ns}}.json',
33
+    jsonIndent: 2,
34
+    lineEnding: '\n'
35
+  },
36
+  // interpolation: {
37
+  //   escapeValue: false, // not needed for react!!
38
+  // },
39
+  trans: false,
40
+}

+ 8 - 0
install_frontend_dependencies.sh View File

18
 npm link tracim_frontend_lib
18
 npm link tracim_frontend_lib
19
 cd -
19
 cd -
20
 
20
 
21
+log "cd frontend_app_thread"
22
+cd frontend_app_thread
23
+log "npm i"
24
+npm i
25
+log "npm link tracim_frontend_lib"
26
+npm link tracim_frontend_lib
27
+cd -
28
+
21
 log "cd frontend"
29
 log "cd frontend"
22
 cd frontend
30
 cd frontend
23
 log "npm i"
31
 log "npm i"