140 lines
6.1 KiB
TypeScript
140 lines
6.1 KiB
TypeScript
import i18n from "i18next";
|
||
import { initReactI18next } from "react-i18next";
|
||
import Backend from "i18next-http-backend";
|
||
|
||
// 1. Функция для принудительного определения языка из URL
|
||
const getLanguageFromURL = (): string => {
|
||
const path = window.location.pathname;
|
||
|
||
// Регулярка для /en/ /ru/ /uz/ в начале пути
|
||
const langMatch = path.match(/^\/(en|ru|uz)(\/|$)/i);
|
||
|
||
if (langMatch) {
|
||
//console.log("Язык из URL:", langMatch[1]);
|
||
return langMatch[1].toLowerCase();
|
||
}
|
||
|
||
//console.log('Язык не указан в URL, используем "ru"');
|
||
return "ru"; // Жёсткий фолбэк
|
||
};
|
||
|
||
const r = {
|
||
ru: {
|
||
"quiz is inactive": "Квиз не активирован",
|
||
"no questions found": "Нет созданных вопросов",
|
||
"quiz is empty": "Квиз пуст",
|
||
"quiz already completed": "Вы уже прошли этот опрос",
|
||
"no quiz id": "Отсутствует id квиза",
|
||
"quiz data is null": "Не были переданы параметры квиза",
|
||
"invalid request data": "Такого квиза не существует",
|
||
"default message": "Что-то пошло не так",
|
||
"The request could not be sent": "Заявка не может быть отправлена",
|
||
"The number of points could not be sent": "Количество баллов не может быть отправлено",
|
||
"Your result": "Ваш результат",
|
||
"Your points": "Ваши баллы",
|
||
of: "из",
|
||
"View answers": "Посмотреть ответы",
|
||
"Find out more": "Узнать подробнее",
|
||
"Go to website": "Перейти на сайт",
|
||
"Question title": "Заголовок вопроса",
|
||
"Question without a title": "Вопрос без названия",
|
||
"Your answer": "Ваш ответ",
|
||
"Add image": "Добавить изображение",
|
||
"Accepts images": "Принимает изображения",
|
||
"Add video": "Добавить видео",
|
||
"Accepts .mp4 and .mov format - maximum 50mb": "Принимает .mp4 и .mov формат — максимум 50мб",
|
||
"Add audio file": "Добавить аудиофайл",
|
||
"Accepts audio files": "Принимает аудиофайлы",
|
||
"Add document": "Добавить документ",
|
||
"Accepts documents": "Принимает документы",
|
||
Next: "Далее",
|
||
Prev: "Назад",
|
||
From: "От",
|
||
До: "До",
|
||
"Enter your answer": "Введите свой ответ",
|
||
"Incorrect file type selected": "Выбран некорректный тип файла",
|
||
"File is too big. Maximum size is 50 MB": "Файл слишком большой. Максимальный размер 50 МБ",
|
||
"Acceptable file extensions": "Допустимые расширения файлов",
|
||
"You have uploaded": "Вы загрузили",
|
||
"The answer was not counted": "Ответ не был засчитан",
|
||
"Select an answer option below": "Выберите вариант ответа ниже",
|
||
"Select an answer option on the left": "Выберите вариант ответа слева",
|
||
"Fill out the form to receive your test results": "Заполните форму, чтобы получить результаты теста",
|
||
Enter: "Введите",
|
||
Name: "Имя",
|
||
"Phone number": "Номер телефона",
|
||
"Last name": "Фамилия",
|
||
Address: "Адрес",
|
||
"Incorrect email entered": "Введена некорректная почта",
|
||
"Please fill in the fields": "Пожалуйста, заполните поля",
|
||
"Please try again later": "повторите попытку позже",
|
||
"Regulation on the processing of personal data": "Положением об обработке персональных данных",
|
||
"Privacy Policy": "Политикой конфиденциальности",
|
||
familiarized: "ознакомлен",
|
||
and: "и",
|
||
"Get results": "Получить результаты",
|
||
"Data sent successfully": "Данные успешно отправлены",
|
||
Step: "Шаг",
|
||
"questions are not ready yet": "Вопросы для аудитории ещё не созданы. Пожалуйста, подождите",
|
||
"Add your image": "Добавьте своё изображение",
|
||
"select emoji": "выберите смайлик",
|
||
},
|
||
};
|
||
|
||
// 2. Конфиг с полной отладкой
|
||
i18n
|
||
.use(Backend)
|
||
.use(initReactI18next)
|
||
.init({
|
||
resources: r,
|
||
lng: getLanguageFromURL(), // Принудительно из URL
|
||
fallbackLng: "ru",
|
||
supportedLngs: ["en", "ru", "uz"],
|
||
debug: true,
|
||
interpolation: {
|
||
escapeValue: false,
|
||
},
|
||
backend: {
|
||
loadPath: "/locales/{{lng}}.json",
|
||
allowMultiLoading: false,
|
||
},
|
||
react: {
|
||
useSuspense: false, // Отключаем для совместимости с React 18
|
||
},
|
||
detection: {
|
||
order: ["path"], // Только из URL
|
||
lookupFromPathIndex: 0,
|
||
caches: [], // Не использовать localStorage
|
||
},
|
||
parseMissingKeyHandler: (key) => {
|
||
console.warn("Missing translation:", key);
|
||
return key; // Вернёт ключ вместо ошибки
|
||
},
|
||
missingKeyHandler: (lngs, ns, key) => {
|
||
console.error("🚨 Missing i18n key:", {
|
||
key,
|
||
languages: lngs,
|
||
namespace: ns,
|
||
stack: new Error().stack, // Выведет стек вызовов
|
||
});
|
||
},
|
||
})
|
||
.then(() => {
|
||
//console.log("i18n инициализирован! Текущий язык:", i18n.language);
|
||
//console.log("Загруженные переводы:", i18n.store.data);
|
||
})
|
||
.catch((err) => {
|
||
console.error("Ошибка i18n:", err);
|
||
});
|
||
|
||
// 3. Логирование всех событий
|
||
i18n.on("languageChanged", (lng) => {
|
||
console.log("Язык изменён на:", lng);
|
||
});
|
||
|
||
i18n.on("failedLoading", (lng, ns, msg) => {
|
||
console.error(`Ошибка загрузки ${lng}.json:`, msg);
|
||
});
|
||
|
||
export default i18n;
|