diff --git a/client_v2/postcss.config.js b/client_v2/postcss.config.js index 0f75c564..79285b47 100644 --- a/client_v2/postcss.config.js +++ b/client_v2/postcss.config.js @@ -1,13 +1,7 @@ import autoprefixer from 'autoprefixer'; import postcssImport from 'postcss-import'; -import postcssCustomMedia from 'postcss-custom-media'; import postcssNested from 'postcss-nested'; export default { - plugins: [ - postcssImport(), - postcssCustomMedia(), - postcssNested(), - autoprefixer({ overrideBrowserslist: ['last 2 versions'] }), - ], + plugins: [postcssImport(), postcssNested(), autoprefixer({ overrideBrowserslist: ['last 2 versions'] })], }; diff --git a/client_v2/src/api/Api.ts b/client_v2/src/api/Api.ts index 58ea0f81..89acf6a5 100644 --- a/client_v2/src/api/Api.ts +++ b/client_v2/src/api/Api.ts @@ -634,6 +634,13 @@ class Api { return this.makeRequest(path, method, config); } + // Logout + LOGOUT_PATH = 'logout'; + + getLogoutUrl() { + return `${this.baseUrl}/${this.LOGOUT_PATH}`; + } + // Profile GET_PROFILE = { path: 'profile', method: 'GET' }; diff --git a/client_v2/src/common/intl/index.ts b/client_v2/src/common/intl/index.ts index 185e8b51..44f2fa11 100644 --- a/client_v2/src/common/intl/index.ts +++ b/client_v2/src/common/intl/index.ts @@ -1,19 +1,20 @@ import React from 'react'; import { I18nInterface, translate } from '@adguard/translate'; +import { BASE_LOCALE } from 'panel/helpers/twosky'; -import en from '../../__locales/en.json'; -import de from '../../__locales/de.json'; -import es from '../../__locales/es.json'; -import fr from '../../__locales/fr.json'; -import it from '../../__locales/it.json'; -import ja from '../../__locales/ja.json'; -import ko from '../../__locales/ko.json'; -import ptBr from '../../__locales/pt-br.json'; -import ptPt from '../../__locales/pt-pt.json'; -import ru from '../../__locales/ru.json'; -import zhCn from '../../__locales/zh-cn.json'; -import zhTw from '../../__locales/zh-tw.json'; +import en from 'panel/__locales/en.json'; +import de from 'panel/__locales/de.json'; +import es from 'panel/__locales/es.json'; +import fr from 'panel/__locales/fr.json'; +import it from 'panel/__locales/it.json'; +import ja from 'panel/__locales/ja.json'; +import ko from 'panel/__locales/ko.json'; +import ptBr from 'panel/__locales/pt-br.json'; +import ptPt from 'panel/__locales/pt-pt.json'; +import ru from 'panel/__locales/ru.json'; +import zhCn from 'panel/__locales/zh-cn.json'; +import zhTw from 'panel/__locales/zh-tw.json'; export type LocalesType = ReturnType; @@ -40,10 +41,10 @@ export const i18n = (lang: LocalesType) => ({ getMessage: (key: string) => messages[lang]?.[key] || '', getUILanguage: () => (lang.includes('zh') ? 'zh' : lang), getBaseMessage: (key: string) => messages.en![key] || key, - getBaseUILanguage: () => 'en' as LocalesType, + getBaseUILanguage: () => BASE_LOCALE as LocalesType, }); -let currentLanguage: LocalesType = 'en'; +let currentLanguage: LocalesType = BASE_LOCALE as LocalesType; let translator = translate.createReactTranslator(i18n(currentLanguage), React, { tags: [ @@ -69,7 +70,7 @@ const intl = { return messages.en?.[key] || key; }, - getBaseUILanguage: () => 'en' as LocalesType, + getBaseUILanguage: () => BASE_LOCALE as LocalesType, changeLanguage: (newLang: LocalesType) => { currentLanguage = newLang; diff --git a/client_v2/src/common/ui/Footer/Footer.tsx b/client_v2/src/common/ui/Footer/Footer.tsx index a390e066..8a3a4fc5 100644 --- a/client_v2/src/common/ui/Footer/Footer.tsx +++ b/client_v2/src/common/ui/Footer/Footer.tsx @@ -9,7 +9,7 @@ import { Icon } from 'panel/common/ui/Icon'; import { REPOSITORY, PRIVACY_POLICY_LINK, THEMES } from '../../../helpers/constants'; import { LANGUAGES } from '../../../helpers/twosky'; import { setHtmlLangAttr, setUITheme } from '../../../helpers/helpers'; -import { changeTheme } from '../../../actions'; +import { changeTheme, changeLanguage as changeLanguageAction } from '../../../actions'; import { RootState } from '../../../initialState'; import s from './styles.module.pcss'; @@ -41,6 +41,8 @@ export const Footer = () => { const currentTheme = useSelector((state: RootState) => (state.dashboard ? state.dashboard.theme : THEMES.auto)); const profileName = useSelector((state: RootState) => (state.dashboard ? state.dashboard.name : '')); + const currentLanguage = + useSelector((state: RootState) => (state.dashboard ? state.dashboard.language : '')) || intl.getUILanguage(); const isLoggedIn = profileName !== ''; const [currentThemeLocal, setCurrentThemeLocal] = useState(THEMES.auto); const [themeDropdownOpen, setThemeDropdownOpen] = useState(false); @@ -70,10 +72,16 @@ export const Footer = () => { return 'theme_light'; }; - const changeLanguage = (newLang: LocalesType) => { + const changeLanguage = async (newLang: LocalesType) => { intl.changeLanguage(newLang); setHtmlLangAttr(newLang); - window.location.reload(); + + try { + await dispatch(changeLanguageAction(newLang)); + window.location.reload(); + } catch (error) { + console.error('Failed to save language preference:', error); + } }; const onThemeChange = (value: string) => { @@ -146,7 +154,7 @@ export const Footer = () => { type="button" key={lang} className={cn(theme.dropdown.item, { - [theme.dropdown.item_active]: intl.getUILanguage() === lang, + [theme.dropdown.item_active]: currentLanguage === lang, })} onClick={() => changeLanguage(lang as LocalesType)}> {LANGUAGES[lang]} @@ -159,7 +167,7 @@ export const Footer = () => { position="bottomRight">
- {LANGUAGES[intl.getUILanguage()]} + {LANGUAGES[currentLanguage] || LANGUAGES[intl.getUILanguage()]}
diff --git a/client_v2/src/common/ui/Menu/Menu.tsx b/client_v2/src/common/ui/Menu/Menu.tsx index f1207179..bce10a52 100644 --- a/client_v2/src/common/ui/Menu/Menu.tsx +++ b/client_v2/src/common/ui/Menu/Menu.tsx @@ -6,6 +6,7 @@ import { Link } from 'panel/common/ui/Link'; import { Paths, RoutePath } from 'panel/components/Routes/Paths'; import theme from 'panel/lib/theme'; import intl from 'panel/common/intl'; +import { apiClient } from 'panel/api/Api'; import { AccordionSection } from './AccordionSection'; import s from './styles.module.pcss'; @@ -123,7 +124,7 @@ export const Menu = ({ headerMenu }: Props) => {
- + {intl.getMessage('logout')} diff --git a/client_v2/src/index.pcss b/client_v2/src/index.pcss index fdc88d39..e9917585 100644 --- a/client_v2/src/index.pcss +++ b/client_v2/src/index.pcss @@ -1,4 +1,3 @@ -@import './common/styles/custom-media.pcss'; @import './common/styles/vars.css'; @import './common/styles/colors/light.css'; @import './common/styles/colors/dark.css'; @@ -6,10 +5,12 @@ :root { --font-family-monospace: Monaco, Menlo, 'Ubuntu Mono', Consolas, source-code-pro, monospace; - --font-family-system: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif + --font-family-system: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif; } -*, *::after, *::before { +*, +*::after, +*::before { box-sizing: border-box; } @@ -36,6 +37,11 @@ select { font-family: var(--font-family-system); } -h1, h2, h3, h4, h5, h6 { +h1, +h2, +h3, +h4, +h5, +h6 { margin: 0; }