diff --git a/client/package-lock.json b/client/package-lock.json index a81a568..838d78d 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -18,8 +18,11 @@ "@types/react": "^19.0.11", "@types/react-dom": "^19.0.4", "antd": "^5.24.7", + "i18next": "^25.0.1", + "i18next-browser-languagedetector": "^8.0.5", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-i18next": "^15.5.1", "react-router-dom": "^7.5.0", "react-scripts": "5.0.1", "typescript": "^4.9.5", @@ -9351,6 +9354,15 @@ "node": ">=12" } }, + "node_modules/html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "license": "MIT", + "dependencies": { + "void-elements": "3.1.0" + } + }, "node_modules/html-webpack-plugin": { "version": "5.6.3", "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.3.tgz", @@ -9504,6 +9516,46 @@ "node": ">=10.17.0" } }, + "node_modules/i18next": { + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.0.1.tgz", + "integrity": "sha512-8S8PyZbrymJZn3DaN70/34JYWNhsqrU6yA4MuzcygJBv+41dgNMocEA8h+kV1P7MCc1ll03lOTOIXE7mpNCicw==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.10" + }, + "peerDependencies": { + "typescript": "^5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/i18next-browser-languagedetector": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.5.tgz", + "integrity": "sha512-OstebRKqKiQw8xEvQF5aRyUujsCatanj7Q9eo5iiH2gJpoXGZ7483ol3sVBwfqbobTQPNH1J+NAyJ1aCQoEC+w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -14931,6 +14983,32 @@ "integrity": "sha512-SN/U6Ytxf1QGkw/9ve5Y+NxBbZM6Ht95tuXNMKs8EJyFa/Vy/+Co3stop3KBHARfn/giv+Lj1uUnTfOJ3moFEQ==", "license": "MIT" }, + "node_modules/react-i18next": { + "version": "15.5.1", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.5.1.tgz", + "integrity": "sha512-C8RZ7N7H0L+flitiX6ASjq9p5puVJU1Z8VyL3OgM/QOMRf40BMZX+5TkpxzZVcTmOLPX5zlti4InEX5pFyiVeA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.0", + "html-parse-stringify": "^3.0.1" + }, + "peerDependencies": { + "i18next": ">= 23.2.3", + "react": ">= 16.8.0", + "typescript": "^5" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", @@ -17720,6 +17798,15 @@ "node": ">= 0.8" } }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", diff --git a/client/package.json b/client/package.json index 197b1db..956c0ce 100644 --- a/client/package.json +++ b/client/package.json @@ -13,8 +13,11 @@ "@types/react": "^19.0.11", "@types/react-dom": "^19.0.4", "antd": "^5.24.7", + "i18next": "^25.0.1", + "i18next-browser-languagedetector": "^8.0.5", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-i18next": "^15.5.1", "react-router-dom": "^7.5.0", "react-scripts": "5.0.1", "typescript": "^4.9.5", diff --git a/client/src/components/SiderMenu.tsx b/client/src/components/SiderMenu.tsx index 8403cf0..8ce7ab4 100644 --- a/client/src/components/SiderMenu.tsx +++ b/client/src/components/SiderMenu.tsx @@ -1,5 +1,6 @@ import { Divider, Menu, Tooltip } from 'antd'; import React from 'react'; +import { useTranslation } from 'react-i18next'; interface SiderMenuProps { collapsed: boolean; @@ -12,6 +13,7 @@ export default function SiderMenu({ selectedKey, hangleMenuClick, }: SiderMenuProps) { + const { t } = useTranslation(); const collapseStyle = collapsed ? { fontSize: '12px' } : { fontSize: '12px', paddingLeft: '52px' }; @@ -37,7 +39,9 @@ export default function SiderMenu({ icon: ( process diagram ), - label: Схемы процессов, + label: ( + {t('processDiagrams')} + ), }, { key: '/running-processes', @@ -47,7 +51,9 @@ export default function SiderMenu({ alt="running processes" /> ), - label: Запущенные процессы, + label: ( + {t('runningProcesses')} + ), }, !collapsed ? { @@ -65,33 +71,33 @@ export default function SiderMenu({ { key: 'sub1', icon: settings, - label: 'Настройки', + label: t('settings'), className: 'no-expand-icon', children: [ { key: '/accounts', label: !collapsed ? ( - Учетные записи + {t('accounts')} ) : ( - 'Учетные записи' + t('accounts') ), style: collapseStyle, }, { key: '/events-list', label: !collapsed ? ( - Справочник событий + {t('eventsList')} ) : ( - 'Справочник событий' + t('eventsList') ), style: collapseStyle, }, { key: '/configuration', label: !collapsed ? ( - Конфигурация + {t('configuration')} ) : ( - 'Конфигурация' + t('configuration') ), style: collapseStyle, }, diff --git a/client/src/index.tsx b/client/src/index.tsx index cceac43..2631204 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -3,17 +3,16 @@ import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import { BrowserRouter } from 'react-router-dom'; -import { ConfigProvider } from 'antd'; -import { theme } from './config/customTheme'; +import AppWrapper from './config/AppWrapper'; const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement ); root.render( - + - + ); diff --git a/client/src/pages/AccountsPage.tsx b/client/src/pages/AccountsPage.tsx index aa6a98e..4387052 100644 --- a/client/src/pages/AccountsPage.tsx +++ b/client/src/pages/AccountsPage.tsx @@ -2,8 +2,10 @@ import Header from '../components/Header'; import { useState } from 'react'; import ContentDrawer from '../components/ContentDrawer'; import UserCreate from '../components/UserCreate'; +import { useTranslation } from 'react-i18next'; export default function AccountsPage() { + const { t } = useTranslation(); const [open, setOpen] = useState(false); const showDrawer = () => setOpen(true); @@ -12,7 +14,7 @@ export default function AccountsPage() { return ( <>