From 6f924cba3e21df6a39641a44c89e11d319559ef6 Mon Sep 17 00:00:00 2001 From: Davlatov Shahzod Date: Fri, 18 Aug 2023 16:20:31 +0300 Subject: [PATCH 1/5] Language detector --- frontend/package.json | 1 + frontend/src/application.jsx | 16 +++++++++++----- yarn.lock | 19 +++++++++++++++++++ 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 7fd62173..2f9314c0 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,6 +13,7 @@ "clipboard": "^2.0.11", "formik": "^2.4.2", "i18next": "^23.4.1", + "i18next-browser-languagedetector": "^7.1.0", "punycode": "^2.3.0", "react": "^18.2.0", "react-autowidth-input": "^1.0.9", diff --git a/frontend/src/application.jsx b/frontend/src/application.jsx index 3e4e6b47..9e24d780 100644 --- a/frontend/src/application.jsx +++ b/frontend/src/application.jsx @@ -1,6 +1,7 @@ import { configureStore } from '@reduxjs/toolkit'; import * as Sentry from '@sentry/react'; import i18next from 'i18next'; +import LanguageDetector from 'i18next-browser-languagedetector'; import { initReactI18next } from 'react-i18next'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; @@ -14,11 +15,16 @@ import { rootReducer } from './slices'; export default async () => { const defaultLanguage = 'ru'; - await i18next.use(initReactI18next).init({ - lng: defaultLanguage, - debug: false, - resources, - }); + await i18next + .use(LanguageDetector) + .use(initReactI18next) + .init({ + ...(process.env.NODE_ENV === 'production' && { + fallbackLng: defaultLanguage, + }), + debug: false, + resources, + }); const store = configureStore({ reducer: rootReducer, }); diff --git a/yarn.lock b/yarn.lock index 6c42d925..99a90dee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1099,6 +1099,13 @@ dependencies: regenerator-runtime "^0.13.11" +"@babel/runtime@^7.19.4": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.10.tgz#ae3e9631fd947cb7e3610d3e9d8fef5f76696682" + integrity sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/runtime@^7.22.5": version "7.22.6" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.6.tgz#57d64b9ae3cff1d67eb067ae117dac087f5bd438" @@ -8339,6 +8346,13 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" +i18next-browser-languagedetector@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.1.0.tgz#01876fac51f86b78975e79b48ccb62e2313a2d7d" + integrity sha512-cr2k7u1XJJ4HTOjM9GyOMtbOA47RtUoWRAtt52z43r3AoMs2StYKyjS3URPhzHaf+mn10hY9dZWamga5WPQjhA== + dependencies: + "@babel/runtime" "^7.19.4" + i18next@^23.4.1: version "23.4.1" resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.4.1.tgz#11fe0db92ac8a4125934960ebccf6a5f8ed6b9fc" @@ -13772,6 +13786,11 @@ regenerator-runtime@^0.13.11, regenerator-runtime@^0.13.9: resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz" integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== +regenerator-runtime@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45" + integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== + regenerator-transform@^0.15.1: version "0.15.1" resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz" From a168dfcf44455ef4ce3216fcbe97b58e67e02806 Mon Sep 17 00:00:00 2001 From: Davlatov Shahzod Date: Fri, 18 Aug 2023 19:06:23 +0300 Subject: [PATCH 2/5] Change fallback language setting --- frontend/src/application.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/application.jsx b/frontend/src/application.jsx index 9e24d780..a9a9733d 100644 --- a/frontend/src/application.jsx +++ b/frontend/src/application.jsx @@ -19,7 +19,7 @@ export default async () => { .use(LanguageDetector) .use(initReactI18next) .init({ - ...(process.env.NODE_ENV === 'production' && { + ...(process.env.NODE_ENV !== 'development' && { fallbackLng: defaultLanguage, }), debug: false, From cde5a202d1e87a864967605284ee6868e7c9e7a1 Mon Sep 17 00:00:00 2001 From: Davlatov Shahzod Date: Sat, 19 Aug 2023 12:40:38 +0300 Subject: [PATCH 3/5] Add REACT_APP_NODE_ENV in playwright config --- frontend/src/application.jsx | 35 +++++++++++++++++++++++++---------- playwright.config.ts | 3 +++ 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/frontend/src/application.jsx b/frontend/src/application.jsx index a9a9733d..464f700e 100644 --- a/frontend/src/application.jsx +++ b/frontend/src/application.jsx @@ -15,16 +15,31 @@ import { rootReducer } from './slices'; export default async () => { const defaultLanguage = 'ru'; - await i18next - .use(LanguageDetector) - .use(initReactI18next) - .init({ - ...(process.env.NODE_ENV !== 'development' && { - fallbackLng: defaultLanguage, - }), - debug: false, - resources, - }); + const baseI18NextConfig = { debug: false, resources }; + + if (process.env.NODE_ENV === 'production') { + await i18next + .use(LanguageDetector) + .use(initReactI18next) + .init({ ...baseI18NextConfig, fallbackLng: defaultLanguage }); + } + + if ( + process.env.NODE_ENV === 'development' && + !process.env.REACT_APP_NODE_ENV + ) { + await i18next + .use(LanguageDetector) + .use(initReactI18next) + .init(baseI18NextConfig); + } + + if (process.env.REACT_APP_NODE_ENV === 'test') { + await i18next + .use(initReactI18next) + .init({ ...baseI18NextConfig, lng: defaultLanguage }); + } + const store = configureStore({ reducer: rootReducer, }); diff --git a/playwright.config.ts b/playwright.config.ts index d6825003..d6ea2a41 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -91,5 +91,8 @@ export default defineConfig({ command: 'npm run start', port: 3000, reuseExistingServer: !process.env.CI, + env: { + REACT_APP_NODE_ENV: 'test' + } }, }); From 87cf6959f5126a7f1682364e6bbc9058aed7d13c Mon Sep 17 00:00:00 2001 From: Davlatov Shahzod Date: Fri, 1 Sep 2023 18:23:07 +0300 Subject: [PATCH 4/5] Clean up --- frontend/src/application.jsx | 31 ++----------------------------- frontend/src/hooks/useLanguage.js | 5 +---- frontend/src/initI18next.js | 28 ++++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 33 deletions(-) create mode 100644 frontend/src/initI18next.js diff --git a/frontend/src/application.jsx b/frontend/src/application.jsx index 464f700e..4b59acf5 100644 --- a/frontend/src/application.jsx +++ b/frontend/src/application.jsx @@ -1,44 +1,17 @@ import { configureStore } from '@reduxjs/toolkit'; import * as Sentry from '@sentry/react'; -import i18next from 'i18next'; -import LanguageDetector from 'i18next-browser-languagedetector'; -import { initReactI18next } from 'react-i18next'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; import AppRoutes from './AppRoutes.jsx'; import ModalWindow from './components/Modals'; -import resources from './locales'; import AuthProvider from './providers/AuthProvider.jsx'; import SnippetsProvider from './providers/SnippetsProvider.jsx'; import { rootReducer } from './slices'; +import { initI18next } from './initI18next.js'; export default async () => { - const defaultLanguage = 'ru'; - const baseI18NextConfig = { debug: false, resources }; - - if (process.env.NODE_ENV === 'production') { - await i18next - .use(LanguageDetector) - .use(initReactI18next) - .init({ ...baseI18NextConfig, fallbackLng: defaultLanguage }); - } - - if ( - process.env.NODE_ENV === 'development' && - !process.env.REACT_APP_NODE_ENV - ) { - await i18next - .use(LanguageDetector) - .use(initReactI18next) - .init(baseI18NextConfig); - } - - if (process.env.REACT_APP_NODE_ENV === 'test') { - await i18next - .use(initReactI18next) - .init({ ...baseI18NextConfig, lng: defaultLanguage }); - } + initI18next(); const store = configureStore({ reducer: rootReducer, diff --git a/frontend/src/hooks/useLanguage.js b/frontend/src/hooks/useLanguage.js index 84a37657..9490ad49 100644 --- a/frontend/src/hooks/useLanguage.js +++ b/frontend/src/hooks/useLanguage.js @@ -1,10 +1,7 @@ import { useTranslation } from 'react-i18next'; import { useLayoutEffect, useState } from 'react'; -const AVAILABLE_LANGUAGES = ['en', 'ru']; -if (process.env.NODE_ENV !== 'production') { - AVAILABLE_LANGUAGES.push('dev'); -} +import { AVAILABLE_LANGUAGES } from '../initI18next'; const useLanguage = () => { const { i18n } = useTranslation(); diff --git a/frontend/src/initI18next.js b/frontend/src/initI18next.js new file mode 100644 index 00000000..d64def6d --- /dev/null +++ b/frontend/src/initI18next.js @@ -0,0 +1,28 @@ +import i18next from 'i18next'; +import LanguageDetector from 'i18next-browser-languagedetector'; +import { initReactI18next } from 'react-i18next'; + +import resources from './locales'; + +const defaultLanguage = 'ru'; +const baseI18NextConfig = { + debug: process.env.NODE_ENV === 'development', + resources, +}; + +export const AVAILABLE_LANGUAGES = ['en', 'ru']; + +export const initI18next = async () => { + if (process.env.REACT_APP_NODE_ENV === 'test') { + await i18next + .use(initReactI18next) + .init({ ...baseI18NextConfig, lng: defaultLanguage }); + + return; + } + + await i18next + .use(LanguageDetector) + .use(initReactI18next) + .init({ ...baseI18NextConfig, fallbackLng: defaultLanguage }); +}; From a6f201d2ee269bd8dba8e36de862b8e70c9955ab Mon Sep 17 00:00:00 2001 From: Davlatov Shahzod Date: Sun, 3 Sep 2023 19:42:09 +0300 Subject: [PATCH 5/5] await initI18next --- frontend/src/application.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/application.jsx b/frontend/src/application.jsx index 4b59acf5..d9b65916 100644 --- a/frontend/src/application.jsx +++ b/frontend/src/application.jsx @@ -11,7 +11,7 @@ import { rootReducer } from './slices'; import { initI18next } from './initI18next.js'; export default async () => { - initI18next(); + await initI18next(); const store = configureStore({ reducer: rootReducer,