Browse Source

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

Skylsmoi 9 months 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,6 +21,10 @@ log "npm run build$windoz # for frontend_app_html-document"
21 21
 npm run build$windoz
22 22
 log "cp dist/html-document.app.js"
23 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 28
 cd -
25 29
 
26 30
 log "cd frontend_app_thread"
@@ -29,3 +33,8 @@ log "npm run build$windoz # for frontend_app_thread"
29 33
 npm run build$windoz
30 34
 log "cp dist/thread.app.js"
31 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

@@ -0,0 +1,16 @@
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

@@ -0,0 +1,13 @@
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

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

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

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

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

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

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

@@ -7,7 +7,7 @@ const Footer = ({ t }) => {
7 7
   return (
8 8
     <footer className='footer text-right'>
9 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 11
       </div>
12 12
       <img className='footer__logo' src={logoFooter} />
13 13
     </footer>

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

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

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

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

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

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

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

@@ -49,7 +49,7 @@ class Header extends React.Component {
49 49
 
50 50
       dispatch(setUserDisconnected())
51 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,7 +57,7 @@ class Login extends React.Component {
57 57
 
58 58
       history.push(PAGE.HOME)
59 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,7 +86,7 @@ class Sidebar extends React.Component {
86 86
 
87 87
             <div className='sidebar__btnnewworkspace'>
88 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 90
               </button>
91 91
             </div>
92 92
 

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

@@ -1,29 +1,39 @@
1 1
 import i18n from 'i18next'
2 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 12
 i18n
8 13
   .use(reactI18nextModule)
9 14
   .init({
10
-    fallbackLng: 'fr',
15
+    fallbackLng: 'en',
11 16
     // have a common namespace used around the full app
12 17
     ns: ['translation'], // namespace
13 18
     defaultNS: 'translation',
14 19
     debug: true,
15
-    // interpolation: {
16
-    //   escapeValue: false, // not needed for react!!
17
-    // },
18 20
     react: {
19 21
       wait: true
20 22
     },
21 23
     resources: {
22 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 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

@@ -0,0 +1,17 @@
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

@@ -0,0 +1,14 @@
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

@@ -0,0 +1,3 @@
1
+{
2
+  "Last version": "Last version"
3
+}

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

@@ -0,0 +1,3 @@
1
+{
2
+  "Last version": "Dernière version"
3
+}

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

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

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

@@ -1,13 +0,0 @@
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,6 +1,9 @@
1 1
 import React from 'react'
2 2
 import HtmlDocumentComponent from '../component/HtmlDocument.jsx'
3
+import { translate } from 'react-i18next'
4
+import i18n from '../i18n.js'
3 5
 import {
6
+  addAllResourceI18n,
4 7
   handleFetchResult,
5 8
   PopinFixed,
6 9
   PopinFixedHeader,
@@ -20,13 +23,12 @@ import {
20 23
   putHtmlDocContent,
21 24
   putHtmlDocStatus
22 25
 } from '../action.async.js'
23
-import i18n from '../i18n.js'
24 26
 
25 27
 class HtmlDocument extends React.Component {
26 28
   constructor (props) {
27 29
     super(props)
28 30
     this.state = {
29
-      appName: 'html-documents',
31
+      appName: 'html-document',
30 32
       isVisible: true,
31 33
       config: props.data ? props.data.config : debug.config,
32 34
       loggedUser: props.data ? props.data.loggedUser : debug.loggedUser,
@@ -38,6 +40,9 @@ class HtmlDocument extends React.Component {
38 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 46
     document.addEventListener('appCustomEvent', this.customEventReducer)
42 47
   }
43 48
 
@@ -284,6 +289,7 @@ class HtmlDocument extends React.Component {
284 289
 
285 290
   render () {
286 291
     const { isVisible, loggedUser, content, timeline, newComment, timelineWysiwyg, config, mode } = this.state
292
+    const { t } = this.props
287 293
 
288 294
     if (!isVisible) return null
289 295
 
@@ -321,7 +327,7 @@ class HtmlDocument extends React.Component {
321 327
                   style={{backgroundColor: config.hexcolor, color: '#fdfdfd'}}
322 328
                 >
323 329
                   <i className='fa fa-code-fork' />
324
-                  Dernière version
330
+                  {t('Last version')}
325 331
                 </button>
326 332
               }
327 333
             </div>
@@ -381,4 +387,4 @@ class HtmlDocument extends React.Component {
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,6 +3,8 @@ import {
3 3
   CardPopupCreateContent, handleFetchResult
4 4
 } from 'tracim_frontend_lib'
5 5
 import { postHtmlDocContent } from '../action.async.js'
6
+import {addAllResourceForI18n, addAllResourceI18n} from '../../../frontend_lib'
7
+import i18n from '../i18n.js'
6 8
 
7 9
 const debug = { // outdated
8 10
   config: {
@@ -42,6 +44,9 @@ class PopupCreateHtmlDocument extends React.Component {
42 44
       idFolder: props.data ? props.data.idFolder : debug.idFolder,
43 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 52
   handleChangeNewContentName = e => this.setState({newContentName: e.target.value})

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

@@ -51,7 +51,19 @@ export const debug = {
51 51
       faIcon: 'warning',
52 52
       hexcolor: '#ababab',
53 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 68
   loggedUser: { // @FIXME this object is outdated
57 69
     user_id: 5,

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

@@ -1,8 +1,5 @@
1 1
 import i18n from 'i18next'
2 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 4
 i18n
8 5
   .use(reactI18nextModule)
@@ -18,14 +15,7 @@ i18n
18 15
     react: {
19 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 21
 export default i18n

+ 17 - 0
frontend_app_thread/build_thread.sh View File

@@ -0,0 +1,17 @@
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

@@ -0,0 +1,14 @@
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

@@ -0,0 +1 @@
1
+{}

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

@@ -0,0 +1 @@
1
+{}

+ 2 - 0
frontend_app_thread/package.json View File

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

+ 0 - 13
frontend_app_thread/rebuild_thread.sh View File

@@ -1,13 +0,0 @@
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,5 +1,6 @@
1 1
 import React from 'react'
2 2
 import {
3
+  addAllResourceI18n,
3 4
   CardPopupCreateContent,
4 5
   handleFetchResult
5 6
 } from 'tracim_frontend_lib'
@@ -19,6 +20,14 @@ const debug = { // outdated
19 20
       'Accept': 'application/json',
20 21
       'Content-Type': 'application/json',
21 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 33
   loggedUser: {
@@ -44,6 +53,9 @@ class PopupCreateHtmlDocument extends React.Component {
44 53
       idFolder: props.data ? props.data.idFolder : debug.idFolder,
45 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 61
   handleChangeNewContentName = e => this.setState({newContentName: e.target.value})

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

@@ -2,6 +2,7 @@ import React from 'react'
2 2
 import i18n from '../i18n.js'
3 3
 import { debug } from '../helper.js'
4 4
 import {
5
+  addAllResourceI18n,
5 6
   handleFetchResult,
6 7
   PopinFixed,
7 8
   PopinFixedHeader,
@@ -33,6 +34,9 @@ class Thread extends React.Component {
33 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 40
     document.addEventListener('appCustomEvent', this.customEventReducer)
37 41
   }
38 42
 

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

@@ -0,0 +1,9 @@
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

@@ -0,0 +1,3 @@
1
+{
2
+  "File status": "File status"
3
+}

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

@@ -0,0 +1,3 @@
1
+{
2
+  "File status": "__NOT_TRANSLATED__"
3
+}

+ 1 - 0
frontend_lib/package.json View File

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

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

@@ -27,7 +27,7 @@ export const SelectStatus = props => {
27 27
       </button>
28 28
 
29 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 32
         <div className='dropdown-divider' />
33 33
 
@@ -39,7 +39,7 @@ export const SelectStatus = props => {
39 39
             key={`status_${s.slug}`}
40 40
             style={{color: s.hexcolor}}
41 41
           >
42
-            {s.label /* props.t('Input.SelectStatus.ongoing') */}
42
+            {s.label}
43 43
             <div className='selectStatus__submenu__item__icon'>
44 44
               <i className={`fa fa-fw fa-${s.faIcon}`} />
45 45
             </div>

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

@@ -20,3 +20,11 @@ export const libHandleFetchResult = async fetchResult => {
20 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,4 +1,6 @@
1
-import { libHandleFetchResult } from './helper.js'
1
+import { libAddAllResourceI18n, libHandleFetchResult } from './helper.js'
2
+
3
+// fr and en are deprecated
2 4
 import fr from './translate/fr.js'
3 5
 import en from './translate/en.js'
4 6
 
@@ -24,6 +26,8 @@ import libSelectStatus from './component/Input/SelectStatus/SelectStatus.jsx'
24 26
 export const langFr = fr
25 27
 export const langEn = en
26 28
 
29
+export const addAllResourceI18n = libAddAllResourceI18n
30
+
27 31
 export const handleFetchResult = libHandleFetchResult
28 32
 
29 33
 export const PopinFixed = libPopinFixed

+ 40 - 0
i18next.option.js View File

@@ -0,0 +1,40 @@
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,6 +18,14 @@ log "npm link tracim_frontend_lib"
18 18
 npm link tracim_frontend_lib
19 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 29
 log "cd frontend"
22 30
 cd frontend
23 31
 log "npm i"