From 8473f6652c3fb240344317168080e7d58772ba0b Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 8 Sep 2019 11:17:02 +0200 Subject: [PATCH] Client - init localization w/ react-i18n - #40 --- .../src/components/NavBar/index.jsx | 286 +++++++++--------- .../src/components/User/Form.jsx | 21 +- fittrackee_client/src/i18n.js | 31 ++ fittrackee_client/src/index.js | 8 +- .../src/locales/en/translations.json | 15 + .../src/locales/fr/translations.json | 15 + package.json | 4 + yarn.lock | 41 ++- 8 files changed, 270 insertions(+), 151 deletions(-) create mode 100644 fittrackee_client/src/i18n.js create mode 100644 fittrackee_client/src/locales/en/translations.json create mode 100644 fittrackee_client/src/locales/fr/translations.json diff --git a/fittrackee_client/src/components/NavBar/index.jsx b/fittrackee_client/src/components/NavBar/index.jsx index 6531a3fd..dda262a6 100644 --- a/fittrackee_client/src/components/NavBar/index.jsx +++ b/fittrackee_client/src/components/NavBar/index.jsx @@ -1,4 +1,5 @@ import React from 'react' +import { Translation } from 'react-i18next' import { connect } from 'react-redux' import { Link } from 'react-router-dom' @@ -8,146 +9,153 @@ class NavBar extends React.PureComponent { render() { const { id, isAuthenticated, picture, username } = this.props return ( -
- +
+ )} + ) } } diff --git a/fittrackee_client/src/components/User/Form.jsx b/fittrackee_client/src/components/User/Form.jsx index f8b26fb9..6869ff6a 100644 --- a/fittrackee_client/src/components/User/Form.jsx +++ b/fittrackee_client/src/components/User/Form.jsx @@ -1,18 +1,21 @@ import React from 'react' +import { useTranslation } from 'react-i18next' import { Helmet } from 'react-helmet' import { history } from '../../index' import { isRegistrationAllowed } from '../../utils' export default function Form(props) { + const { t } = useTranslation() + const pageTitle = `${props.formType + .charAt(0) + .toUpperCase()}${props.formType.slice(1)}` return (
- FitTrackee - {props.formType} + FitTrackee - {t(props.formType)} -

- {`${props.formType.charAt(0).toUpperCase()}${props.formType.slice(1)}`} -

+

{t(pageTitle)}

@@ -43,7 +46,7 @@ export default function Form(props) { )} diff --git a/fittrackee_client/src/i18n.js b/fittrackee_client/src/i18n.js new file mode 100644 index 00000000..b91ac215 --- /dev/null +++ b/fittrackee_client/src/i18n.js @@ -0,0 +1,31 @@ +import i18n from 'i18next' +import LanguageDetector from 'i18next-browser-languagedetector' +import XHR from 'i18next-xhr-backend' + +import EnTranslations from './locales/en/translations.json' +import FrTranslations from './locales/fr/translations.json' + +i18n + .use(XHR) + .use(LanguageDetector) + .init({ + debug: true, + lng: 'en', + fallbackLng: 'en', + keySeparator: false, + interpolation: { + escapeValue: false, + }, + resources: { + en: { + translations: EnTranslations, + }, + fr: { + translations: FrTranslations, + }, + }, + ns: ['translations'], + defaultNS: 'translations', + }) + +export default i18n diff --git a/fittrackee_client/src/index.js b/fittrackee_client/src/index.js index a8028e77..e77285bd 100644 --- a/fittrackee_client/src/index.js +++ b/fittrackee_client/src/index.js @@ -1,11 +1,13 @@ /* eslint-disable react/jsx-filename-extension */ import { createBrowserHistory } from 'history' import React from 'react' +import { I18nextProvider } from 'react-i18next' import ReactDOM from 'react-dom' import { routerMiddleware } from 'connected-react-router' -import { applyMiddleware, createStore, compose } from 'redux' +import { applyMiddleware, compose, createStore } from 'redux' import thunk from 'redux-thunk' +import i18n from './i18n' import App from './components/App' import Root from './components/Root' import registerServiceWorker from './registerServiceWorker' @@ -34,7 +36,9 @@ if (window.localStorage.authToken !== null) { ReactDOM.render( - + + + , rootNode ) diff --git a/fittrackee_client/src/locales/en/translations.json b/fittrackee_client/src/locales/en/translations.json new file mode 100644 index 00000000..da87b57a --- /dev/null +++ b/fittrackee_client/src/locales/en/translations.json @@ -0,0 +1,15 @@ +{ + "Dashboard": "Dashboard", + "Workouts": "Workouts", + "Statistics": "Statistics", + "Add workout": "Add workout", + "Register": "Register", + "Login": "Login", + "Logout": "Logout", + "login": "login", + "Enter a username": "Enter a username", + "Enter an email address": "Enter an email address", + "Enter a password": "Enter a password", + "Enter the password confirmation": "Enter the password confirmation", + "Submit": "Submit" +} diff --git a/fittrackee_client/src/locales/fr/translations.json b/fittrackee_client/src/locales/fr/translations.json new file mode 100644 index 00000000..996f5f43 --- /dev/null +++ b/fittrackee_client/src/locales/fr/translations.json @@ -0,0 +1,15 @@ +{ + "Dashboard": "Tableau de Bord", + "Workouts": "Activités", + "Statistics": "Statistiques", + "Add workout": "Ajouter une activité", + "Register": "S'inscrire", + "Login": "Se connecter", + "Logout": "Se déconnecter", + "login": "se connecter", + "Enter a username": "Saisir un nom", + "Enter an email address": "Saisir une adresse e-mail", + "Enter a password": "Saisir un mot de passe", + "Enter the password confirmation": "Confirmer le mot de passe", + "Submit": "Valider" +} diff --git a/package.json b/package.json index 8a904a49..f9002482 100644 --- a/package.json +++ b/package.json @@ -7,12 +7,16 @@ "connected-react-router": "^6.5.2", "date-fns": "^2.1.0", "history": "^4.9.0", + "i18next": "^17.0.13", + "i18next-browser-languagedetector": "^3.0.3", + "i18next-xhr-backend": "^3.1.2", "leaflet": "^1.5.1", "luxon": "^1.17.2", "object-hash": "^1.3.1", "react": "^16.9.0", "react-dom": "^16.9.0", "react-helmet": "^6.0.0-beta", + "react-i18next": "^10.12.2", "react-leaflet": "^2.4.0", "react-redux": "^7.1.1", "react-router-dom": "^5.0.1", diff --git a/yarn.lock b/yarn.lock index 5524260f..00395fab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -851,7 +851,7 @@ dependencies: regenerator-runtime "^0.13.2" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5": version "7.6.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.6.0.tgz#4fc1d642a9fd0299754e8b5de62c631cf5568205" integrity sha512-89eSBLJsxNxOERC0Op4vd+0Bqm6wRMqMbFtV3i0/fbaWw/mJ8Q3eBvgX0G4SyrOOLCtbu98HspF8o09MRT+KzQ== @@ -5692,6 +5692,13 @@ html-minifier@^3.5.20: relateurl "0.2.x" uglify-js "3.4.x" +html-parse-stringify2@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/html-parse-stringify2/-/html-parse-stringify2-2.0.1.tgz#dc5670b7292ca158b7bc916c9a6735ac8872834a" + integrity sha1-3FZwtyksoVi3vJFsmmc1rIhyg0o= + dependencies: + void-elements "^2.0.1" + html-webpack-plugin@4.0.0-beta.5: version "4.0.0-beta.5" resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.0.0-beta.5.tgz#2c53083c1151bfec20479b1f8aaf0039e77b5513" @@ -5791,6 +5798,25 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= +i18next-browser-languagedetector@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-3.0.3.tgz#879ebe421685c70cc5cfa96191364a35ea7da742" + integrity sha512-1YuAogyQap0J6N4kM+6gAjZ6T7QWrp3xZCmSs0QedkNmgAKhj7FiQlCviHKl3IwbM6zJNgft4D7UDPWb1dTCMQ== + +i18next-xhr-backend@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/i18next-xhr-backend/-/i18next-xhr-backend-3.1.2.tgz#f9da86c81981ac245325cb2dbfd4232a5b183676" + integrity sha512-zN+x85W5R2ezGfmRh8F7+lsXoQgCNNb1jjSfm0325VuSIZ4ewvsnq3uHFrZaXmSJ8qTwPibO9rRb3mIzncEF9g== + dependencies: + "@babel/runtime" "^7.5.5" + +i18next@^17.0.13: + version "17.0.13" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-17.0.13.tgz#3c639e15de86e0523f8f286f6cf07db355ee0a4f" + integrity sha512-tCBpekVs95IsN3kdi/6HhnfzHDlpXerOmOsf2ZMWtct9YbMYKI54HVdQ6XxsHGXBxY+UgjbQJwqghKCd2sYQWw== + dependencies: + "@babel/runtime" "^7.3.1" + iconv-lite@0.4.11: version "0.4.11" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.11.tgz#2ecb42fd294744922209a2e7c404dac8793d8ade" @@ -9450,6 +9476,14 @@ react-helmet@^6.0.0-beta: react-fast-compare "^2.0.2" react-side-effect "^1.1.0" +react-i18next@^10.12.2: + version "10.12.2" + resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-10.12.2.tgz#2f2d79b84c1f3e3844d110e4c9d5c73a48f99418" + integrity sha512-tZCBhUz8rJtgmTi1z2pWEoQBvFHjwOS2+TQ7L4RfJq1LDirXi2m+3Pwg6gUECVCGenWomLufWNiTwRF9fmBrUQ== + dependencies: + "@babel/runtime" "^7.3.1" + html-parse-stringify2 "2.0.1" + react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.9.0: version "16.9.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.9.0.tgz#21ca9561399aad0ff1a7701c01683e8ca981edcb" @@ -11642,6 +11676,11 @@ vm-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.0.tgz#bd76d6a23323e2ca8ffa12028dc04559c75f9019" integrity sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw== +void-elements@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" + integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w= + w3c-hr-time@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045"