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: (
),
- 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:
,
- 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 (
<>