From e58c47c205604f2b2aca6d24eb863bd2c3adf115 Mon Sep 17 00:00:00 2001 From: cihatata Date: Mon, 5 May 2025 23:55:21 +0300 Subject: [PATCH 1/4] fix: language detection --- client/src/App.jsx | 25 ------------------------- client/src/Features/UI/uiSlice.js | 2 +- client/src/Pages/Auth/Login/Login.jsx | 12 +++++++++--- client/src/Utils/NetworkService.js | 4 ++-- client/src/Utils/i18n.js | 3 ++- client/src/locales/gb.json | 3 ++- client/src/locales/ru.json | 3 ++- client/src/locales/tr.json | 3 ++- 8 files changed, 20 insertions(+), 35 deletions(-) diff --git a/client/src/App.jsx b/client/src/App.jsx index 1d5709847..7fb63ee61 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -1,43 +1,18 @@ import { useEffect } from "react"; import { useSelector } from "react-redux"; -import { useDispatch } from "react-redux"; import "react-toastify/dist/ReactToastify.css"; import { ToastContainer } from "react-toastify"; import { ThemeProvider } from "@emotion/react"; import lightTheme from "./Utils/Theme/lightTheme"; import darkTheme from "./Utils/Theme/darkTheme"; import { CssBaseline, GlobalStyles } from "@mui/material"; -import { getAppSettings } from "./Features/Settings/settingsSlice"; import { logger } from "./Utils/Logger"; // Import the logger import { networkService } from "./main"; import { Routes } from "./Routes"; import WalletProvider from "./Components/WalletProvider"; -import { useTranslation } from "react-i18next"; -import { setLanguage } from "./Features/UI/uiSlice"; function App() { const mode = useSelector((state) => state.ui.mode); - const { authToken } = useSelector((state) => state.auth); - const dispatch = useDispatch(); - const { i18n } = useTranslation(); - - useEffect(() => { - if (authToken) { - dispatch(getAppSettings({ authToken })).then((action) => { - if (action.payload && action.payload.success) { - const { language } = action.payload.data; - const availableLanguages = Object.keys(i18n.options.resources || {}); - if (language && availableLanguages.includes(language)) { - dispatch(setLanguage(language)); - i18n.changeLanguage(language); - } else { - dispatch(setLanguage(availableLanguages[0])); - i18n.changeLanguage(availableLanguages[0]); - } - } - }); - } - }, [dispatch, authToken, i18n]); // Cleanup useEffect(() => { diff --git a/client/src/Features/UI/uiSlice.js b/client/src/Features/UI/uiSlice.js index f20115b92..1fc2f865d 100644 --- a/client/src/Features/UI/uiSlice.js +++ b/client/src/Features/UI/uiSlice.js @@ -23,7 +23,7 @@ const initialState = { greeting: { index: 0, lastUpdate: null }, timezone: "America/Toronto", distributedUptimeEnabled: false, - language: "gb", + language: localStorage.getItem("app_language") || "gb", starPromptOpen: true, }; diff --git a/client/src/Pages/Auth/Login/Login.jsx b/client/src/Pages/Auth/Login/Login.jsx index 9db56ae49..1337a8723 100644 --- a/client/src/Pages/Auth/Login/Login.jsx +++ b/client/src/Pages/Auth/Login/Login.jsx @@ -16,6 +16,7 @@ import PasswordStep from "./Components/PasswordStep"; import ThemeSwitch from "../../../Components/ThemeSwitch"; import ForgotPasswordLabel from "./Components/ForgotPasswordLabel"; import LanguageSelector from "../../../Components/LanguageSelector"; +import { useTranslation } from "react-i18next"; const DEMO = import.meta.env.VITE_APP_DEMO; @@ -27,6 +28,7 @@ const Login = () => { const dispatch = useDispatch(); const navigate = useNavigate(); const theme = useTheme(); + const { t } = useTranslation(); const authState = useSelector((state) => state.auth); const { authToken } = authState; @@ -63,13 +65,17 @@ const Login = () => { const handleChange = (event) => { const { value, id } = event.target; const name = idMap[id]; - const lowerCasedValue = name === idMap["login-email-input"]? value?.toLowerCase()||value : value + const lowerCasedValue = + name === idMap["login-email-input"] ? value?.toLowerCase() || value : value; setForm((prev) => ({ ...prev, [name]: lowerCasedValue, })); - const { error } = credentials.validate({ [name]: lowerCasedValue }, { abortEarly: false }); + const { error } = credentials.validate( + { [name]: lowerCasedValue }, + { abortEarly: false } + ); setErrors((prev) => { const prevErrors = { ...prev }; @@ -114,7 +120,7 @@ const Login = () => { if (action.payload.success) { navigate("/uptime"); createToast({ - body: "Welcome back! You're successfully logged in.", + body: t("welcomeBack"), }); } else { if (action.payload) { diff --git a/client/src/Utils/NetworkService.js b/client/src/Utils/NetworkService.js index 7c4ffba9f..52e3aae69 100644 --- a/client/src/Utils/NetworkService.js +++ b/client/src/Utils/NetworkService.js @@ -32,7 +32,7 @@ class NetworkService { config.headers = { Authorization: `Bearer ${authToken}`, - "Accept-Language": currentLanguage, + "Accept-Language": currentLanguage === "gb" ? "en" : currentLanguage, ...config.headers, }; @@ -920,7 +920,7 @@ class NetworkService { onOpen?.(); }; - this.eventSource.addEventListener("open", (e) => {}); + this.eventSource.addEventListener("open", (e) => { }); this.eventSource.onmessage = (event) => { const data = JSON.parse(event.data); diff --git a/client/src/Utils/i18n.js b/client/src/Utils/i18n.js index 6243a2599..a2e84f1dc 100644 --- a/client/src/Utils/i18n.js +++ b/client/src/Utils/i18n.js @@ -16,7 +16,7 @@ Object.keys(translations).forEach((path) => { }); const savedLanguage = store.getState()?.ui?.language; -const initialLanguage = savedLanguage || primaryLanguage; +const initialLanguage = savedLanguage; i18n.use(initReactI18next).init({ resources, @@ -32,6 +32,7 @@ i18n.use(initReactI18next).init({ i18n.on("languageChanged", (lng) => { store.dispatch(setLanguage(lng)); + window.localStorage.setItem("app_language", lng); }); export default i18n; diff --git a/client/src/locales/gb.json b/client/src/locales/gb.json index 95ef6d32e..4d5ac89c1 100644 --- a/client/src/locales/gb.json +++ b/client/src/locales/gb.json @@ -18,6 +18,7 @@ "createAPassword": "Create a password", "authRegisterAlreadyHaveAccount": "Already have an account?", "commonAppName": "Checkmate", + "welcomeBack": "Welcome back! You're successfully logged in.", "authLoginEnterEmail": "Enter your email", "authRegisterTitle": "Create an account", "authRegisterStepOneTitle": "Create your account", @@ -396,4 +397,4 @@ "DeleteDescriptionText": "Note that deleting your account will remove all data from the server. This is permanent and non-recoverable.", "DeleteAccountWarning": "If you delete your account, you will no longer be able to sign in, and all of your data will be deleted. Deleting your account is permanent and non-recoverable action.", "DeleteWarningTitle": "Really delete this account?" -} +} \ No newline at end of file diff --git a/client/src/locales/ru.json b/client/src/locales/ru.json index 5d0f649de..76c8c28bd 100644 --- a/client/src/locales/ru.json +++ b/client/src/locales/ru.json @@ -18,6 +18,7 @@ "createAPassword": "Создайте пароль", "authRegisterAlreadyHaveAccount": "Уже есть аккаунт?", "commonAppName": "Checkmate", + "welcomeBack": "Добро пожаловать обратно! Вы успешно вошли в систему.", "authLoginEnterEmail": "Введите свой email", "authRegisterTitle": "Создать аккаунт", "authRegisterStepOneTitle": "Создайте свой аккаут", @@ -364,4 +365,4 @@ "pageSpeedWarning": "Предупреждение: Вы не добавили ключ API Google PageSpeed. Без него монитор PageSpeed не будет работать.", "pageSpeedLearnMoreLink": "Нажмите здесь, чтобы узнать", "pageSpeedAddApiKey": "как добавить ваш ключ API." -} +} \ No newline at end of file diff --git a/client/src/locales/tr.json b/client/src/locales/tr.json index d975d056c..6d89cab94 100644 --- a/client/src/locales/tr.json +++ b/client/src/locales/tr.json @@ -18,6 +18,7 @@ "createAPassword": "Bir parola oluşturun", "authRegisterAlreadyHaveAccount": "Zaten hesabınız var mı?", "commonAppName": "Checkmate", + "welcomeBack": "Tekrar hoş geldiniz! Başarıyla giriş yaptınız.", "authLoginEnterEmail": "E-posta adresinizi girin", "authRegisterTitle": "Hesap oluştur", "authRegisterStepOneTitle": "Hesabınızı oluşturun", @@ -396,4 +397,4 @@ "DeleteDescriptionText": "", "DeleteAccountWarning": "", "DeleteWarningTitle": "" -} +} \ No newline at end of file From 16e014a6fedd93e798249afc6948a171ecb0b69d Mon Sep 17 00:00:00 2001 From: cihatata Date: Mon, 5 May 2025 23:55:56 +0300 Subject: [PATCH 2/4] fix: language detection - server --- server/db/models/AppSettings.js | 4 ---- server/middleware/languageMiddleware.js | 12 +++--------- server/service/settingsService.js | 1 - 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/server/db/models/AppSettings.js b/server/db/models/AppSettings.js index 26ba6f254..6415b229d 100755 --- a/server/db/models/AppSettings.js +++ b/server/db/models/AppSettings.js @@ -7,10 +7,6 @@ const AppSettingsSchema = mongoose.Schema( required: true, default: "http://localhost:5000/api/v1", }, - language: { - type: String, - default: "en", - }, logLevel: { type: String, default: "debug", diff --git a/server/middleware/languageMiddleware.js b/server/middleware/languageMiddleware.js index fd32ee818..1449e203f 100755 --- a/server/middleware/languageMiddleware.js +++ b/server/middleware/languageMiddleware.js @@ -1,16 +1,10 @@ import logger from "../utils/logger.js"; const languageMiddleware = - (stringService, translationService, settingsService) => async (req, res, next) => { + (stringService, translationService) => async (req, res, next) => { try { - const settings = await settingsService.getSettings(); - - let language = settings && settings.language ? settings.language : null; - - if (!language) { - const acceptLanguage = req.headers["accept-language"] || "en"; - language = acceptLanguage.split(",")[0].slice(0, 2).toLowerCase(); - } + const acceptLanguage = req.headers["accept-language"] || "en"; + const language = acceptLanguage.split(",")[0].slice(0, 2).toLowerCase(); translationService.setLanguage(language); stringService.setLanguage(language); diff --git a/server/service/settingsService.js b/server/service/settingsService.js index 1443755f9..6c7beb456 100755 --- a/server/service/settingsService.js +++ b/server/service/settingsService.js @@ -3,7 +3,6 @@ import dotenv from "dotenv"; dotenv.config(); const envConfig = { logLevel: process.env.LOG_LEVEL, - language: process.env.LANGUAGE, clientHost: process.env.CLIENT_HOST, jwtSecret: process.env.JWT_SECRET, dbType: process.env.DB_TYPE, From 82b9dcea4fdf0f3a7b97a1049d07c484addeabcf Mon Sep 17 00:00:00 2001 From: cihatata Date: Tue, 6 May 2025 00:09:49 +0300 Subject: [PATCH 3/4] fix: remove cron --- .github/workflows/poeditor-sync.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/poeditor-sync.yml b/.github/workflows/poeditor-sync.yml index 96f735100..8446745bc 100644 --- a/.github/workflows/poeditor-sync.yml +++ b/.github/workflows/poeditor-sync.yml @@ -13,9 +13,6 @@ on: required: false default: "key_value_json" - # For automatic execution at a specific time (every day at midnight) - schedule: - - cron: "0 0 * * *" permissions: contents: write From f5a0932489f910ff7cdde8ecac9ae8283fc9d59e Mon Sep 17 00:00:00 2001 From: cihatata Date: Tue, 6 May 2025 00:29:58 +0300 Subject: [PATCH 4/4] fix: remove localstorage usage --- client/src/Features/Settings/settingsSlice.js | 2 +- client/src/Features/UI/uiSlice.js | 2 +- client/src/Utils/i18n.js | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/client/src/Features/Settings/settingsSlice.js b/client/src/Features/Settings/settingsSlice.js index 614ab7159..967858901 100644 --- a/client/src/Features/Settings/settingsSlice.js +++ b/client/src/Features/Settings/settingsSlice.js @@ -5,7 +5,7 @@ const initialState = { isLoading: false, apiBaseUrl: "", logLevel: "debug", - language: "", + language: "gb", }; export const getAppSettings = createAsyncThunk( diff --git a/client/src/Features/UI/uiSlice.js b/client/src/Features/UI/uiSlice.js index 1fc2f865d..f20115b92 100644 --- a/client/src/Features/UI/uiSlice.js +++ b/client/src/Features/UI/uiSlice.js @@ -23,7 +23,7 @@ const initialState = { greeting: { index: 0, lastUpdate: null }, timezone: "America/Toronto", distributedUptimeEnabled: false, - language: localStorage.getItem("app_language") || "gb", + language: "gb", starPromptOpen: true, }; diff --git a/client/src/Utils/i18n.js b/client/src/Utils/i18n.js index a2e84f1dc..985762a4e 100644 --- a/client/src/Utils/i18n.js +++ b/client/src/Utils/i18n.js @@ -32,7 +32,6 @@ i18n.use(initReactI18next).init({ i18n.on("languageChanged", (lng) => { store.dispatch(setLanguage(lng)); - window.localStorage.setItem("app_language", lng); }); export default i18n;