From 03829aacc66d2d8b2835b6d23cc6ba24214fac8f Mon Sep 17 00:00:00 2001
From: itoshi <kkzemeow@gmail.com>
Date: Tue, 29 Apr 2025 21:16:53 +0300
Subject: [PATCH] station edit in the route edit page

---
 src/components/CustomDataGrid.tsx             |  10 +-
 src/components/LanguageSwitch/index.tsx       |  70 +++
 src/components/LinkedItems.tsx                | 511 +++++++++---------
 src/components/index.ts                       |   1 -
 .../modals/ArticleEditModal/index.tsx         | 171 ++++++
 .../modals/StationEditModal/index.tsx         | 164 ++++++
 src/pages/article/edit.tsx                    |  28 +-
 src/pages/article/list.tsx                    |  87 +--
 src/pages/carrier/create.tsx                  | 195 ++++---
 src/pages/carrier/list.tsx                    |  10 +-
 src/pages/city/list.tsx                       | 104 ++--
 src/pages/country/list.tsx                    |  82 ++-
 src/pages/sight/create.tsx                    |  49 +-
 src/pages/sight/edit.tsx                      | 398 +++++++++-----
 src/pages/sight/list.tsx                      |  15 +-
 src/pages/station/edit.tsx                    | 173 +++++-
 src/pages/station/list.tsx                    |  10 +-
 src/pages/vehicle/edit.tsx                    | 111 ++--
 src/pages/vehicle/list.tsx                    | 133 +++--
 src/store/ArticleStore.ts                     |  20 +
 src/store/StationStore.ts                     |  20 +
 21 files changed, 1642 insertions(+), 720 deletions(-)
 create mode 100644 src/components/LanguageSwitch/index.tsx
 delete mode 100644 src/components/index.ts
 create mode 100644 src/components/modals/ArticleEditModal/index.tsx
 create mode 100644 src/components/modals/StationEditModal/index.tsx
 create mode 100644 src/store/ArticleStore.ts
 create mode 100644 src/store/StationStore.ts

diff --git a/src/components/CustomDataGrid.tsx b/src/components/CustomDataGrid.tsx
index 88594cf..888dfc9 100644
--- a/src/components/CustomDataGrid.tsx
+++ b/src/components/CustomDataGrid.tsx
@@ -3,17 +3,20 @@ import {
   type DataGridProps,
   type GridColumnVisibilityModel,
 } from "@mui/x-data-grid";
-import { Stack, Button, Typography } from "@mui/material";
+import { Stack, Button, Typography, Box } from "@mui/material";
 import { ExportButton } from "@refinedev/mui";
 import { useExport } from "@refinedev/core";
 import React, { useState, useEffect, useMemo } from "react";
 import Cookies from "js-cookie";
 
 import { localeText } from "../locales/ru/localeText";
