mirror of
https://git.vectorsigma.ru/public/AdGuardHome.git
synced 2026-07-28 21:49:08 +00:00
fix language change
This commit is contained in:
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"client_settings": "Настройки клиентов"
|
"privacy_policy": "Политика конфиденциальности"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import escapeRegExp from 'lodash/escapeRegExp';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { compose } from 'redux';
|
import { compose } from 'redux';
|
||||||
import type { Dispatch } from 'redux';
|
import type { Dispatch } from 'redux';
|
||||||
import intl from 'panel/common/intl';
|
import intl, { type LocalesType } from 'panel/common/intl';
|
||||||
import {
|
import {
|
||||||
splitByNewLine,
|
splitByNewLine,
|
||||||
sortClients,
|
sortClients,
|
||||||
@@ -23,6 +23,7 @@ import {
|
|||||||
SETTINGS_NAMES,
|
SETTINGS_NAMES,
|
||||||
MANUAL_UPDATE_LINK,
|
MANUAL_UPDATE_LINK,
|
||||||
DISABLE_PROTECTION_TIMINGS,
|
DISABLE_PROTECTION_TIMINGS,
|
||||||
|
THEMES,
|
||||||
} from '../helpers/constants';
|
} from '../helpers/constants';
|
||||||
import { areEqualVersions } from '../helpers/version';
|
import { areEqualVersions } from '../helpers/version';
|
||||||
import { getTlsStatus } from './encryption';
|
import { getTlsStatus } from './encryption';
|
||||||
@@ -32,6 +33,7 @@ import { getFilteringStatus, setRules } from './filtering';
|
|||||||
|
|
||||||
type SafeSearchConfig = Record<string, boolean> & { enabled: boolean };
|
type SafeSearchConfig = Record<string, boolean> & { enabled: boolean };
|
||||||
type ToggleSettingKey = keyof typeof SETTINGS_NAMES;
|
type ToggleSettingKey = keyof typeof SETTINGS_NAMES;
|
||||||
|
type Theme = typeof THEMES[keyof typeof THEMES];
|
||||||
|
|
||||||
export const toggleSettingStatus = createAction<{
|
export const toggleSettingStatus = createAction<{
|
||||||
settingKey: ToggleSettingKey;
|
settingKey: ToggleSettingKey;
|
||||||
@@ -441,13 +443,13 @@ export const testUpstreamWithFormValues = (formValues: any) => async (dispatch:
|
|||||||
|
|
||||||
export const changeLanguageRequest = createAction('CHANGE_LANGUAGE_REQUEST');
|
export const changeLanguageRequest = createAction('CHANGE_LANGUAGE_REQUEST');
|
||||||
export const changeLanguageFailure = createAction('CHANGE_LANGUAGE_FAILURE');
|
export const changeLanguageFailure = createAction('CHANGE_LANGUAGE_FAILURE');
|
||||||
export const changeLanguageSuccess = createAction('CHANGE_LANGUAGE_SUCCESS');
|
export const changeLanguageSuccess = createAction<{ language: LocalesType }>('CHANGE_LANGUAGE_SUCCESS');
|
||||||
|
|
||||||
export const changeLanguage = (lang: any) => async (dispatch: any) => {
|
export const changeLanguage = (lang: LocalesType) => async (dispatch: Dispatch) => {
|
||||||
dispatch(changeLanguageRequest());
|
dispatch(changeLanguageRequest());
|
||||||
try {
|
try {
|
||||||
await apiClient.changeLanguage({ language: lang });
|
await apiClient.changeLanguage({ language: lang });
|
||||||
dispatch(changeLanguageSuccess());
|
dispatch(changeLanguageSuccess({ language: lang }));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
dispatch(addErrorToast({ error }));
|
dispatch(addErrorToast({ error }));
|
||||||
dispatch(changeLanguageFailure());
|
dispatch(changeLanguageFailure());
|
||||||
@@ -456,9 +458,9 @@ export const changeLanguage = (lang: any) => async (dispatch: any) => {
|
|||||||
|
|
||||||
export const changeThemeRequest = createAction('CHANGE_THEME_REQUEST');
|
export const changeThemeRequest = createAction('CHANGE_THEME_REQUEST');
|
||||||
export const changeThemeFailure = createAction('CHANGE_THEME_FAILURE');
|
export const changeThemeFailure = createAction('CHANGE_THEME_FAILURE');
|
||||||
export const changeThemeSuccess = createAction('CHANGE_THEME_SUCCESS');
|
export const changeThemeSuccess = createAction<{ theme: Theme }>('CHANGE_THEME_SUCCESS');
|
||||||
|
|
||||||
export const changeTheme = (theme: any) => async (dispatch: any) => {
|
export const changeTheme = (theme: Theme) => async (dispatch: Dispatch) => {
|
||||||
dispatch(changeThemeRequest());
|
dispatch(changeThemeRequest());
|
||||||
try {
|
try {
|
||||||
await apiClient.changeTheme({ theme });
|
await apiClient.changeTheme({ theme });
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
|
import type { LocalesType } from 'panel/common/intl';
|
||||||
|
|
||||||
import { BASE_URL } from '../../constants';
|
import { BASE_URL } from '../../constants';
|
||||||
|
|
||||||
import { getPathWithQueryString } from '../helpers/helpers';
|
import { getPathWithQueryString } from '../helpers/helpers';
|
||||||
@@ -7,6 +9,8 @@ import { QUERY_LOGS_PAGE_LIMIT, HTML_PAGES, R_PATH_LAST_PART, THEMES } from '../
|
|||||||
import i18n from '../i18n';
|
import i18n from '../i18n';
|
||||||
import { LANGUAGES } from '../helpers/twosky';
|
import { LANGUAGES } from '../helpers/twosky';
|
||||||
|
|
||||||
|
type Theme = typeof THEMES[keyof typeof THEMES];
|
||||||
|
|
||||||
class Api {
|
class Api {
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
|
|
||||||
@@ -258,8 +262,7 @@ class Api {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// Language
|
// Language
|
||||||
|
async changeLanguage(config: { language: LocalesType }) {
|
||||||
async changeLanguage(config: any) {
|
|
||||||
const profile = await this.getProfile();
|
const profile = await this.getProfile();
|
||||||
profile.language = config.language;
|
profile.language = config.language;
|
||||||
|
|
||||||
@@ -267,8 +270,7 @@ class Api {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Theme
|
// Theme
|
||||||
|
async changeTheme(config: { theme: Theme }) {
|
||||||
async changeTheme(config: any) {
|
|
||||||
const profile = await this.getProfile();
|
const profile = await this.getProfile();
|
||||||
profile.theme = config.theme;
|
profile.theme = config.theme;
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import ptPt from 'panel/__locales/pt-pt.json';
|
|||||||
import ru from 'panel/__locales/ru.json';
|
import ru from 'panel/__locales/ru.json';
|
||||||
import zhCn from 'panel/__locales/zh-cn.json';
|
import zhCn from 'panel/__locales/zh-cn.json';
|
||||||
import zhTw from 'panel/__locales/zh-tw.json';
|
import zhTw from 'panel/__locales/zh-tw.json';
|
||||||
|
import { LOCAL_STORAGE_KEYS, LocalStorageHelper } from 'panel/helpers/localStorageHelper';
|
||||||
|
|
||||||
export type LocalesType = ReturnType<I18nInterface['getUILanguage']>;
|
export type LocalesType = ReturnType<I18nInterface['getUILanguage']>;
|
||||||
|
|
||||||
@@ -37,14 +38,55 @@ const LOCALES = {
|
|||||||
|
|
||||||
const messages: LocalesTypes = LOCALES;
|
const messages: LocalesTypes = LOCALES;
|
||||||
|
|
||||||
export const i18n = (lang: LocalesType) => ({
|
const resolveLanguage = (lng: string): LocalesType => {
|
||||||
getMessage: (key: string) => messages[lang]?.[key] || '',
|
const l = lng.toLowerCase();
|
||||||
getUILanguage: () => (lang.includes('zh') ? 'zh' : lang),
|
|
||||||
getBaseMessage: (key: string) => messages.en![key] || key,
|
|
||||||
getBaseUILanguage: () => BASE_LOCALE as LocalesType,
|
|
||||||
});
|
|
||||||
|
|
||||||
let currentLanguage: LocalesType = BASE_LOCALE as LocalesType;
|
if (messages[l as LocalesType]) {
|
||||||
|
return l as LocalesType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chinese locales
|
||||||
|
if (l.startsWith('zh')) {
|
||||||
|
if (l.includes('tw') || l.includes('hk') || l.includes('mo')) {
|
||||||
|
return 'zh-tw' as LocalesType;
|
||||||
|
}
|
||||||
|
return 'zh-cn' as LocalesType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Portuguese locales
|
||||||
|
if (l.startsWith('pt')) {
|
||||||
|
if (l.includes('br')) {
|
||||||
|
return 'pt-br' as LocalesType;
|
||||||
|
}
|
||||||
|
return 'pt-pt' as LocalesType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try base language (e.g., en-us -> en)
|
||||||
|
const base = l.split('-')[0] as LocalesType;
|
||||||
|
if (messages[base]) {
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BASE_LOCALE as LocalesType;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const i18n = (lang: LocalesType) => {
|
||||||
|
const resolved = resolveLanguage(lang);
|
||||||
|
return {
|
||||||
|
getMessage: (key: string) => messages[resolved]?.[key] || '',
|
||||||
|
getUILanguage: () => resolved,
|
||||||
|
getBaseMessage: (key: string) => messages.en![key] || key,
|
||||||
|
getBaseUILanguage: () => BASE_LOCALE as LocalesType,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const detectedLanguage = (
|
||||||
|
(typeof window !== 'undefined' && typeof localStorage !== 'undefined' && LocalStorageHelper.getItem(LOCAL_STORAGE_KEYS.LANGUAGE)) ||
|
||||||
|
(typeof navigator !== 'undefined' && (navigator.language as string)) ||
|
||||||
|
BASE_LOCALE
|
||||||
|
) as LocalesType;
|
||||||
|
|
||||||
|
let currentLanguage: LocalesType = resolveLanguage(detectedLanguage);
|
||||||
|
|
||||||
let translator = translate.createReactTranslator<any>(i18n(currentLanguage), React, {
|
let translator = translate.createReactTranslator<any>(i18n(currentLanguage), React, {
|
||||||
tags: [
|
tags: [
|
||||||
@@ -77,8 +119,9 @@ const intl = {
|
|||||||
getBaseUILanguage: () => BASE_LOCALE as LocalesType,
|
getBaseUILanguage: () => BASE_LOCALE as LocalesType,
|
||||||
|
|
||||||
changeLanguage: (newLang: LocalesType) => {
|
changeLanguage: (newLang: LocalesType) => {
|
||||||
currentLanguage = newLang;
|
const resolved = resolveLanguage(newLang);
|
||||||
translator = translate.createReactTranslator<any>(i18n(newLang), React, {
|
currentLanguage = resolved;
|
||||||
|
translator = translate.createReactTranslator<any>(i18n(resolved), React, {
|
||||||
tags: [
|
tags: [
|
||||||
{
|
{
|
||||||
key: 'br',
|
key: 'br',
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { Dropdown } from 'panel/common/ui/Dropdown';
|
|||||||
import { Icon } from 'panel/common/ui/Icon';
|
import { Icon } from 'panel/common/ui/Icon';
|
||||||
import intl, { LocalesType } from 'panel/common/intl';
|
import intl, { LocalesType } from 'panel/common/intl';
|
||||||
|
|
||||||
|
import { LOCAL_STORAGE_KEYS, LocalStorageHelper } from 'panel/helpers/localStorageHelper';
|
||||||
import { REPOSITORY, PRIVACY_POLICY_LINK, THEMES } from '../../../helpers/constants';
|
import { REPOSITORY, PRIVACY_POLICY_LINK, THEMES } from '../../../helpers/constants';
|
||||||
import { LANGUAGES } from '../../../helpers/twosky';
|
import { LANGUAGES } from '../../../helpers/twosky';
|
||||||
import { setHtmlLangAttr, setUITheme } from '../../../helpers/helpers';
|
import { setHtmlLangAttr, setUITheme } from '../../../helpers/helpers';
|
||||||
@@ -73,11 +74,11 @@ export const Footer = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const changeLanguage = async (newLang: LocalesType) => {
|
const changeLanguage = async (newLang: LocalesType) => {
|
||||||
intl.changeLanguage(newLang);
|
|
||||||
setHtmlLangAttr(newLang);
|
setHtmlLangAttr(newLang);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await dispatch(changeLanguageAction(newLang));
|
await dispatch(changeLanguageAction(newLang));
|
||||||
|
LocalStorageHelper.setItem(LOCAL_STORAGE_KEYS.LANGUAGE, newLang);
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to save language preference:', error);
|
console.error('Failed to save language preference:', error);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ export const LOCAL_STORAGE_KEYS = {
|
|||||||
CLIENTS_PAGE_SIZE: 'clients_page_size',
|
CLIENTS_PAGE_SIZE: 'clients_page_size',
|
||||||
REWRITES_PAGE_SIZE: 'rewrites_page_size',
|
REWRITES_PAGE_SIZE: 'rewrites_page_size',
|
||||||
AUTO_CLIENTS_PAGE_SIZE: 'auto_clients_page_size',
|
AUTO_CLIENTS_PAGE_SIZE: 'auto_clients_page_size',
|
||||||
|
LANGUAGE: 'language',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const LocalStorageHelper = {
|
export const LocalStorageHelper = {
|
||||||
|
|||||||
@@ -163,6 +163,10 @@ const dashboard = handleActions(
|
|||||||
theme: payload.theme,
|
theme: payload.theme,
|
||||||
processingProfile: false,
|
processingProfile: false,
|
||||||
}),
|
}),
|
||||||
|
[actions.changeLanguageSuccess.toString()]: (state, { payload }: any) => ({
|
||||||
|
...state,
|
||||||
|
language: payload.language,
|
||||||
|
}),
|
||||||
[actions.changeThemeSuccess.toString()]: (state, { payload }: any) => ({
|
[actions.changeThemeSuccess.toString()]: (state, { payload }: any) => ({
|
||||||
...state,
|
...state,
|
||||||
theme: payload.theme,
|
theme: payload.theme,
|
||||||
@@ -188,6 +192,7 @@ const dashboard = handleActions(
|
|||||||
supportedTags: [],
|
supportedTags: [],
|
||||||
name: '',
|
name: '',
|
||||||
theme: undefined,
|
theme: undefined,
|
||||||
|
language: undefined,
|
||||||
checkUpdateFlag: false,
|
checkUpdateFlag: false,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user