Смена языка динамически

Библиотека MUI (Material-UI) предоставляет встроенные механизмы для локализации компонентов, что особенно важно для приложений с поддержкой нескольких языков. Динамическая смена языка позволяет менять локализацию интерфейса без перезагрузки страницы, сохраняя состояние компонентов.

Подключение локализации MUI

Для начала необходимо импортировать нужные пакеты локализации. MUI предоставляет набор готовых локалей в пакете @mui/material/locale. Пример импорта:

import { createTheme, ThemeProvider } from '@mui/material/styles';
import { Button } from '@mui/material';
import { ruRU, enUS } from '@mui/material/locale';
  • ruRU — локаль для русского языка.
  • enUS — локаль для английского языка.

Каждая локаль содержит переводы текста компонентов, а также настройки форматов чисел, даты и времени.

Создание темы с локализацией

Локаль MUI интегрируется в тему приложения с помощью функции createTheme.

const themeRU = createTheme({}, ruRU);
const themeEN = createTheme({}, enUS);

Пустой объект {} перед локалью позволяет расширять тему дополнительными настройками: цвета, типографику, компоненты.

Организация состояния текущего языка

Динамическая смена языка требует хранить текущее состояние локали. В React это удобно реализовать через useState или контекст.

import React, { useState } from 'react';
import { ThemeProvider, Button } from '@mui/material';

function App() {
  const [locale, setLocale] = useState('en');

  const theme = locale === 'ru' ? createTheme({}, ruRU) : createTheme({}, enUS);

  return (
    <ThemeProvider theme={theme}>
      <Button onCl ick={() => setLocale(locale === 'ru' ? 'en' : 'ru')}>
        Сменить язык
      </Button>
    </ThemeProvider>
  );
}
  • При изменении состояния locale происходит пересоздание темы с новой локалью.
  • Все компоненты MUI, обернутые в ThemeProvider, автоматически обновляют язык.

Использование контекста для глобальной локали

Для больших приложений рекомендуется вынести язык в отдельный контекст, чтобы доступ к нему был в любом компоненте без проброса пропсов.

import React, { createContext, useState, useContext } from 'react';

const LocaleContext = createContext();

export const useLocale = () => useContext(LocaleContext);

export function LocaleProvider({ children }) {
  const [locale, setLocale] = useState('en');
  const theme = locale === 'ru' ? createTheme({}, ruRU) : createTheme({}, enUS);

  return (
    <LocaleContext.Provider value={{ locale, setLocale }}>
      <ThemeProvider theme={theme}>
        {children}
      </ThemeProvider>
    </LocaleContext.Provider>
  );
}

Компоненты могут получать язык и функцию смены через хук useLocale:

function LanguageSwitcher() {
  const { locale, setLocale } = useLocale();

  return (
    <Button onCl ick={() => setLocale(locale === 'ru' ? 'en' : 'ru')}>
      Сменить язык
    </Button>
  );
}

Синхронизация с внешними библиотеками

Если приложение использует i18n библиотеки (например, react-i18next), важно синхронизировать локаль MUI с текущим языком i18n:

import { useTranslation } from 'react-i18next';

function App() {
  const { i18n } = useTranslation();
  const [locale, setLocale] = useState(i18n.language);

  const theme = locale === 'ru' ? createTheme({}, ruRU) : createTheme({}, enUS);

  const handleChangeLanguage = (lang) => {
    i18n.changeLanguage(lang);
    setLocale(lang);
  };

  return (
    <ThemeProvider theme={theme}>
      <Button onCl ick={() => handleChangeLanguage(locale === 'ru' ? 'en' : 'ru')}>
        Сменить язык
      </Button>
    </ThemeProvider>
  );
}

Таким образом, текст компонентов MUI и собственные строки приложения будут синхронно обновляться при смене языка.

Локализация форматов и компонентов

MUI локали влияют на следующие аспекты:

  • Кнопки и элементы управления — переводы стандартных надписей (ok, cancel).
  • Диалоги и модальные окна — переводы текста действий и подсказок.
  • DatePicker, TimePicker, DataGrid — форматирование даты, времени, чисел и таблиц в соответствии с языком.

Пример для DatePicker с динамическим языком:

import { LocalizationProvider, DatePicker } from '@mui/x-date-pickers';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import ruLocale from 'date-fns/locale/ru';
import enLocale from 'date-fns/locale/en-US';

function Calendar() {
  const { locale } = useLocale();
  const dateLocale = locale === 'ru' ? ruLocale : enLocale;

  return (
    <LocalizationProvider dateAdapter={AdapterDateFns} locale={dateLocale}>
      <DatePicker label="Выберите дату" />
    </LocalizationProvider>
  );
}

Оптимизация и производительность

  • Создание темы при каждом рендере может быть затратным. Рекомендуется использовать useMemo для кеширования темы:
const theme = React.useMemo(
  () => (locale === 'ru' ? createTheme({}, ruRU) : createTheme({}, enUS)),
  [locale]
);
  • Это уменьшает лишние перерасчёты стилей и ускоряет работу приложения.

  • Для приложений с поддержкой множества языков можно загружать локали лениво, чтобы уменьшить размер бандла.

const localeMap = {
  ru: () => import('@mui/material/locale/ruRU'),
  en: () => import('@mui/material/locale/enUS'),
};

Динамическая смена языка в MUI позволяет создавать полностью локализованные приложения с мгновенным обновлением интерфейса, сохраняя состояние компонентов и форматирование данных в соответствии с выбранным языком.