+import { languageStore } from "../store/LanguageStore";
+import { LanguageSwitch } from "./LanguageSwitch";
 
 interface CustomDataGridProps extends DataGridProps {
   hasCoordinates?: boolean;
   resource?: string; // Add this prop
+  languageEnabled?: boolean;
 }
 
 const DEV_FIELDS = [
@@ -46,6 +49,7 @@ const DEV_FIELDS = [
 ] as const;
 
 export const CustomDataGrid = ({
+  languageEnabled = false,
   hasCoordinates = false,
   columns = [],
   resource,
@@ -130,6 +134,9 @@ export const CustomDataGrid = ({
 
   return (
     <Stack spacing={2}>
+      <Box sx={{ visibility: languageEnabled ? "visible" : "hidden" }}>
+        <LanguageSwitch />
+      </Box>
       <DataGrid
         {...props}
         columns={columns}
@@ -149,7 +156,6 @@ export const CustomDataGrid = ({
         }}
         pageSizeOptions={[10, 25, 50, 100]}
       />
-
       <Stack direction="row" spacing={2} justifyContent="space-between" mb={2}>
         <Stack direction="row" spacing={2} sx={{ mb: 2 }}>
           {hasCoordinates && (
diff --git a/src/components/LanguageSwitch/index.tsx b/src/components/LanguageSwitch/index.tsx
new file mode 100644
index 0000000..c216097
--- /dev/null
+++ b/src/components/LanguageSwitch/index.tsx
@@ -0,0 +1,70 @@
+import { Box } from "@mui/material";
+import { languageStore } from "../../store/LanguageStore";
+import { observer } from "mobx-react-lite";
+
+export const LanguageSwitch = observer(({ action }: any) => {
+  const { language, setLanguageAction } = languageStore;
+
+  const handleLanguageChange = (lang: string) => {
+    if (action) {
+      action();
+    }
+    setLanguageAction(lang);
+  };
+
+  return (
+    <Box
+      sx={{
+        flex: 1,
+        display: "flex",
+        gap: 2,
+      }}
+    >
+      <Box
+        sx={{
+          cursor: "pointer",
+          flex: 1,
+          display: "flex",
+          justifyContent: "center",
+          bgcolor: language === "ru" ? "primary.main" : "transparent",
+          color: language === "ru" ? "white" : "inherit",
+          borderRadius: 1,
+          p: 1,
+        }}
+        onClick={() => handleLanguageChange("ru")}
+      >
+        RU
+      </Box>
+      <Box
+        sx={{
+          cursor: "pointer",
+          flex: 1,
+          display: "flex",
+          justifyContent: "center",
+          bgcolor: language === "en" ? "primary.main" : "transparent",
+          color: language === "en" ? "white" : "inherit",
+          borderRadius: 1,
+          p: 1,
+        }}
+        onClick={() => handleLanguageChange("en")}
+      >
+        EN
+      </Box>
+      <Box
+        sx={{
+          cursor: "pointer",
+          flex: 1,
+          display: "flex",
+          justifyContent: "center",
+          bgcolor: language === "zh" ? "primary.main" : "transparent",
+          color: language === "zh" ? "white" : "inherit",
+          borderRadius: 1,
+          p: 1,
+        }}
+        onClick={() => handleLanguageChange("zh")}
+      >
+        ZH
+      </Box>
+    </Box>
+  );
+});
diff --git a/src/components/LinkedItems.tsx b/src/components/LinkedItems.tsx
index 614eb3f..bf25d84 100644
--- a/src/components/LinkedItems.tsx
+++ b/src/components/LinkedItems.tsx
@@ -1,4 +1,5 @@
 import { useState, useEffect } from "react";
+import { Close } from "@mui/icons-material";
 import {
   Stack,
   Typography,
@@ -20,14 +21,19 @@ import {
   Paper,
   TableBody,
   IconButton,
+  Collapse,
+  Modal,
 } from "@mui/material";
 import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
 import DragIndicatorIcon from "@mui/icons-material/DragIndicator";
 import { axiosInstance } from "../providers/data";
 
 import { DragDropContext, Droppable, Draggable } from "@hello-pangea/dnd";
-import axios from "axios";
 
+import { articleStore } from "../store/ArticleStore";
+import { ArticleEditModal } from "./modals/ArticleEditModal";
+import { StationEditModal } from "./modals/StationEditModal";
+import { stationStore } from "../store/StationStore";
 function insertAtPosition<T>(arr: T[], pos: number, value: T): T[] {
   const index = pos - 1;
   if (index >= arr.length) {
@@ -82,41 +88,8 @@ export const LinkedItems = <T extends { id: number; [key: string]: any }>({
   type,
   onSave,
 }: LinkedItemsProps<T>) => {
-  const [articleLanguages, setArticleLanguages] = useState<
-    Record<number, string>
-  >({});
-
-  const handleArticleLanguageChange = (
-    articleId: number,
-    languageCode: string
-  ) => {
-    setArticleLanguages((prev) => ({ ...prev, [articleId]: languageCode }));
-    console.log(articleId, languageCode);
-    // Отправка запроса на сервер для сохранения языка
-    axios
-      .get(
-        `${import.meta.env.VITE_KRBL_API}/article/${articleId}/`, // Пример эндпоинта
-        {
-          headers: {
-            Authorization: `Bearer ${localStorage.getItem("refine-auth")}`,
-            "X-language": languageCode.toLowerCase(),
-          },
-        }
-      )
-      .then((response) => {
-        setLinkedItems(
-          linkedItems.map((item) => {
-            if (item.id == articleId) {
-              console.log(response.data);
-              return { ...response.data, language: languageCode };
-            } else {
-              return item;
-            }
-          })
-        );
-      });
-  };
-
+  const { setArticleModalOpenAction, setArticleIdAction } = articleStore;
+  const { setStationModalOpenAction, setStationIdAction } = stationStore;
   const [position, setPosition] = useState<number>(1);
   const [items, setItems] = useState<T[]>([]);
   const [linkedItems, setLinkedItems] = useState<T[]>([]);
@@ -143,22 +116,6 @@ export const LinkedItems = <T extends { id: number; [key: string]: any }>({
     }
   }, [linkedItems, setItemsParent]);
 
-  useEffect(() => {
-    // При загрузке linkedItems можно запросить текущие языки для статей
-    if (childResource === "article" && linkedItems.length > 0) {
-      const initialLanguages: Record<number, string> = {};
-      linkedItems.forEach((article) => {
-        // Предполагается, что у объекта article есть свойство language
-        if (article.language) {
-          initialLanguages[article.id] = article.language;
-        } else {
-          initialLanguages[article.id] = "RU"; // Или другой язык по умолчанию
-        }
-      });
-      setArticleLanguages(initialLanguages);
-    }
-  }, [linkedItems, childResource]);
-
   const onDragEnd = (result: any) => {
     if (!result.destination) return;
 
@@ -294,223 +251,247 @@ export const LinkedItems = <T extends { id: number; [key: string]: any }>({
   };
 
   return (
-    <Accordion>
-      <AccordionSummary
-        expandIcon={<ExpandMoreIcon />}
-        sx={{
-          background: theme.palette.background.paper,
-          borderBottom: `1px solid ${theme.palette.divider}`,
-        }}
-      >
-        <Typography variant="subtitle1" fontWeight="bold">
-          Привязанные {title}
-        </Typography>
-      </AccordionSummary>
+    <>
+      <Accordion>
+        <AccordionSummary
+          expandIcon={<ExpandMoreIcon />}
+          sx={{
+            background: theme.palette.background.paper,
+            borderBottom: `1px solid ${theme.palette.divider}`,
+          }}
+        >
+          <Typography variant="subtitle1" fontWeight="bold">
+            Привязанные {title}
+          </Typography>
+        </AccordionSummary>
 
-      <AccordionDetails sx={{ background: theme.palette.background.paper }}>
-        <Stack gap={2}>
-          <DragDropContext onDragEnd={onDragEnd}>
-            <TableContainer component={Paper}>
-              <Table>
-                <TableHead>
-                  <TableRow>
-                    {type === "edit" && dragAllowed && (
-                      <TableCell width="40px"></TableCell>
-                    )}
-                    <TableCell key="id">№</TableCell>
-                    {fields.map((field) => (
-                      <TableCell key={String(field.data)}>
-                        {field.label}
-                      </TableCell>
-                    ))}
-
-                    {type === "edit" && (
-                      <TableCell width="120px">Действие</TableCell>
-                    )}
-                  </TableRow>
-                </TableHead>
-
-                <Droppable
-                  droppableId="droppable"
-                  isDropDisabled={type !== "edit" || !dragAllowed}
-                >
-                  {(provided) => (
-                    <TableBody
-                      ref={provided.innerRef}
-                      {...provided.droppableProps}
-                    >
-                      {linkedItems.map((item, index) => (
-                        <Draggable
-                          key={item.id}
-                          draggableId={"q" + String(item.id)}
-                          index={index}
-                          isDragDisabled={type !== "edit" || !dragAllowed}
-                        >
-                          {(provided) => (
-                            <TableRow
-                              ref={provided.innerRef}
-                              {...provided.draggableProps}
-                              {...provided.dragHandleProps}
-                              hover
-                            >
-                              {type === "edit" && dragAllowed && (
-                                <TableCell {...provided.dragHandleProps}>
-                                  <IconButton size="small">
-                                    <DragIndicatorIcon />
-                                  </IconButton>
-                                </TableCell>
-                              )}
-                              <TableCell key={String(item.id)}>
-                                {index + 1}
-                              </TableCell>
-                              {fields.map((field, index) => (
-                                <TableCell
-                                  key={String(field.data) + String(index)}
-                                >
-                                  {field.render
-                                    ? field.render(item[field.data])
-                                    : item[field.data]}
-                                </TableCell>
-                              ))}
-
-                              {type === "edit" && (
-                                <TableCell>
-                                  <Button
-                                    variant="outlined"
-                                    color="error"
-                                    size="small"
-                                    onClick={() => deleteItem(item.id)}
-                                  >
-                                    Отвязать
-                                  </Button>
-                                </TableCell>
-                              )}
-                            </TableRow>
-                          )}
-                        </Draggable>
+        <AccordionDetails sx={{ background: theme.palette.background.paper }}>
+          <Stack gap={2}>
+            <DragDropContext onDragEnd={onDragEnd}>
+              <TableContainer component={Paper}>
+                <Table>
+                  <TableHead>
+                    <TableRow>
+                      {type === "edit" && dragAllowed && (
+                        <TableCell width="40px"></TableCell>
+                      )}
+                      <TableCell key="id">№</TableCell>
+                      {fields.map((field) => (
+                        <TableCell key={String(field.data)}>
+                          {field.label}
+                        </TableCell>
                       ))}
-                      {provided.placeholder}
-                    </TableBody>
+
+                      {type === "edit" && (
+                        <TableCell width="120px">Действие</TableCell>
+                      )}
+                    </TableRow>
+                  </TableHead>
+
+                  <Droppable
+                    droppableId="droppable"
+                    isDropDisabled={type !== "edit" || !dragAllowed}
+                  >
+                    {(provided) => (
+                      <TableBody
+                        ref={provided.innerRef}
+                        {...provided.droppableProps}
+                      >
+                        {linkedItems.map((item, index) => (
+                          <Draggable
+                            key={item.id}
+                            draggableId={"q" + String(item.id)}
+                            index={index}
+                            isDragDisabled={type !== "edit" || !dragAllowed}
+                          >
+                            {(provided) => (
+                              <>
+                                <TableRow
+                                  sx={{
+                                    cursor:
+                                      childResource === "article"
+                                        ? "pointer"
+                                        : "default",
+                                  }}
+                                  onClick={() => {
+                                    if (childResource === "article") {
+                                      setArticleModalOpenAction(true);
+                                      setArticleIdAction(item.id);
+                                    }
+                                    if (childResource === "station") {
+                                      setStationModalOpenAction(true);
+                                      setStationIdAction(item.id);
+                                    }
+                                  }}
+                                  ref={provided.innerRef}
+                                  {...provided.draggableProps}
+                                  {...provided.dragHandleProps}
+                                  hover
+                                >
+                                  {type === "edit" && dragAllowed && (
+                                    <TableCell {...provided.dragHandleProps}>
+                                      <IconButton size="small">
+                                        <DragIndicatorIcon />
+                                      </IconButton>
+                                    </TableCell>
+                                  )}
+                                  <TableCell key={String(item.id)}>
+                                    {index + 1}
+                                  </TableCell>
+                                  {fields.map((field, index) => (
+                                    <TableCell
+                                      key={String(field.data) + String(index)}
+                                    >
+                                      {field.render
+                                        ? field.render(item[field.data])
+                                        : item[field.data]}
+                                    </TableCell>
+                                  ))}
+
+                                  {type === "edit" && (
+                                    <TableCell>
+                                      <Button
+                                        variant="outlined"
+                                        color="error"
+                                        size="small"
+                                        onClick={() => deleteItem(item.id)}
+                                      >
+                                        Отвязать
+                                      </Button>
+                                    </TableCell>
+                                  )}
+                                </TableRow>
+                              </>
+                            )}
+                          </Draggable>
+                        ))}
+
+                        {provided.placeholder}
+                      </TableBody>
+                    )}
+                  </Droppable>
+                </Table>
+              </TableContainer>
+            </DragDropContext>
+
+            {linkedItems.length === 0 && !isLoading && (
+              <Typography color="textSecondary" textAlign="center" py={2}>
+                {title} не найдены
+              </Typography>
+            )}
+
+            {type === "edit" && (
+              <Stack gap={2} mt={2}>
+                <Typography variant="subtitle1">Добавить {title}</Typography>
+                <Autocomplete
+                  fullWidth
+                  value={
+                    availableItems?.find(
+                      (item) => item.id === selectedItemId
+                    ) || null
+                  }
+                  onChange={(_, newValue) =>
+                    setSelectedItemId(newValue?.id || null)
+                  }
+                  options={availableItems}
+                  getOptionLabel={(item) => String(item[fields[0].data])}
+                  renderInput={(params) => (
+                    <TextField
+                      {...params}
+                      label={`Выберите ${title}`}
+                      fullWidth
+                    />
                   )}
-                </Droppable>
-              </Table>
-            </TableContainer>
-          </DragDropContext>
-
-          {linkedItems.length === 0 && !isLoading && (
-            <Typography color="textSecondary" textAlign="center" py={2}>
-              {title} не найдены
-            </Typography>
-          )}
-
-          {type === "edit" && (
-            <Stack gap={2} mt={2}>
-              <Typography variant="subtitle1">Добавить {title}</Typography>
-              <Autocomplete
-                fullWidth
-                value={
-                  availableItems?.find((item) => item.id === selectedItemId) ||
-                  null
-                }
-                onChange={(_, newValue) =>
-                  setSelectedItemId(newValue?.id || null)
-                }
-                options={availableItems}
-                getOptionLabel={(item) => String(item[fields[0].data])}
-                renderInput={(params) => (
-                  <TextField
-                    {...params}
-                    label={`Выберите ${title}`}
-                    fullWidth
-                  />
-                )}
-                isOptionEqualToValue={(option, value) =>
-                  option.id === value?.id
-                }
-                filterOptions={(options, { inputValue }) => {
-                  const searchWords = inputValue
-                    .toLowerCase()
-                    .split(" ")
-                    .filter((word) => word.length > 0);
-                  return options.filter((option) => {
-                    const optionWords = String(option[fields[0].data])
+                  isOptionEqualToValue={(option, value) =>
+                    option.id === value?.id
+                  }
+                  filterOptions={(options, { inputValue }) => {
+                    const searchWords = inputValue
                       .toLowerCase()
-                      .split(" ");
-                    return searchWords.every((searchWord) =>
-                      optionWords.some((word) => word.startsWith(searchWord))
-                    );
-                  });
-                }}
-                renderOption={(props, option) => (
-                  <li {...props} key={option.id}>
-                    {String(option[fields[0].data])}
-                  </li>
-                )}
-              />
-
-              {childResource === "article" && (
-                <FormControl fullWidth>
-                  <TextField
-                    type="number"
-                    label="Номер страницы"
-                    name="page_num"
-                    value={pageNum}
-                    onChange={(e) => {
-                      const newValue = Number(e.target.value);
-                      const minValue = linkedItems.length + 1;
-                      setPageNum(newValue < minValue ? minValue : newValue);
-                    }}
-                    fullWidth
-                    InputLabelProps={{ shrink: true }}
-                  />
-                </FormControl>
-              )}
-
-              {childResource === "media" && (
-                <FormControl fullWidth>
-                  <TextField
-                    type="number"
-                    label="Порядок отображения медиа"
-                    value={mediaOrder}
-                    onChange={(e) => {
-                      const newValue = Number(e.target.value);
-                      const maxValue = linkedItems.length + 1;
-                      const value = Math.max(1, Math.min(newValue, maxValue));
-                      setMediaOrder(value);
-                    }}
-                    fullWidth
-                    InputLabelProps={{ shrink: true }}
-                  />
-                </FormControl>
-              )}
-
-              <Button
-                variant="contained"
-                onClick={linkItem}
-                disabled={!selectedItemId}
-                sx={{ alignSelf: "flex-start" }}
-              >
-                Добавить
-              </Button>
-              {childResource == "station" && (
-                <TextField
-                  type="text"
-                  label="Позиция добавляемой остановки к маршруту"
-                  value={position}
-                  onChange={(e) => {
-                    const newValue = Number(e.target.value);
-                    setPosition(
-                      newValue > linkedItems.length + 1
-                        ? linkedItems.length + 1
-                        : newValue
-                    );
+                      .split(" ")
+                      .filter((word) => word.length > 0);
+                    return options.filter((option) => {
+                      const optionWords = String(option[fields[0].data])
+                        .toLowerCase()
+                        .split(" ");
+                      return searchWords.every((searchWord) =>
+                        optionWords.some((word) => word.startsWith(searchWord))
+                      );
+                    });
                   }}
-                ></TextField>
-              )}
-            </Stack>
-          )}
-        </Stack>
-      </AccordionDetails>
-    </Accordion>
+                  renderOption={(props, option) => (
+                    <li {...props} key={option.id}>
+                      {String(option[fields[0].data])}
+                    </li>
+                  )}
+                />
+
+                {childResource === "article" && (
+                  <FormControl fullWidth>
+                    <TextField
+                      type="number"
+                      label="Номер страницы"
+                      name="page_num"
+                      value={pageNum}
+                      onChange={(e) => {
+                        const newValue = Number(e.target.value);
+                        const minValue = linkedItems.length + 1;
+                        setPageNum(newValue < minValue ? minValue : newValue);
+                      }}
+                      fullWidth
+                      InputLabelProps={{ shrink: true }}
+                    />
+                  </FormControl>
+                )}
+
+                {childResource === "media" && (
+                  <FormControl fullWidth>
+                    <TextField
+                      type="number"
+                      label="Порядок отображения медиа"
+                      value={mediaOrder}
+                      onChange={(e) => {
+                        const newValue = Number(e.target.value);
+                        const maxValue = linkedItems.length + 1;
+                        const value = Math.max(1, Math.min(newValue, maxValue));
+                        setMediaOrder(value);
+                      }}
+                      fullWidth
+                      InputLabelProps={{ shrink: true }}
+                    />
+                  </FormControl>
+                )}
+
+                <Button
+                  variant="contained"
+                  onClick={linkItem}
+                  disabled={!selectedItemId}
+                  sx={{ alignSelf: "flex-start" }}
+                >
+                  Добавить
+                </Button>
+                {childResource == "station" && (
+                  <TextField
+                    type="text"
+                    label="Позиция добавляемой остановки к маршруту"
+                    value={position}
+                    onChange={(e) => {
+                      const newValue = Number(e.target.value);
+                      setPosition(
+                        newValue > linkedItems.length + 1
+                          ? linkedItems.length + 1
+                          : newValue
+                      );
+                    }}
+                  ></TextField>
+                )}
+              </Stack>
+            )}
+          </Stack>
+        </AccordionDetails>
+      </Accordion>
+      <ArticleEditModal />
+      <StationEditModal />
+    </>
   );
 };
diff --git a/src/components/index.ts b/src/components/index.ts
deleted file mode 100644
index 7c8ead2..0000000
--- a/src/components/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export {Header} from './header'
diff --git a/src/components/modals/ArticleEditModal/index.tsx b/src/components/modals/ArticleEditModal/index.tsx
new file mode 100644
index 0000000..a843dc7
--- /dev/null
+++ b/src/components/modals/ArticleEditModal/index.tsx
@@ -0,0 +1,171 @@
+import { Modal, Box, Button, TextField, Typography } from "@mui/material";
+import { articleStore } from "../../../store/ArticleStore";
+import { observer } from "mobx-react-lite";
+import { useForm } from "@refinedev/react-hook-form";
+import { Controller } from "react-hook-form";
+import "easymde/dist/easymde.min.css";
+import { memo, useMemo, useEffect } from "react";
+import { MarkdownEditor } from "../../MarkdownEditor";
+import { Edit } from "@refinedev/mui";
+import { languageStore } from "../../../store/LanguageStore";
+import { LanguageSwitch } from "../../LanguageSwitch/index";
+import { useNavigate } from "react-router";
+import { useState } from "react";
+
+const MemoizedSimpleMDE = memo(MarkdownEditor);
+
+const style = {
+  position: "absolute",
+  top: "50%",
+  left: "50%",
+  transform: "translate(-50%, -50%)",
+  width: "60%",
+  bgcolor: "background.paper",
+  border: "2px solid #000",
+  boxShadow: 24,
+  p: 4,
+};
+
+export const ArticleEditModal = observer(() => {
+  const [articleData, setArticleData] = useState({
+    ru: {
+      heading: "",
+      body: "",
+    },
+    en: {
+      heading: "",
+      body: "",
+    },
+    zh: {
+      heading: "",
+      body: "",
+    },
+  });
+  const { articleModalOpen, setArticleModalOpenAction, selectedArticleId } =
+    articleStore;
+  const { language } = languageStore;
+
+  useEffect(() => {
+    return () => {
+      setArticleModalOpenAction(false);
+    };
+  }, []);
+
+  const {
+    register,
+    control,
+    formState: { errors },
+    saveButtonProps,
+    reset,
+    setValue,
+    watch,
+  } = useForm({
+    refineCoreProps: {
+      resource: "article",
+      id: selectedArticleId ?? undefined,
+      action: "edit",
+      redirect: false,
+
+      onMutationSuccess: () => {
+        setArticleModalOpenAction(false);
+        reset();
+        window.location.reload();
+      },
+      meta: {
+        headers: {
+          "Accept-Language": language,
+        },
+      },
+    },
+  });
+
+  useEffect(() => {
+    if (articleData[language as keyof typeof articleData]?.heading) {
+      setValue(
+        "heading",
+        articleData[language as keyof typeof articleData]?.heading || ""
+      );
+    }
+    if (articleData[language as keyof typeof articleData]?.body) {
+      setValue(
+        "body",
+        articleData[language as keyof typeof articleData]?.body || ""
+      );
+    }
+  }, [language, articleData, setValue]);
+
+  const handleLanguageChange = () => {
+    setArticleData((prevData) => ({
+      ...prevData,
+      [language]: {
+        heading: watch("heading") || "",
+        body: watch("body") || "",
+      },
+    }));
+  };
+
+  const simpleMDEOptions = useMemo(
+    () => ({
+      placeholder: "Введите контент в формате Markdown...",
+      spellChecker: false,
+    }),
+    []
+  );
+
+  return (
+    <Modal
+      open={articleModalOpen}
+      onClose={() => setArticleModalOpenAction(false)}
+      aria-labelledby="modal-modal-title"
+      aria-describedby="modal-modal-description"
+    >
+      <Box sx={style}>
+        <Edit
+          title={<Typography variant="h5">Редактирование статьи</Typography>}
+          headerProps={{
+            sx: {
+              fontSize: "50px",
+            },
+          }}
+          saveButtonProps={saveButtonProps}
+        >
+          <LanguageSwitch action={handleLanguageChange} />
+          <Box
+            component="form"
+            sx={{ display: "flex", flexDirection: "column" }}
+            autoComplete="off"
+          >
+            <TextField
+              {...register("heading", {
+                required: "Это поле является обязательным",
+              })}
+              error={!!errors.heading}
+              helperText={errors.heading?.message as string}
+              margin="normal"
+              fullWidth
+              InputLabelProps={{ shrink: true }}
+              type="text"
+              name="heading"
+              label="Заголовок *"
+            />
+
+            <Controller
+              control={control}
+              name="body"
+              rules={{ required: "Это поле является обязательным" }}
+              defaultValue=""
+              render={({ field: { onChange, value } }) => (
+                <MemoizedSimpleMDE
+                  value={value}
+                  onChange={onChange}
+                  options={simpleMDEOptions}
+                  className="my-markdown-editor"
+                />
+              )}
+            />
+          </Box>
+        </Edit>
+      </Box>
+    </Modal>
+  );
+});
diff --git a/src/components/modals/StationEditModal/index.tsx b/src/components/modals/StationEditModal/index.tsx
new file mode 100644
index 0000000..473a421
--- /dev/null
+++ b/src/components/modals/StationEditModal/index.tsx
@@ -0,0 +1,164 @@
+import {
+  Modal,
+  Box,
+  Button,
+  TextField,
+  Typography,
+  Grid,
+  Paper,
+} from "@mui/material";
+
+import { observer } from "mobx-react-lite";
+import { useForm } from "@refinedev/react-hook-form";
+import { Controller } from "react-hook-form";
+import "easymde/dist/easymde.min.css";
+import { memo, useMemo, useEffect } from "react";
+import { MarkdownEditor } from "../../MarkdownEditor";
+import { Edit } from "@refinedev/mui";
+import { languageStore } from "../../../store/LanguageStore";
+import { LanguageSwitch } from "../../LanguageSwitch/index";
+
+import { useState } from "react";
+import { stationStore } from "../../../store/StationStore";
+const MemoizedSimpleMDE = memo(MarkdownEditor);
+
+const TRANSFER_FIELDS = [
+  { name: "bus", label: "Автобус" },
+  { name: "metro_blue", label: "Метро (синяя)" },
+  { name: "metro_green", label: "Метро (зеленая)" },
+  { name: "metro_orange", label: "Метро (оранжевая)" },
+  { name: "metro_purple", label: "Метро (фиолетовая)" },
+  { name: "metro_red", label: "Метро (красная)" },
+  { name: "train", label: "Электричка" },
+  { name: "tram", label: "Трамвай" },
+  { name: "trolleybus", label: "Троллейбус" },
+];
+
+const style = {
+  position: "absolute",
+  top: "50%",
+  left: "50%",
+  transform: "translate(-50%, -50%)",
+  width: "60%",
+  bgcolor: "background.paper",
+  border: "2px solid #000",
+  boxShadow: 24,
+  p: 4,
+};
+
+export const StationEditModal = observer(() => {
+  const { stationModalOpen, setStationModalOpenAction, selectedStationId } =
+    stationStore;
+  const { language } = languageStore;
+
+  useEffect(() => {
+    return () => {
+      setStationModalOpenAction(false);
+    };
+  }, []);
+
+  const {
+    register,
+    control,
+    formState: { errors },
+    saveButtonProps,
+    reset,
+    setValue,
+    watch,
+  } = useForm({
+    refineCoreProps: {
+      resource: "station",
+      id: selectedStationId ?? undefined,
+      action: "edit",
+      redirect: false,
+
+      onMutationSuccess: () => {
+        setStationModalOpenAction(false);
+        reset();
+        window.location.reload();
+      },
+      meta: {
+        headers: {
+          "Accept-Language": language,
+        },
+      },
+    },
+  });
+
+  return (
+    <Modal
+      open={stationModalOpen}
+      onClose={() => setStationModalOpenAction(false)}
+      aria-labelledby="modal-modal-title"
+      aria-describedby="modal-modal-description"
+    >
+      <Box sx={style}>
+        <Edit
+          title={<Typography variant="h5">Редактирование станции</Typography>}
+          saveButtonProps={saveButtonProps}
+        >
+          <Box
+            component="form"
+            sx={{ display: "flex", flexDirection: "column" }}
+            autoComplete="off"
+          >
+            <TextField
+              {...register("offset_x", {
+                setValueAs: (value) => parseFloat(value),
+              })}
+              error={!!(errors as any)?.offset_x}
+              helperText={(errors as any)?.offset_x?.message}
+              margin="normal"
+              fullWidth
+              InputLabelProps={{ shrink: true }}
+              type="number"
+              label={"Смещение (X)"}
+              name="offset_x"
+            />
+
+            <TextField
+              {...register("offset_y", {
+                required: "Это поле является обязательным",
+                setValueAs: (value) => parseFloat(value),
+              })}
+              error={!!(errors as any)?.offset_y}
+              helperText={(errors as any)?.offset_y?.message}
+              margin="normal"
+              fullWidth
+              InputLabelProps={{ shrink: true }}
+              type="number"
+              label={"Смещение (Y)"}
+              name="offset_y"
+            />
+
+            {/* Группа полей пересадок */}
+            <Paper sx={{ p: 2, mt: 2 }}>
+              <Typography variant="h6" gutterBottom>
+                Пересадки
+              </Typography>
+              <Grid container spacing={2}>
+                {TRANSFER_FIELDS.map((field) => (
+                  <Grid item xs={12} sm={6} md={4} key={field.name}>
+                    <TextField
+                      {...register(`transfers.${field.name}`)}
+                      error={!!(errors as any)?.transfers?.[field.name]}
+                      helperText={
+                        (errors as any)?.transfers?.[field.name]?.message
+                      }
+                      margin="normal"
+                      fullWidth
+                      InputLabelProps={{ shrink: true }}
+                      type="text"
+                      label={field.label}
+                      name={`transfers.${field.name}`}
+                    />
+                  </Grid>
+                ))}
+              </Grid>
+            </Paper>
+          </Box>
+        </Edit>
+      </Box>
+    </Modal>
+  );
+});
diff --git a/src/pages/article/edit.tsx b/src/pages/article/edit.tsx
index 6dde00f..bbf4204 100644
--- a/src/pages/article/edit.tsx
+++ b/src/pages/article/edit.tsx
@@ -58,18 +58,22 @@ export const ArticleEdit = observer(() => {
   });
 
   useEffect(() => {
-    setValue(
-      "heading",
-      articleData[language as keyof typeof articleData]?.heading || ""
-    );
-    setValue(
-      "body",
-      articleData[language as keyof typeof articleData]?.body || ""
-    );
-    setPreview(articleData[language as keyof typeof articleData]?.body || "");
-    setHeadingPreview(
-      articleData[language as keyof typeof articleData]?.heading || ""
-    );
+    if (articleData[language as keyof typeof articleData]?.heading) {
+      setValue(
+        "heading",
+        articleData[language as keyof typeof articleData]?.heading
+      );
+      setHeadingPreview(
+        articleData[language as keyof typeof articleData]?.heading || ""
+      );
+    }
+    if (articleData[language as keyof typeof articleData]?.body) {
+      setValue(
+        "body",
+        articleData[language as keyof typeof articleData]?.body || ""
+      );
+      setPreview(articleData[language as keyof typeof articleData]?.body || "");
+    }
   }, [language, articleData, setValue]);
 
   const handleLanguageChange = (lang: string) => {
diff --git a/src/pages/article/list.tsx b/src/pages/article/list.tsx
index 16b9d2b..168a63f 100644
--- a/src/pages/article/list.tsx
+++ b/src/pages/article/list.tsx
@@ -1,34 +1,49 @@
-import {type GridColDef} from '@mui/x-data-grid'
-import {CustomDataGrid} from '../../components/CustomDataGrid'
-import {DeleteButton, EditButton, List, ShowButton, useDataGrid} from '@refinedev/mui'
-import React from 'react'
+import { type GridColDef } from "@mui/x-data-grid";
+import { CustomDataGrid } from "../../components/CustomDataGrid";
+import {
+  DeleteButton,
+  EditButton,
+  List,
+  ShowButton,
+  useDataGrid,
+} from "@refinedev/mui";
+import React, { useEffect } from "react";
 
-import {localeText} from '../../locales/ru/localeText'
+import { localeText } from "../../locales/ru/localeText";
+import { observer } from "mobx-react-lite";
+import { languageStore } from "../../store/LanguageStore";
 
-export const ArticleList = () => {
-  const {dataGridProps} = useDataGrid({
-    resource: 'article/',
-  })
+export const ArticleList = observer(() => {
+  const { language } = languageStore;
+
+  const { dataGridProps } = useDataGrid({
+    resource: "article/",
+    meta: {
+      headers: {
+        "Accept-Language": language,
+      },
+    },
+  });
 
   const columns = React.useMemo<GridColDef[]>(
     () => [
       {
-        field: 'id',
-        headerName: 'ID',
-        type: 'number',
+        field: "id",
+        headerName: "ID",
+        type: "number",
         minWidth: 70,
-        display: 'flex',
-        align: 'left',
-        headerAlign: 'left',
+        display: "flex",
+        align: "left",
+        headerAlign: "left",
       },
       {
-        field: 'heading',
-        headerName: 'Заголовок',
-        type: 'string',
+        field: "heading",
+        headerName: "Заголовок",
+        type: "string",
         minWidth: 300,
-        display: 'flex',
-        align: 'left',
-        headerAlign: 'left',
+        display: "flex",
+        align: "left",
+        headerAlign: "left",
         flex: 1,
       },
       // {
@@ -41,32 +56,38 @@ export const ArticleList = () => {
       //   flex: 1,
       // },
       {
-        field: 'actions',
-        headerName: 'Действия',
-        align: 'right',
-        headerAlign: 'center',
+        field: "actions",
+        headerName: "Действия",
+        align: "right",
+        headerAlign: "center",
         minWidth: 120,
-        display: 'flex',
+        display: "flex",
         sortable: false,
         filterable: false,
         disableColumnMenu: true,
-        renderCell: function render({row}) {
+        renderCell: function render({ row }) {
           return (
             <>
               <EditButton hideText recordItemId={row.id} />
               <ShowButton hideText recordItemId={row.id} />
               <DeleteButton hideText recordItemId={row.id} />
             </>
-          )
+          );
         },
       },
     ],
-    [],
-  )
+    []
+  );
 
   return (
     <List>
-      <CustomDataGrid {...dataGridProps} columns={columns} localeText={localeText} getRowId={(row: any) => row.id} />
+      <CustomDataGrid
+        {...dataGridProps}
+        languageEnabled
+        columns={columns}
+        localeText={localeText}
+        getRowId={(row: any) => row.id}
+      />
     </List>
-  )
-}
+  );
+});
diff --git a/src/pages/carrier/create.tsx b/src/pages/carrier/create.tsx
index fc692c9..891ea3e 100644
--- a/src/pages/carrier/create.tsx
+++ b/src/pages/carrier/create.tsx
@@ -1,172 +1,202 @@
-import {Autocomplete, Box, TextField} from '@mui/material'
-import {Create, useAutocomplete} from '@refinedev/mui'
-import {useForm} from '@refinedev/react-hook-form'
-import {Controller} from 'react-hook-form'
-
-export const CarrierCreate = () => {
+import { Autocomplete, Box, TextField } from "@mui/material";
+import { Create, useAutocomplete } from "@refinedev/mui";
+import { useForm } from "@refinedev/react-hook-form";
+import { Controller } from "react-hook-form";
+import { observer } from "mobx-react-lite";
+import { languageStore } from "../../store/LanguageStore";
+export const CarrierCreate = observer(() => {
+  const { language } = languageStore;
   const {
     saveButtonProps,
-    refineCore: {formLoading},
+    refineCore: { formLoading },
     register,
     control,
-    formState: {errors},
-  } = useForm({})
+    formState: { errors },
+  } = useForm({
+    refineCoreProps: {
+      meta: {
+        headers: {
+          "Accept-Language": language,
+        },
+      },
+    },
+  });
 
-  const {autocompleteProps: cityAutocompleteProps} = useAutocomplete({
-    resource: 'city',
+  const { autocompleteProps: cityAutocompleteProps } = useAutocomplete({
+    resource: "city",
     onSearch: (value) => [
       {
-        field: 'name',
-        operator: 'contains',
+        field: "name",
+        operator: "contains",
         value,
       },
     ],
-  })
+  });
 
-  const {autocompleteProps: mediaAutocompleteProps} = useAutocomplete({
-    resource: 'media',
+  const { autocompleteProps: mediaAutocompleteProps } = useAutocomplete({
+    resource: "media",
     onSearch: (value) => [
       {
-        field: 'media_name',
-        operator: 'contains',
+        field: "media_name",
+        operator: "contains",
         value,
       },
     ],
-  })
+  });
 
   return (
     <Create isLoading={formLoading} saveButtonProps={saveButtonProps}>
-      <Box component="form" sx={{display: 'flex', flexDirection: 'column'}} autoComplete="off">
+      <Box
+        component="form"
+        sx={{ display: "flex", flexDirection: "column" }}
+        autoComplete="off"
+      >
         <Controller
           control={control}
           name="city_id"
-          rules={{required: 'Это поле является обязательным'}}
+          rules={{ required: "Это поле является обязательным" }}
           defaultValue={null}
-          render={({field}) => (
+          render={({ field }) => (
             <Autocomplete
               {...cityAutocompleteProps}
-              value={cityAutocompleteProps.options.find((option) => option.id === field.value) || null}
+              value={
+                cityAutocompleteProps.options.find(
+                  (option) => option.id === field.value
+                ) || null
+              }
               onChange={(_, value) => {
-                field.onChange(value?.id || '')
+                field.onChange(value?.id || "");
               }}
               getOptionLabel={(item) => {
-                return item ? item.name : ''
+                return item ? item.name : "";
               }}
               isOptionEqualToValue={(option, value) => {
-                return option.id === value?.id
+                return option.id === value?.id;
               }}
-              filterOptions={(options, {inputValue}) => {
-                return options.filter((option) => option.name.toLowerCase().includes(inputValue.toLowerCase()))
+              filterOptions={(options, { inputValue }) => {
+                return options.filter((option) =>
+                  option.name.toLowerCase().includes(inputValue.toLowerCase())
+                );
               }}
-              renderInput={(params) => <TextField {...params} label="Выберите город" margin="normal" variant="outlined" error={!!errors.city_id} helperText={(errors as any)?.city_id?.message} required />}
+              renderInput={(params) => (
+                <TextField
+                  {...params}
+                  label="Выберите город"
+                  margin="normal"
+                  variant="outlined"
+                  error={!!errors.city_id}
+                  helperText={(errors as any)?.city_id?.message}
+                  required
+                />
+              )}
             />
           )}
         />
 
         <TextField
-          {...register('full_name', {
-            required: 'Это поле является обязательным',
+          {...register("full_name", {
+            required: "Это поле является обязательным",
           })}
           error={!!(errors as any)?.full_name}
           helperText={(errors as any)?.full_name?.message}
           margin="normal"
           fullWidth
-          InputLabelProps={{shrink: true}}
+          InputLabelProps={{ shrink: true }}
           type="text"
-          label={'Полное имя *'}
+          label={"Полное имя *"}
           name="full_name"
         />
 
         <TextField
-          {...register('short_name', {
-            required: 'Это поле является обязательным',
+          {...register("short_name", {
+            required: "Это поле является обязательным",
           })}
           error={!!(errors as any)?.short_name}
           helperText={(errors as any)?.short_name?.message}
           margin="normal"
           fullWidth
-          InputLabelProps={{shrink: true}}
+          InputLabelProps={{ shrink: true }}
           type="text"
-          label={'Короткое имя *'}
+          label={"Короткое имя *"}
           name="short_name"
         />
 
         <TextField
-          {...register('main_color', {
+          {...register("main_color", {
             // required: 'Это поле является обязательным',
           })}
           error={!!(errors as any)?.main_color}
           helperText={(errors as any)?.main_color?.message}
           margin="normal"
           fullWidth
-          InputLabelProps={{shrink: true}}
+          InputLabelProps={{ shrink: true }}
           type="color"
-          label={'Основной цвет'}
+          label={"Основной цвет"}
           name="main_color"
           sx={{
-            '& input': {
-              height: '50px',
-              paddingBlock: '14px',
-              paddingInline: '14px',
-              cursor: 'pointer',
+            "& input": {
+              height: "50px",
+              paddingBlock: "14px",
+              paddingInline: "14px",
+              cursor: "pointer",
             },
           }}
         />
 
         <TextField
-          {...register('left_color', {
+          {...register("left_color", {
             // required: 'Это поле является обязательным',
           })}
           error={!!(errors as any)?.left_color}
           helperText={(errors as any)?.left_color?.message}
           margin="normal"
           fullWidth
-          InputLabelProps={{shrink: true}}
+          InputLabelProps={{ shrink: true }}
           type="color"
-          label={'Цвет левого виджета'}
+          label={"Цвет левого виджета"}
           name="left_color"
           sx={{
-            '& input': {
-              height: '50px',
-              paddingBlock: '14px',
-              paddingInline: '14px',
-              cursor: 'pointer',
+            "& input": {
+              height: "50px",
+              paddingBlock: "14px",
+              paddingInline: "14px",
+              cursor: "pointer",
             },
           }}
         />
         <TextField
-          {...register('right_color', {
+          {...register("right_color", {
             // required: 'Это поле является обязательным',
           })}
           error={!!(errors as any)?.right_color}
           helperText={(errors as any)?.right_color?.message}
           margin="normal"
           fullWidth
-          InputLabelProps={{shrink: true}}
+          InputLabelProps={{ shrink: true }}
           type="color"
-          label={'Цвет правого виджета'}
+          label={"Цвет правого виджета"}
           name="right_color"
           sx={{
-            '& input': {
-              height: '50px',
-              paddingBlock: '14px',
-              paddingInline: '14px',
-              cursor: 'pointer',
+            "& input": {
+              height: "50px",
+              paddingBlock: "14px",
+              paddingInline: "14px",
+              cursor: "pointer",
             },
           }}
         />
 
         <TextField
-          {...register('slogan', {
+          {...register("slogan", {
             // required: 'Это поле является обязательным',
           })}
           error={!!(errors as any)?.slogan}
           helperText={(errors as any)?.slogan?.message}
           margin="normal"
           fullWidth
-          InputLabelProps={{shrink: true}}
+          InputLabelProps={{ shrink: true }}
           type="text"
-          label={'Слоган'}
+          label={"Слоган"}
           name="slogan"
         />
 
@@ -175,27 +205,44 @@ export const CarrierCreate = () => {
           name="logo"
           // rules={{required: 'Это поле является обязательным'}}
           defaultValue={null}
-          render={({field}) => (
+          render={({ field }) => (
             <Autocomplete
               {...mediaAutocompleteProps}
-              value={mediaAutocompleteProps.options.find((option) => option.id === field.value) || null}
+              value={
+                mediaAutocompleteProps.options.find(
+                  (option) => option.id === field.value
+                ) || null
+              }
               onChange={(_, value) => {
-                field.onChange(value?.id || '')
+                field.onChange(value?.id || "");
               }}
               getOptionLabel={(item) => {
-                return item ? item.media_name : ''
+                return item ? item.media_name : "";
               }}
               isOptionEqualToValue={(option, value) => {
-                return option.id === value?.id
+                return option.id === value?.id;
               }}
-              filterOptions={(options, {inputValue}) => {
-                return options.filter((option) => option.media_name.toLowerCase().includes(inputValue.toLowerCase()))
+              filterOptions={(options, { inputValue }) => {
+                return options.filter((option) =>
+                  option.media_name
+                    .toLowerCase()
+                    .includes(inputValue.toLowerCase())
+                );
               }}
-              renderInput={(params) => <TextField {...params} label="Выберите логотип" margin="normal" variant="outlined" error={!!errors.logo} helperText={(errors as any)?.logo?.message} />}
+              renderInput={(params) => (
+                <TextField
+                  {...params}
+                  label="Выберите логотип"
+                  margin="normal"
+                  variant="outlined"
+                  error={!!errors.logo}
+                  helperText={(errors as any)?.logo?.message}
+                />
+              )}
             />
           )}
         />
       </Box>
     </Create>
-  )
-}
+  );
+});
diff --git a/src/pages/carrier/list.tsx b/src/pages/carrier/list.tsx
index 2eddc30..bc9b0eb 100644
--- a/src/pages/carrier/list.tsx
+++ b/src/pages/carrier/list.tsx
@@ -10,11 +10,19 @@ import {
 import React from "react";
 import { observer } from "mobx-react-lite";
 import { cityStore } from "../../store/CityStore";
+import { languageStore } from "../../store/LanguageStore";
 
 export const CarrierList = observer(() => {
   const { city_id } = cityStore;
+  const { language } = languageStore;
+
   const { dataGridProps } = useDataGrid({
     resource: "carrier",
+    meta: {
+      headers: {
+        "Accept-Language": language,
+      },
+    },
     filters: {
       permanent: [
         {
@@ -167,7 +175,7 @@ export const CarrierList = observer(() => {
 
   return (
     <List>
-      <CustomDataGrid {...dataGridProps} columns={columns} />
+      <CustomDataGrid {...dataGridProps} languageEnabled columns={columns} />
     </List>
   );
 });
diff --git a/src/pages/city/list.tsx b/src/pages/city/list.tsx
index d477288..32682a7 100644
--- a/src/pages/city/list.tsx
+++ b/src/pages/city/list.tsx
@@ -1,78 +1,100 @@
-import {type GridColDef} from '@mui/x-data-grid'
-import {CustomDataGrid} from '../../components/CustomDataGrid'
-import {DeleteButton, EditButton, List, ShowButton, useDataGrid} from '@refinedev/mui'
-import React from 'react'
+import { type GridColDef } from "@mui/x-data-grid";
+import { CustomDataGrid } from "../../components/CustomDataGrid";
+import {
+  DeleteButton,
+  EditButton,
+  List,
+  ShowButton,
+  useDataGrid,
+} from "@refinedev/mui";
+import React, { useEffect } from "react";
 
-export const CityList = () => {
-  const {dataGridProps} = useDataGrid({})
+import { observer } from "mobx-react-lite";
+import { languageStore } from "../../store/LanguageStore";
+
+export const CityList = observer(() => {
+  const { language } = languageStore;
+
+  const { dataGridProps } = useDataGrid({
+    resource: "city",
+    meta: {
+      headers: {
+        "Accept-Language": language,
+      },
+    },
+  });
 
   const columns = React.useMemo<GridColDef[]>(
     () => [
       {
-        field: 'id',
-        headerName: 'ID',
-        type: 'number',
+        field: "id",
+        headerName: "ID",
+        type: "number",
         minWidth: 50,
-        align: 'left',
-        headerAlign: 'left',
+        align: "left",
+        headerAlign: "left",
       },
       {
-        field: 'country_code',
-        headerName: 'Код страны',
-        type: 'string',
+        field: "country_code",
+        headerName: "Код страны",
+        type: "string",
         minWidth: 150,
-        align: 'left',
-        headerAlign: 'left',
+        align: "left",
+        headerAlign: "left",
       },
       {
-        field: 'country',
-        headerName: 'Cтрана',
-        type: 'string',
+        field: "country",
+        headerName: "Cтрана",
+        type: "string",
         minWidth: 150,
-        align: 'left',
-        headerAlign: 'left',
+        align: "left",
+        headerAlign: "left",
       },
       {
-        field: 'name',
-        headerName: 'Название',
-        type: 'string',
+        field: "name",
+        headerName: "Название",
+        type: "string",
         minWidth: 150,
         flex: 1,
       },
       {
-        field: 'arms',
-        headerName: 'Герб',
-        type: 'string',
+        field: "arms",
+        headerName: "Герб",
+        type: "string",
         flex: 1,
       },
       {
-        field: 'actions',
-        headerName: 'Действия',
-        cellClassName: 'city-actions',
+        field: "actions",
+        headerName: "Действия",
+        cellClassName: "city-actions",
         minWidth: 120,
-        display: 'flex',
-        align: 'right',
-        headerAlign: 'center',
+        display: "flex",
+        align: "right",
+        headerAlign: "center",
         sortable: false,
         filterable: false,
         disableColumnMenu: true,
-        renderCell: function render({row}) {
+        renderCell: function render({ row }) {
           return (
             <>
               <EditButton hideText recordItemId={row.id} />
               <ShowButton hideText recordItemId={row.id} />
-              <DeleteButton hideText confirmTitle="Вы уверены?" recordItemId={row.id} />
+              <DeleteButton
+                hideText
+                confirmTitle="Вы уверены?"
+                recordItemId={row.id}
+              />
             </>
-          )
+          );
         },
       },
     ],
-    [],
-  )
+    []
+  );
 
   return (
     <List>
-      <CustomDataGrid {...dataGridProps} columns={columns} />
+      <CustomDataGrid {...dataGridProps} columns={columns} languageEnabled />
     </List>
-  )
-}
+  );
+});
diff --git a/src/pages/country/list.tsx b/src/pages/country/list.tsx
index 7bfe487..a592e95 100644
--- a/src/pages/country/list.tsx
+++ b/src/pages/country/list.tsx
@@ -1,56 +1,82 @@
-import {type GridColDef} from '@mui/x-data-grid'
-import {CustomDataGrid} from '../../components/CustomDataGrid'
-import {DeleteButton, EditButton, List, ShowButton, useDataGrid} from '@refinedev/mui'
-import React from 'react'
+import { type GridColDef } from "@mui/x-data-grid";
+import { CustomDataGrid } from "../../components/CustomDataGrid";
+import {
+  DeleteButton,
+  EditButton,
+  List,
+  ShowButton,
+  useDataGrid,
+} from "@refinedev/mui";
+import React from "react";
+import { languageStore } from "../../store/LanguageStore";
+import { observer } from "mobx-react-lite";
 
-export const CountryList = () => {
-  const {dataGridProps} = useDataGrid({})
+export const CountryList = observer(() => {
+  const { language } = languageStore;
+
+  const { dataGridProps } = useDataGrid({
+    resource: "country",
+    meta: {
+      headers: {
+        "Accept-Language": language,
+      },
+    },
+  });
 
   const columns = React.useMemo<GridColDef[]>(
     () => [
       {
-        field: 'code',
-        headerName: 'Код',
-        type: 'string',
+        field: "code",
+        headerName: "Код",
+        type: "string",
         minWidth: 150,
-        align: 'left',
-        headerAlign: 'left',
+        align: "left",
+        headerAlign: "left",
       },
       {
-        field: 'name',
-        headerName: 'Название',
-        type: 'string',
+        field: "name",
+        headerName: "Название",
+        type: "string",
         minWidth: 150,
         flex: 1,
       },
       {
-        field: 'actions',
-        headerName: 'Действия',
-        cellClassName: 'country-actions',
+        field: "actions",
+        headerName: "Действия",
+        cellClassName: "country-actions",
         minWidth: 120,
-        display: 'flex',
-        align: 'right',
-        headerAlign: 'center',
+        display: "flex",
+        align: "right",
+        headerAlign: "center",
         sortable: false,
         filterable: false,
         disableColumnMenu: true,
-        renderCell: function render({row}) {
+        renderCell: function render({ row }) {
           return (
             <>
               <EditButton hideText recordItemId={row.code} />
               <ShowButton hideText recordItemId={row.code} />
-              <DeleteButton hideText confirmTitle="Вы уверены?" recordItemId={row.code} />
+              <DeleteButton
+                hideText
+                confirmTitle="Вы уверены?"
+                recordItemId={row.code}
+              />
             </>
-          )
+          );
         },
       },
     ],
-    [],
-  )
+    []
+  );
 
   return (
     <List>
-      <CustomDataGrid {...dataGridProps} columns={columns} getRowId={(row: any) => row.code} />
+      <CustomDataGrid
+        {...dataGridProps}
+        languageEnabled
+        columns={columns}
+        getRowId={(row: any) => row.code}
+      />
     </List>
-  )
-}
+  );
+});
diff --git a/src/pages/sight/create.tsx b/src/pages/sight/create.tsx
index 2c7e52a..7c0b76a 100644
--- a/src/pages/sight/create.tsx
+++ b/src/pages/sight/create.tsx
@@ -8,24 +8,36 @@ import { TOKEN_KEY } from "../../authProvider";
 import { observer } from "mobx-react-lite";
 import Cookies from "js-cookie";
 import { useLocation } from "react-router";
-
+import { languageStore } from "../../store/LanguageStore";
 export const SightCreate = observer(() => {
-  const [language, setLanguage] = useState(Cookies.get("lang") || "ru");
+  const { language, setLanguageAction } = languageStore;
+  const [sightData, setSightData] = useState({
+    ru: {
+      name: "",
+      address: "",
+    },
+    en: {
+      name: "",
+      address: "",
+    },
+    zh: {
+      name: "",
+      address: "",
+    },
+  });
+
   // Состояния для предпросмотра
   const handleLanguageChange = (lang: string) => {
-    setLanguage(lang);
-    Cookies.set("lang", lang);
+    setSightData((prevData) => ({
+      ...prevData,
+      [language]: {
+        name: watch("name") ?? "",
+        address: watch("address") ?? "",
+      },
+    }));
+    setLanguageAction(lang);
   };
 
-  useEffect(() => {
-    const lang = Cookies.get("lang")!;
-    Cookies.set("lang", language);
-
-    return () => {
-      Cookies.set("lang", lang);
-    };
-  }, [language]);
-
   const {
     saveButtonProps,
     refineCore: { formLoading },
@@ -41,6 +53,17 @@ export const SightCreate = observer(() => {
   });
   const { city_id } = cityStore;
 
+  useEffect(() => {
+    if (sightData[language as keyof typeof sightData]?.name) {
+      setValue("name", sightData[language as keyof typeof sightData]?.name);
+    }
+    if (sightData[language as keyof typeof sightData]?.address) {
+      setValue(
+        "address",
+        sightData[language as keyof typeof sightData]?.address
+      );
+    }
+  }, [sightData, language, setValue]);
   const [namePreview, setNamePreview] = useState("");
   const [coordinatesPreview, setCoordinatesPreview] = useState({
     latitude: "",
diff --git a/src/pages/sight/edit.tsx b/src/pages/sight/edit.tsx
index c19d99e..a71c7f2 100644
--- a/src/pages/sight/edit.tsx
+++ b/src/pages/sight/edit.tsx
@@ -19,6 +19,8 @@ import { TOKEN_KEY } from "../../authProvider";
 import { observer } from "mobx-react-lite";
 
 import { languageStore } from "../../store/LanguageStore";
+import axios from "axios";
+import { LanguageSwitch } from "../../components/LanguageSwitch/index";
 
 function a11yProps(index: number) {
   return {
@@ -53,6 +55,21 @@ export const SightEdit = observer(() => {
   const { id: sightId } = useParams<{ id: string }>();
   const { language, setLanguageAction } = languageStore;
 
+  const [sightData, setSightData] = useState({
+    ru: {
+      name: "",
+      address: "",
+    },
+    en: {
+      name: "",
+      address: "",
+    },
+    zh: {
+      name: "",
+      address: "",
+    },
+  });
+
   const {
     saveButtonProps,
     register,
@@ -71,6 +88,10 @@ export const SightEdit = observer(() => {
     },
   });
 
+  useEffect(() => {
+    setLanguageAction("ru");
+  }, []);
+
   const { autocompleteProps: cityAutocompleteProps } = useAutocomplete({
     resource: "city",
     onSearch: (value) => [
@@ -80,7 +101,20 @@ export const SightEdit = observer(() => {
         value,
       },
     ],
+    meta: {
+      headers: {
+        "Accept-Language": "ru",
+      },
+    },
   });
+  const [mediaFile, setMediaFile] = useState<{
+    src: string;
+    filename: string;
+  }>({
+    src: "",
+    filename: "",
+  });
+
   const [tabValue, setTabValue] = useState(0);
   const { autocompleteProps: mediaAutocompleteProps } = useAutocomplete({
     resource: "media",
@@ -112,6 +146,18 @@ export const SightEdit = observer(() => {
     ],
   });
 
+  useEffect(() => {
+    if (sightData[language as keyof typeof sightData]?.name) {
+      setValue("name", sightData[language as keyof typeof sightData]?.name);
+    }
+    if (sightData[language as keyof typeof sightData]?.address) {
+      setValue(
+        "address",
+        sightData[language as keyof typeof sightData]?.address || ""
+      );
+    }
+  }, [language, sightData, setValue]);
+
   useEffect(() => {
     const latitude = getValues("latitude");
     const longitude = getValues("longitude");
@@ -183,6 +229,46 @@ export const SightEdit = observer(() => {
     });
   }, [latitudeContent, longitudeContent]);
 
+  useEffect(() => {
+    const getMedia = async () => {
+      if (!linkedArticles[selectedArticleIndex]?.id) return;
+      try {
+        const response = await axios.get(
+          `${import.meta.env.VITE_KRBL_API}/article/${
+            linkedArticles[selectedArticleIndex].id
+          }/media`,
+          {
+            headers: {
+              Authorization: `Bearer ${localStorage.getItem(TOKEN_KEY)}`,
+            },
+          }
+        );
+        const media = response.data[0];
+        if (media) {
+          setMediaFile({
+            src: `${import.meta.env.VITE_KRBL_MEDIA}${
+              media.id
+            }/download?token=${localStorage.getItem(TOKEN_KEY)}`,
+            filename: media.filename,
+          });
+          console.log(media);
+        } else {
+          setMediaFile({
+            src: "",
+            filename: "",
+          }); // или другой дефолт
+        }
+      } catch (error) {
+        setMediaFile({
+          src: "",
+          filename: "",
+        }); // или обработка ошибки
+      }
+    };
+
+    getMedia();
+  }, [selectedArticleIndex, linkedArticles]);
+
   useEffect(() => {
     const selectedCity = cityAutocompleteProps.options.find(
       (option) => option.id === cityContent
@@ -243,6 +329,22 @@ export const SightEdit = observer(() => {
     setPreviewArticlePreview(selectedPreviewArticle?.heading || "");
   }, [previewArticleContent, articleAutocompleteProps.options]);
 
+  const handleLanguageChange = (lang: string) => {
+    setSightData((prevData) => ({
+      ...prevData,
+      [language]: {
+        name: watch("name") ?? "",
+        address: watch("address") ?? "",
+      },
+    }));
+    setLanguageAction(lang);
+  };
+  useEffect(() => {
+    return () => {
+      setLanguageAction("ru");
+    };
+  }, [setLanguageAction]);
+
   return (
     <Box sx={{ display: "flex", flexDirection: "column", gap: 2 }}>
       <Box sx={{ borderBottom: 1, borderColor: "divider" }}>
@@ -251,13 +353,167 @@ export const SightEdit = observer(() => {
           onChange={(_, newValue) => setTabValue(newValue)}
           aria-label="basic tabs example"
         >
-          <Tab label="Основная информация" {...a11yProps(1)} />
-          <Tab label="Левый виджет" {...a11yProps(2)} />
-          <Tab label="Правый информация" {...a11yProps(3)} />
+          <Tab label="Левый виджет" {...a11yProps(1)} />
+          <Tab label="Правый виджет" {...a11yProps(2)} />
+          <Tab label="Основная информация" {...a11yProps(3)} />
         </Tabs>
       </Box>
 
       <CustomTabPanel value={tabValue} index={0}>
+        <Edit
+          saveButtonProps={saveButtonProps}
+          footerButtonProps={{
+            sx: {
+              bottom: 0,
+              left: 0,
+            },
+          }}
+        >
+          <Box
+            sx={{
+              maxWidth: "50%",
+              display: "flex",
+              flexDirection: "column",
+              gap: 2,
+              position: "relative",
+            }}
+          >
+            <Box
+              component="form"
+              sx={{ flex: 1, display: "flex", flexDirection: "column" }}
+              autoComplete="off"
+            >
+              <TextField
+                {...register("name", {
+                  required: "Это поле является обязательным",
+                })}
+                error={!!(errors as any)?.name}
+                helperText={(errors as any)?.name?.message}
+                margin="normal"
+                fullWidth
+                InputLabelProps={{ shrink: true }}
+                type="text"
+                label={"Название *"}
+                name="name"
+              />
+            </Box>
+            <LanguageSwitch />
+            <Box sx={{ mt: 3 }}>
+              <LinkedItems<ArticleItem>
+                type="edit"
+                parentId={sightId!}
+                dragAllowed={true}
+                setItemsParent={setLinkedArticles}
+                parentResource="sight"
+                fields={articleFields}
+                childResource="article"
+                title="статьи"
+              />
+
+              <CreateSightArticle
+                parentId={sightId!}
+                parentResource="sight"
+                childResource="article"
+                title="статью"
+              />
+            </Box>
+          </Box>
+        </Edit>
+        <Paper
+          sx={{
+            position: "fixed",
+            p: 2,
+
+            width: "30%",
+
+            top: "178px",
+
+            right: 50,
+            zIndex: 1000,
+            borderRadius: 2,
+            border: "1px solid",
+            borderColor: "primary.main",
+            bgcolor: (theme) =>
+              theme.palette.mode === "dark" ? "background.paper" : "#fff",
+          }}
+        >
+          <Typography variant="h6" gutterBottom color="primary">
+            Предпросмотр
+          </Typography>
+
+          <Box sx={{ mb: 2 }}>
+            {mediaFile.src && (
+              <>
+                {mediaFile.filename.endsWith(".mp4") ? (
+                  <video
+                    style={{ width: "100%", height: "100%" }}
+                    src={mediaFile.src}
+                    controls
+                  />
+                ) : (
+                  <img
+                    style={{ width: "100%", height: "100%" }}
+                    src={mediaFile.src}
+                    alt="Предпросмотр"
+                  />
+                )}
+              </>
+            )}
+            <p style={{ fontSize: "12px", color: "white" }}>
+              {mediaFile.filename}
+            </p>
+          </Box>
+          {/* Водяные знаки */}
+          <Box sx={{ mb: 2 }}>
+            <Box sx={{ display: "flex", flexDirection: "column", gap: 2 }}>
+              {selectedArticle && (
+                <Typography
+                  variant="h4"
+                  gutterBottom
+                  sx={{ color: "text.primary" }}
+                >
+                  {selectedArticle.heading}
+                </Typography>
+              )}
+
+              {selectedArticle && (
+                <Typography
+                  variant="body1"
+                  gutterBottom
+                  sx={{ color: "text.primary" }}
+                >
+                  {selectedArticle.body}
+                </Typography>
+              )}
+            </Box>
+            {/* Координаты */}
+            <Box sx={{ display: "flex", gap: 1, mt: 2 }}>
+              {linkedArticles.map((article, index) => (
+                <Box
+                  key={article.id}
+                  onClick={() => setSelectedArticleIndex(index)}
+                  sx={{
+                    cursor: "pointer",
+                    bgcolor:
+                      selectedArticleIndex === index
+                        ? "primary.main"
+                        : "transparent",
+                    color: selectedArticleIndex === index ? "white" : "inherit",
+                    p: 1,
+                    borderRadius: 1,
+                  }}
+                >
+                  <Typography variant="body1" gutterBottom>
+                    {article.heading}
+                  </Typography>
+                </Box>
+              ))}
+            </Box>
+          </Box>
+        </Paper>
+      </CustomTabPanel>
+
+      <CustomTabPanel value={tabValue} index={1}>
         <Edit
           saveButtonProps={saveButtonProps}
           footerButtonProps={{
@@ -297,7 +553,7 @@ export const SightEdit = observer(() => {
                     p: 1,
                     borderRadius: 1,
                   }}
-                  onClick={() => setLanguageAction("ru")}
+                  onClick={() => handleLanguageChange("ru")}
                 >
                   RU
                 </Box>
@@ -312,7 +568,7 @@ export const SightEdit = observer(() => {
                     p: 1,
                     borderRadius: 1,
                   }}
-                  onClick={() => setLanguageAction("en")}
+                  onClick={() => handleLanguageChange("en")}
                 >
                   EN
                 </Box>
@@ -327,7 +583,7 @@ export const SightEdit = observer(() => {
                     p: 1,
                     borderRadius: 1,
                   }}
-                  onClick={() => setLanguageAction("zh")}
+                  onClick={() => handleLanguageChange("zh")}
                 >
                   ZH
                 </Box>
@@ -776,135 +1032,6 @@ export const SightEdit = observer(() => {
           </Box>
         </Edit>
       </CustomTabPanel>
-      <CustomTabPanel value={tabValue} index={1}>
-        <Edit
-          saveButtonProps={saveButtonProps}
-          footerButtonProps={{
-            sx: {
-              bottom: 0,
-              left: 0,
-            },
-          }}
-        >
-          <Box
-            sx={{
-              maxWidth: "50%",
-              display: "flex",
-              flexDirection: "column",
-              gap: 2,
-              position: "relative",
-            }}
-          >
-            <Box
-              component="form"
-              sx={{ flex: 1, display: "flex", flexDirection: "column" }}
-              autoComplete="off"
-            >
-              <TextField
-                {...register("name", {
-                  required: "Это поле является обязательным",
-                })}
-                error={!!(errors as any)?.name}
-                helperText={(errors as any)?.name?.message}
-                margin="normal"
-                fullWidth
-                InputLabelProps={{ shrink: true }}
-                type="text"
-                label={"Название *"}
-                name="name"
-              />
-            </Box>
-            <Box sx={{ mt: 3 }}>
-              <LinkedItems<ArticleItem>
-                type="edit"
-                parentId={sightId!}
-                setItemsParent={setLinkedArticles}
-                parentResource="sight"
-                fields={articleFields}
-                childResource="article"
-                title="статьи"
-              />
-
-              <CreateSightArticle
-                parentId={sightId!}
-                parentResource="sight"
-                childResource="article"
-                title="статью"
-              />
-            </Box>
-          </Box>
-        </Edit>
-        <Paper
-          sx={{
-            position: "fixed",
-            p: 2,
-
-            width: "30%",
-
-            top: "178px",
-
-            right: 50,
-            zIndex: 1000,
-            borderRadius: 2,
-            border: "1px solid",
-            borderColor: "primary.main",
-            bgcolor: (theme) =>
-              theme.palette.mode === "dark" ? "background.paper" : "#fff",
-          }}
-        >
-          <Typography variant="h6" gutterBottom color="primary">
-            Предпросмотр
-          </Typography>
-
-          {/* Водяные знаки */}
-          <Box sx={{ mb: 2 }}>
-            <Box sx={{ display: "flex", flexDirection: "column", gap: 2 }}>
-              {selectedArticle && (
-                <Typography
-                  variant="h4"
-                  gutterBottom
-                  sx={{ color: "text.primary" }}
-                >
-                  {selectedArticle.heading}
-                </Typography>
-              )}
-
-              {selectedArticle && (
-                <Typography
-                  variant="body1"
-                  gutterBottom
-                  sx={{ color: "text.primary" }}
-                >
-                  {selectedArticle.body}
-                </Typography>
-              )}
-            </Box>
-            {/* Координаты */}
-            <Box sx={{ display: "flex", gap: 1, mt: 2 }}>
-              {linkedArticles.map((article, index) => (
-                <Box
-                  key={article.id}
-                  onClick={() => setSelectedArticleIndex(index)}
-                  sx={{
-                    cursor: "pointer",
-                    bgcolor:
-                      selectedArticleIndex === index
-                        ? "primary.main"
-                        : "transparent",
-                    color: selectedArticleIndex === index ? "white" : "inherit",
-                    p: 1,
-                    borderRadius: 1,
-                  }}
-                >
-                  <Typography variant="body1" gutterBottom>
-                    {article.heading}
-                  </Typography>
-                </Box>
-              ))}
-            </Box>
-          </Box>
-        </Paper>
-      </CustomTabPanel>
       <CustomTabPanel value={tabValue} index={2}>
         <Edit
           saveButtonProps={saveButtonProps}
@@ -928,6 +1055,7 @@ export const SightEdit = observer(() => {
               sx={{ flex: 1, display: "flex", flexDirection: "column" }}
               autoComplete="off"
             >
+              <LanguageSwitch />
               <Controller
                 control={control}
                 name="watermark_lu"
diff --git a/src/pages/sight/list.tsx b/src/pages/sight/list.tsx
index f75bf7f..6b50585 100644
--- a/src/pages/sight/list.tsx
+++ b/src/pages/sight/list.tsx
@@ -1,4 +1,4 @@
-import React from "react";
+import React, { useEffect } from "react";
 import { type GridColDef } from "@mui/x-data-grid";
 import {
   DeleteButton,
@@ -12,11 +12,21 @@ import { CustomDataGrid } from "../../components/CustomDataGrid";
 import { localeText } from "../../locales/ru/localeText";
 import { cityStore } from "../../store/CityStore";
 import { observer } from "mobx-react-lite";
+import { languageStore } from "../../store/LanguageStore";
 
 export const SightList = observer(() => {
   const { city_id } = cityStore;
+  const { language } = languageStore;
+
   const { dataGridProps } = useDataGrid({
-    resource: "sight/",
+    resource: "sight",
+
+    meta: {
+      headers: {
+        "Accept-Language": language,
+      },
+    },
+
     filters: {
       permanent: [
         {
@@ -147,6 +157,7 @@ export const SightList = observer(() => {
       <Stack gap={2.5}>
         <CustomDataGrid
           {...dataGridProps}
+          languageEnabled
           columns={columns}
           localeText={localeText}
           getRowId={(row: any) => row.id}
diff --git a/src/pages/station/edit.tsx b/src/pages/station/edit.tsx
index 96a4fa6..cd9933d 100644
--- a/src/pages/station/edit.tsx
+++ b/src/pages/station/edit.tsx
@@ -15,6 +15,10 @@ import { Controller } from "react-hook-form";
 import { useParams } from "react-router";
 import { LinkedItems } from "../../components/LinkedItems";
 import { type SightItem, sightFields } from "./types";
+import { observer } from "mobx-react-lite";
+import { languageStore } from "../../store/LanguageStore";
+import { useEffect, useState } from "react";
+import { LanguageSwitch } from "../../components/LanguageSwitch/index";
 
 const TRANSFER_FIELDS = [
   { name: "bus", label: "Автобус" },
@@ -28,16 +32,126 @@ const TRANSFER_FIELDS = [
   { name: "trolleybus", label: "Троллейбус" },
 ];
 
-export const StationEdit = () => {
+export const StationEdit = observer(() => {
+  const { language, setLanguageAction } = languageStore;
+  const [stationData, setStationData] = useState({
+    ru: {
+      name: "",
+      system_name: "",
+      description: "",
+      address: "",
+      latitude: "",
+      longitude: "",
+    },
+    en: {
+      name: "",
+      system_name: "",
+      description: "",
+      address: "",
+      latitude: "",
+      longitude: "",
+    },
+    zh: {
+      name: "",
+      system_name: "",
+      description: "",
+      address: "",
+      latitude: "",
+      longitude: "",
+    },
+  });
+
+  const handleLanguageChange = () => {
+    setStationData((prevData) => ({
+      ...prevData,
+      [language]: {
+        name: watch("name") ?? "",
+        system_name: watch("system_name") ?? "",
+        description: watch("description") ?? "",
+        address: watch("address") ?? "",
+        latitude: watch("latitude") ?? "",
+        longitude: watch("longitude") ?? "",
+      },
+    }));
+  };
+
+  const [coordinatesPreview, setCoordinatesPreview] = useState({
+    latitude: "",
+    longitude: "",
+  });
+
   const {
     saveButtonProps,
     register,
     control,
+    getValues,
+    setValue,
+    watch,
     formState: { errors },
-  } = useForm({});
+  } = useForm({
+    refineCoreProps: {
+      meta: {
+        headers: { "Accept-Language": language },
+      },
+    },
+  });
+
+  useEffect(() => {
+    if (stationData[language as keyof typeof stationData]?.name) {
+      setValue("name", stationData[language as keyof typeof stationData]?.name);
+    }
+    if (stationData[language as keyof typeof stationData]?.address) {
+      setValue(
+        "system_name",
+        stationData[language as keyof typeof stationData]?.system_name || ""
+      );
+    }
+    if (stationData[language as keyof typeof stationData]?.description) {
+      setValue(
+        "description",
+        stationData[language as keyof typeof stationData]?.description || ""
+      );
+    }
+    if (stationData[language as keyof typeof stationData]?.latitude) {
+      setValue(
+        "latitude",
+        stationData[language as keyof typeof stationData]?.latitude || ""
+      );
+    }
+    if (stationData[language as keyof typeof stationData]?.longitude) {
+      setValue(
+        "longitude",
+        stationData[language as keyof typeof stationData]?.longitude || ""
+      );
+    }
+  }, [language, stationData, setValue]);
+
+  useEffect(() => {
+    setLanguageAction("ru");
+  }, []);
 
   const { id: stationId } = useParams<{ id: string }>();
 
+  const handleCoordinatesChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+    const [lat, lon] = e.target.value.split(",").map((s) => s.trim());
+    setCoordinatesPreview({
+      latitude: lat,
+      longitude: lon,
+    });
+    setValue("latitude", lat);
+    setValue("longitude", lon);
+  };
+
+  const latitudeContent = watch("latitude");
+  const longitudeContent = watch("longitude");
+
+  useEffect(() => {
+    setCoordinatesPreview({
+      latitude: latitudeContent || "",
+      longitude: longitudeContent || "",
+    });
+  }, [latitudeContent, longitudeContent]);
+
   const { autocompleteProps: cityAutocompleteProps } = useAutocomplete({
     resource: "city",
     onSearch: (value) => [
@@ -47,8 +161,28 @@ export const StationEdit = () => {
         value,
       },
     ],
+
+    meta: {
+      headers: {
+        "Accept-Language": "ru",
+      },
+    },
+    queryOptions: {
+      queryKey: ["city"],
+    },
   });
 
+  useEffect(() => {
+    const latitude = getValues("latitude");
+    const longitude = getValues("longitude");
+    if (latitude && longitude) {
+      setCoordinatesPreview({
+        latitude: latitude,
+        longitude: longitude,
+      });
+    }
+  }, [getValues]);
+
   return (
     <Edit saveButtonProps={saveButtonProps}>
       <Box
@@ -56,6 +190,7 @@ export const StationEdit = () => {
         sx={{ display: "flex", flexDirection: "column" }}
         autoComplete="off"
       >
+        <LanguageSwitch action={handleLanguageChange} />
         <TextField
           {...register("name", {
             required: "Это поле является обязательным",
@@ -125,33 +260,27 @@ export const StationEdit = () => {
           label={"Адрес"}
           name="address"
         />
+
         <TextField
-          {...register("latitude", {
-            required: "Это поле является обязательным",
-            valueAsNumber: true,
-          })}
+          value={`${coordinatesPreview.latitude}, ${coordinatesPreview.longitude}`}
+          onChange={handleCoordinatesChange}
           error={!!(errors as any)?.latitude}
           helperText={(errors as any)?.latitude?.message}
           margin="normal"
           fullWidth
           InputLabelProps={{ shrink: true }}
-          type="number"
-          label={"Широта *"}
-          name="latitude"
+          type="text"
+          label={"Координаты *"}
         />
-        <TextField
-          {...register("longitude", {
-            required: "Это поле является обязательным",
-            valueAsNumber: true,
+        <input
+          type="hidden"
+          {...register("latitude", {
+            value: coordinatesPreview.latitude,
           })}
-          error={!!(errors as any)?.longitude}
-          helperText={(errors as any)?.longitude?.message}
-          margin="normal"
-          fullWidth
-          InputLabelProps={{ shrink: true }}
-          type="number"
-          label={"Долгота *"}
-          name="longitude"
+        />
+        <input
+          type="hidden"
+          {...register("longitude", { value: coordinatesPreview.longitude })}
         />
 
         <Controller
@@ -210,4 +339,4 @@ export const StationEdit = () => {
       )}
     </Edit>
   );
-};
+});
diff --git a/src/pages/station/list.tsx b/src/pages/station/list.tsx
index bb831aa..2713010 100644
--- a/src/pages/station/list.tsx
+++ b/src/pages/station/list.tsx
@@ -1,4 +1,4 @@
-import React, { useMemo } from "react";
+import React, { useEffect, useMemo } from "react";
 import { type GridColDef } from "@mui/x-data-grid";
 import {
   DeleteButton,
@@ -12,12 +12,19 @@ import { CustomDataGrid } from "../../components/CustomDataGrid";
 import { localeText } from "../../locales/ru/localeText";
 import { cityStore } from "../../store/CityStore";
 import { observer } from "mobx-react-lite";
+import { languageStore } from "../../store/LanguageStore";
 
 export const StationList = observer(() => {
   const { city_id } = cityStore;
+  const { language } = languageStore;
 
   const { dataGridProps } = useDataGrid({
     resource: "station",
+    meta: {
+      headers: {
+        "Accept-Language": language,
+      },
+    },
     filters: {
       permanent: [
         {
@@ -160,6 +167,7 @@ export const StationList = observer(() => {
         <CustomDataGrid
           {...dataGridProps}
           columns={columns}
+          languageEnabled
           localeText={localeText}
           getRowId={(row: any) => row.id}
           hasCoordinates
diff --git a/src/pages/vehicle/edit.tsx b/src/pages/vehicle/edit.tsx
index 5c612b9..af57990 100644
--- a/src/pages/vehicle/edit.tsx
+++ b/src/pages/vehicle/edit.tsx
@@ -1,48 +1,52 @@
-import {Autocomplete, Box, TextField} from '@mui/material'
-import {Edit, useAutocomplete} from '@refinedev/mui'
-import {useForm} from '@refinedev/react-hook-form'
-import {Controller} from 'react-hook-form'
+import { Autocomplete, Box, TextField } from "@mui/material";
+import { Edit, useAutocomplete } from "@refinedev/mui";
+import { useForm } from "@refinedev/react-hook-form";
+import { Controller } from "react-hook-form";
 
-import {VEHICLE_TYPES} from '../../lib/constants'
+import { VEHICLE_TYPES } from "../../lib/constants";
 
 type VehicleFormValues = {
-  tail_number: number
-  type: number
-  city_id: number
-}
+  tail_number: number;
+  type: number;
+  city_id: number;
+};
 
 export const VehicleEdit = () => {
   const {
     saveButtonProps,
     register,
     control,
-    formState: {errors},
-  } = useForm<VehicleFormValues>({})
+    formState: { errors },
+  } = useForm<VehicleFormValues>({});
 
-  const {autocompleteProps: carrierAutocompleteProps} = useAutocomplete({
-    resource: 'carrier',
+  const { autocompleteProps: carrierAutocompleteProps } = useAutocomplete({
+    resource: "carrier",
     onSearch: (value) => [
       {
-        field: 'short_name',
-        operator: 'contains',
+        field: "short_name",
+        operator: "contains",
         value,
       },
     ],
-  })
+  });
 
   return (
     <Edit saveButtonProps={saveButtonProps}>
-      <Box component="form" sx={{display: 'flex', flexDirection: 'column'}} autoComplete="off">
+      <Box
+        component="form"
+        sx={{ display: "flex", flexDirection: "column" }}
+        autoComplete="off"
+      >
         <TextField
-          {...register('tail_number', {
-            required: 'Это поле является обязательным',
+          {...register("tail_number", {
+            required: "Это поле является обязательным",
             valueAsNumber: true,
           })}
           error={!!(errors as any)?.tail_number}
           helperText={(errors as any)?.tail_number?.message}
           margin="normal"
           fullWidth
-          InputLabelProps={{shrink: true}}
+          InputLabelProps={{ shrink: true }}
           type="number"
           label="Бортовой номер *"
           name="tail_number"
@@ -52,23 +56,36 @@ export const VehicleEdit = () => {
           control={control}
           name="type"
           rules={{
-            required: 'Это поле является обязательным',
+            required: "Это поле является обязательным",
           }}
           defaultValue={null}
-          render={({field}) => (
+          render={({ field }) => (
             <Autocomplete
               options={VEHICLE_TYPES}
-              value={VEHICLE_TYPES.find((option) => option.value === field.value) || null}
+              value={
+                VEHICLE_TYPES.find((option) => option.value === field.value) ||
+                null
+              }
               onChange={(_, value) => {
-                field.onChange(value?.value || null)
+                field.onChange(value?.value || null);
               }}
               getOptionLabel={(item) => {
-                return item ? item.label : ''
+                return item ? item.label : "";
               }}
               isOptionEqualToValue={(option, value) => {
-                return option.value === value?.value
+                return option.value === value?.value;
               }}
-              renderInput={(params) => <TextField {...params} label="Выберите тип" margin="normal" variant="outlined" error={!!errors.type} helperText={(errors as any)?.type?.message} required />}
+              renderInput={(params) => (
+                <TextField
+                  {...params}
+                  label="Выберите тип"
+                  margin="normal"
+                  variant="outlined"
+                  error={!!errors.type}
+                  helperText={(errors as any)?.type?.message}
+                  required
+                />
+              )}
             />
           )}
         />
@@ -76,29 +93,47 @@ export const VehicleEdit = () => {
         <Controller
           control={control}
           name="carrier_id"
-          rules={{required: 'Это поле является обязательным'}}
+          rules={{ required: "Это поле является обязательным" }}
           defaultValue={null}
-          render={({field}) => (
+          render={({ field }) => (
             <Autocomplete
               {...carrierAutocompleteProps}
-              value={carrierAutocompleteProps.options.find((option) => option.id === field.value) || null}
+              value={
+                carrierAutocompleteProps.options.find(
+                  (option) => option.id === field.value
+                ) || null
+              }
               onChange={(_, value) => {
-                field.onChange(value?.id || '')
+                field.onChange(value?.id || "");
               }}
               getOptionLabel={(item) => {
-                return item ? item.short_name : ''
+                return item ? item.short_name : "";
               }}
               isOptionEqualToValue={(option, value) => {
-                return option.id === value?.id
+                return option.id === value?.id;
               }}
-              filterOptions={(options, {inputValue}) => {
-                return options.filter((option) => option.short_name.toLowerCase().includes(inputValue.toLowerCase()))
+              filterOptions={(options, { inputValue }) => {
+                return options.filter((option) =>
+                  option.short_name
+                    .toLowerCase()
+                    .includes(inputValue.toLowerCase())
+                );
               }}
-              renderInput={(params) => <TextField {...params} label="Выберите перевозчика" margin="normal" variant="outlined" error={!!errors.city_id} helperText={(errors as any)?.city_id?.message} required />}
+              renderInput={(params) => (
+                <TextField
+                  {...params}
+                  label="Выберите перевозчика"
+                  margin="normal"
+                  variant="outlined"
+                  error={!!errors.city_id}
+                  helperText={(errors as any)?.city_id?.message}
+                  required
+                />
+              )}
             />
           )}
         />
       </Box>
     </Edit>
-  )
-}
+  );
+};
diff --git a/src/pages/vehicle/list.tsx b/src/pages/vehicle/list.tsx
index 74d03c5..b3e3722 100644
--- a/src/pages/vehicle/list.tsx
+++ b/src/pages/vehicle/list.tsx
@@ -1,91 +1,120 @@
-import {type GridColDef} from '@mui/x-data-grid'
-import {CustomDataGrid} from '../../components/CustomDataGrid'
-import {DeleteButton, EditButton, List, ShowButton, useDataGrid} from '@refinedev/mui'
-import React from 'react'
-import {VEHICLE_TYPES} from '../../lib/constants'
+import { type GridColDef } from "@mui/x-data-grid";
+import { CustomDataGrid } from "../../components/CustomDataGrid";
+import {
+  DeleteButton,
+  EditButton,
+  List,
+  ShowButton,
+  useDataGrid,
+} from "@refinedev/mui";
+import React, { useEffect } from "react";
+import { VEHICLE_TYPES } from "../../lib/constants";
 
-import {localeText} from '../../locales/ru/localeText'
+import { localeText } from "../../locales/ru/localeText";
+import { observer } from "mobx-react-lite";
+import { languageStore } from "../../store/LanguageStore";
 
-export const VehicleList = () => {
-  const {dataGridProps} = useDataGrid({})
+export const VehicleList = observer(() => {
+  const { language } = languageStore;
+
+  const { dataGridProps } = useDataGrid({
+    resource: "vehicle",
+    meta: {
+      headers: {
+        "Accept-Language": language,
+      },
+    },
+  });
 
   const columns = React.useMemo<GridColDef[]>(
     () => [
       {
-        field: 'id',
-        headerName: 'ID',
-        type: 'number',
+        field: "id",
+        headerName: "ID",
+        type: "number",
         minWidth: 70,
-        display: 'flex',
-        align: 'left',
-        headerAlign: 'left',
+        display: "flex",
+        align: "left",
+        headerAlign: "left",
       },
       {
-        field: 'carrier_id',
-        headerName: 'ID перевозчика',
-        type: 'string',
+        field: "carrier_id",
+        headerName: "ID перевозчика",
+        type: "string",
         minWidth: 150,
-        display: 'flex',
-        align: 'left',
-        headerAlign: 'left',
+        display: "flex",
+        align: "left",
+        headerAlign: "left",
       },
       {
-        field: 'tail_number',
-        headerName: 'Бортовой номер',
-        type: 'number',
+        field: "tail_number",
+        headerName: "Бортовой номер",
+        type: "number",
         minWidth: 150,
-        display: 'flex',
-        align: 'left',
-        headerAlign: 'left',
+        display: "flex",
+        align: "left",
+        headerAlign: "left",
       },
       {
-        field: 'type',
-        headerName: 'Тип',
-        type: 'string',
+        field: "type",
+        headerName: "Тип",
+        type: "string",
         minWidth: 200,
-        display: 'flex',
-        align: 'left',
-        headerAlign: 'left',
+        display: "flex",
+        align: "left",
+        headerAlign: "left",
         renderCell: (params) => {
-          const value = params.row.type
-          return VEHICLE_TYPES.find((type) => type.value === value)?.label || value
+          const value = params.row.type;
+          return (
+            VEHICLE_TYPES.find((type) => type.value === value)?.label || value
+          );
         },
       },
       {
-        field: 'city',
-        headerName: 'Город',
-        type: 'string',
-        align: 'left',
-        headerAlign: 'left',
+        field: "city",
+        headerName: "Город",
+        type: "string",
+        align: "left",
+        headerAlign: "left",
         flex: 1,
       },
       {
-        field: 'actions',
-        headerName: 'Действия',
+        field: "actions",
+        headerName: "Действия",
         minWidth: 120,
-        display: 'flex',
-        align: 'right',
-        headerAlign: 'center',
+        display: "flex",
+        align: "right",
+        headerAlign: "center",
         sortable: false,
         filterable: false,
         disableColumnMenu: true,
-        renderCell: function render({row}) {
+        renderCell: function render({ row }) {
           return (
             <>
               <EditButton hideText recordItemId={row.id} />
               <ShowButton hideText recordItemId={row.id} />
-              <DeleteButton hideText confirmTitle="Вы уверены?" recordItemId={row.id} />
+              <DeleteButton
+                hideText
+                confirmTitle="Вы уверены?"
+                recordItemId={row.id}
+              />
             </>
-          )
+          );
         },
       },
     ],
-    [],
-  )
+    []
+  );
 
   return (
     <List>
-      <CustomDataGrid {...dataGridProps} columns={columns} localeText={localeText} getRowId={(row: any) => row.id} />
+      <CustomDataGrid
+        {...dataGridProps}
+        languageEnabled
+        columns={columns}
+        localeText={localeText}
+        getRowId={(row: any) => row.id}
+      />
     </List>
-  )
-}
+  );
+});
diff --git a/src/store/ArticleStore.ts b/src/store/ArticleStore.ts
new file mode 100644
index 0000000..f844e28
--- /dev/null
+++ b/src/store/ArticleStore.ts
@@ -0,0 +1,20 @@
+import { makeAutoObservable } from "mobx";
+
+class ArticleStore {
+  articleModalOpen: boolean = false;
+  selectedArticleId: number | null = null;
+
+  constructor() {
+    makeAutoObservable(this);
+  }
+
+  setArticleIdAction = (id: number) => {
+    this.selectedArticleId = id;
+  };
+
+  setArticleModalOpenAction = (open: boolean) => {
+    this.articleModalOpen = open;
+  };
+}
+
+export const articleStore = new ArticleStore();
diff --git a/src/store/StationStore.ts b/src/store/StationStore.ts
new file mode 100644
index 0000000..5304821
--- /dev/null
+++ b/src/store/StationStore.ts
@@ -0,0 +1,20 @@
+import { makeAutoObservable } from "mobx";
+
+class StationStore {
+  stationModalOpen: boolean = false;
+  selectedStationId: number | null = null;
+
+  constructor() {
+    makeAutoObservable(this);
+  }
+
+  setStationIdAction = (id: number) => {
+    this.selectedStationId = id;
+  };
+
+  setStationModalOpenAction = (open: boolean) => {
+    this.stationModalOpen = open;
+  };
+}
+
+export const stationStore = new StationStore();