From 408531d13ab771227e7899dda804338f66aecbf7 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Mon, 2 Nov 2020 11:07:08 +0100 Subject: [PATCH] use i18next instead of angular-translate for react components --- .../src/javascript/components/plan-card.tsx | 31 ++++++--- app/frontend/src/javascript/lib/i18n.ts | 22 +++++++ .../src/stylesheets/app.components.scss | 3 + app/models/stylesheet.rb | 6 +- package.json | 4 ++ yarn.lock | 65 +++++++++++++++++++ 6 files changed, 120 insertions(+), 11 deletions(-) create mode 100644 app/frontend/src/javascript/lib/i18n.ts diff --git a/app/frontend/src/javascript/components/plan-card.tsx b/app/frontend/src/javascript/components/plan-card.tsx index 04c8cf5f3..a7a452603 100644 --- a/app/frontend/src/javascript/components/plan-card.tsx +++ b/app/frontend/src/javascript/components/plan-card.tsx @@ -2,7 +2,8 @@ * This component is a "card" publicly presenting the details of a plan */ -import React from 'react'; +import React, { Suspense } from 'react'; +import { useTranslation } from 'react-i18next'; import { react2angular } from 'react2angular'; import { IFilterService } from 'angular'; import moment from 'moment'; @@ -10,6 +11,7 @@ import _ from 'lodash' import { IApplication } from '../models/application'; import { Plan } from '../models/plan'; import { User, UserRole } from '../models/user'; +import '../lib/i18n'; declare var Application: IApplication; @@ -19,11 +21,11 @@ interface PlanCardProps { operator: User, isSelected: boolean, onSelectPlan: (plan: Plan) => void, - _t: (key: string, interpolation?: object) => Promise, $filter: IFilterService } -const PlanCard: React.FC = ({ plan, user, operator, onSelectPlan, isSelected, _t, $filter }) => { +const PlanCard: React.FC = ({ plan, user, operator, onSelectPlan, isSelected, $filter }) => { + const { t } = useTranslation('public'); /** * Return the formatted localized amount of the given plan (eg. 20.5 => "20,50 €") */ @@ -75,22 +77,35 @@ const PlanCard: React.FC = ({ plan, user, operator, onSelectPlan, {!hasSubscribedToThisPlan() && } {hasSubscribedToThisPlan() && } } {canSubscribeForOther() &&
} ); } -Application.Components.component('planCard', react2angular(PlanCard, ['plan', 'user', 'operator', 'onSelectPlan', 'isSelected'], ['_t', '$filter'])); +const PlanCardWrapper: React.FC = ({ plan, user, operator, onSelectPlan, isSelected, $filter }) => { + const loading = ( +
+ +
+ ); + return ( + + + + ); +} + +Application.Components.component('planCard', react2angular(PlanCardWrapper, ['plan', 'user', 'operator', 'onSelectPlan', 'isSelected'], ['$filter'])); diff --git a/app/frontend/src/javascript/lib/i18n.ts b/app/frontend/src/javascript/lib/i18n.ts new file mode 100644 index 000000000..a561001f8 --- /dev/null +++ b/app/frontend/src/javascript/lib/i18n.ts @@ -0,0 +1,22 @@ +import i18n from 'i18next'; +import ICU from 'i18next-icu'; +import HttpApi from 'i18next-http-backend'; +import { initReactI18next } from 'react-i18next'; + +declare var Fablab: any; + +i18n + .use(ICU) + .use(HttpApi) + .use(initReactI18next) + .init({ + lng: Fablab.locale, + fallbackLng: 'en', + ns: ['admin', 'logged', 'public', 'shared'], + defaultNS: 'shared', + backend: { + loadPath: '/api/translations/{{lng}}/app.{{ns}}' + } + }); + +export default i18n; diff --git a/app/frontend/src/stylesheets/app.components.scss b/app/frontend/src/stylesheets/app.components.scss index b3c51a807..ef7e9bc01 100644 --- a/app/frontend/src/stylesheets/app.components.scss +++ b/app/frontend/src/stylesheets/app.components.scss @@ -344,6 +344,9 @@ padding-left: 30px; padding-right: 30px; } + button.subscribe-button:focus, button.subscribe-button:hover { + outline: 0; + } } } diff --git a/app/models/stylesheet.rb b/app/models/stylesheet.rb index 6e2012f66..f2939f1ca 100644 --- a/app/models/stylesheet.rb +++ b/app/models/stylesheet.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # Stylesheet is a cached CSS file that allows to easily customize the interface of Fab-manager with some configurable colors and # a picture for the background of the user's profile. @@ -82,8 +82,8 @@ class Stylesheet < ApplicationRecord scss_files = Dir['app/themes/casemate/**/*.scss'] templates = '' - erb_files.each { |erb_file| templates.concat(ERB.new(File.read(erb_file)).result) } - scss_files.each { |scss_file| templates.concat(File.read(scss_file)) } + erb_files.each { |erb_file| templates += ERB.new(File.read(erb_file)).result } + scss_files.each { |scss_file| templates += File.read(scss_file) } engine = SassC::Engine.new(templates, style: :compressed) engine.render.presence diff --git a/package.json b/package.json index 93dc46897..c1a7c3dff 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,9 @@ "elasticsearch-browser": "3.1", "fullcalendar": "3.10.2", "holderjs": "2.6", + "i18next": "^19.8.3", + "i18next-http-backend": "^1.0.21", + "i18next-icu": "^1.4.2", "jasny-bootstrap": "3.1", "jquery": ">=3.5.0", "jquery-ujs": "^1.2.2", @@ -94,6 +97,7 @@ "prop-types": "^15.7.2", "react": "^17.0.0", "react-dom": "^17.0.0", + "react-i18next": "^11.7.3", "react-switch": "^5.0.1", "react2angular": "^4.0.6", "summernote": "0.8.18", diff --git a/yarn.lock b/yarn.lock index b13ea3c8a..f3a3df029 100644 --- a/yarn.lock +++ b/yarn.lock @@ -979,6 +979,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.12.0", "@babel/runtime@^7.3.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.1.tgz#b4116a6b6711d010b2dad3b7b6e43bf1b9954740" + integrity sha512-J5AIf3vPj3UwXaAzb5j1xM4WAQDX3EMgemF8rjCP3SoW09LfRKAXQKt6CoVYl230P6iWdRcBbnLDDdnqWxZSCA== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" @@ -4567,6 +4574,13 @@ html-minifier-terser@^5.1.1: relateurl "^0.2.7" terser "^4.6.3" +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" + htmlparser2@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-4.1.0.tgz#9a4ef161f2e4625ebf7dfbe6c0a2f52d18a59e78" @@ -4652,6 +4666,27 @@ 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-http-backend@^1.0.21: + version "1.0.21" + resolved "https://registry.yarnpkg.com/i18next-http-backend/-/i18next-http-backend-1.0.21.tgz#cee901b3527dad5165fa91de973b6aa6404c1c37" + integrity sha512-UDeHoV2B+31Gr++0KFAVjM5l+SEwePpF6sfDyaDq5ennM9QNJ78PBEMPStwkreEm4h5C8sT7M1JdNQrLcU1Wdg== + dependencies: + node-fetch "2.6.1" + +i18next-icu@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/i18next-icu/-/i18next-icu-1.4.2.tgz#2b79d1ac2c2d542725219beac34a74db15cd2ff9" + integrity sha512-EqHafx/sL8eoEowwqi5P6cXtLrzJXBKI4RmV+UaMXlpIJNfckVsq873F2KkMKkApxiw2ATj46C8MurmhMsHQGw== + dependencies: + intl-messageformat "2.2.0" + +i18next@^19.8.3: + version "19.8.3" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-19.8.3.tgz#10df7222db8c23389b13bceb9ba67a5e20a0241e" + integrity sha512-eVrqAw2gGGYYJaJMYw4VM1FNFawLD4b84IsoTZMVXeWHaxAM2gyTa34j2Sip15UkBz/LrSxdFJj0Jhlrz7EvHA== + dependencies: + "@babel/runtime" "^7.12.0" + iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -4825,6 +4860,18 @@ interpret@^1.4.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== +intl-messageformat-parser@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/intl-messageformat-parser/-/intl-messageformat-parser-1.4.0.tgz#b43d45a97468cadbe44331d74bb1e8dea44fc075" + integrity sha1-tD1FqXRoytvkQzHXS7Ho3qRPwHU= + +intl-messageformat@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-2.2.0.tgz#345bcd46de630b7683330c2e52177ff5eab484fc" + integrity sha1-NFvNRt5jC3aDMwwuUhd/9eq0hPw= + dependencies: + intl-messageformat-parser "1.4.0" + invariant@^2.2.2, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" @@ -6016,6 +6063,11 @@ no-case@^3.0.3: lower-case "^2.0.1" tslib "^1.10.0" +node-fetch@2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + node-forge@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" @@ -7574,6 +7626,14 @@ react-dom@^17.0.0: object-assign "^4.1.1" scheduler "^0.20.0" +react-i18next@^11.7.3: + version "11.7.3" + resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.7.3.tgz#256461c46baf5b3208c3c6860ca4e569fc7ed053" + integrity sha512-7sYZqVZgdaS9Z0ZH6nuJFErCD0zz5wK3jR4/xCrWjZcxHHF3GRu7BXdicbSPprZV4ZYz7LJzxxMHO7dg5Qb70A== + dependencies: + "@babel/runtime" "^7.3.1" + html-parse-stringify2 "2.0.1" + react-is@^16.8.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" @@ -9245,6 +9305,11 @@ vm-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== +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= + watchpack-chokidar2@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0"