import i18n from "i18next"; import { initReactI18next } from "react-i18next"; // 1. Функция для определения языка из URL const getLanguageFromURL = (): string => { const path = window.location.pathname; const langMatch = path.match(/^\/(en|ru|uz)(\/|$)/i); const detectedLang = langMatch ? langMatch[1].toLowerCase() : "ru"; // Фолбэк на 'ru' console.log("🔍 Widget i18n: Detected language from URL:", detectedLang, "path:", path); return detectedLang; }; // 2. Локали, встроенные прямо в конфиг const r = { ru: { translation: { "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": "выберите смайлик", "Please complete the phone number": "Пожалуйста, заполните номер телефона до конца", "": "", // Пустой ключ для fallback }, }, en: { translation: { "quiz is inactive": "Quiz is inactive", "no questions found": "No questions found", "quiz is empty": "Quiz is empty", "quiz already completed": "You've already completed this quiz", "no quiz id": "Missing quiz ID", "quiz data is null": "No quiz parameters were provided", "invalid request data": "This quiz doesn't exist", "default message": "Something went wrong", "The request could not be sent": "Request could not be sent", "The number of points could not be sent": "Points could not be submitted", "Your result": "Your result", "Your points": "Your points", of: "of", "View answers": "View answers", "Find out more": "Learn more", "Go to website": "Go to website", "Question title": "Question title", "Question without a title": "Untitled question", "Your answer": "Your answer", "Add image": "Add image", "Accepts images": "Accepts images", "Add video": "Add video", "Accepts .mp4 and .mov format - maximum 50mb": "Accepts .mp4 and .mov format - maximum 50MB", "Add audio file": "Add audio file", "Accepts audio files": "Accepts audio files", "Add document": "Add document", "Accepts documents": "Accepts documents", Next: "Next", Prev: "Previous", From: "From", До: "To", "Enter your answer": "Enter your answer", "Incorrect file type selected": "Invalid file type selected", "File is too big. Maximum size is 50 MB": "File is too large. Maximum size is 50 MB", "Acceptable file extensions": "Allowed file extensions", "You have uploaded": "You've uploaded", "The answer was not counted": "Answer wasn't counted", "Select an answer option below": "Select an answer option below", "Select an answer option on the left": "Select an answer option on the left", "Fill out the form to receive your test results": "Fill out the form to receive your test results", Enter: "Enter", Name: "Name", "Phone number": "Phone number", "Last name": "Last name", Address: "Address", "Incorrect email entered": "Invalid email entered", "Please fill in the fields": "Please fill in the fields", "Please try again later": "Please try again later", "Regulation on the processing of personal data": "Personal Data Processing Regulation", "Privacy Policy": "Privacy Policy", familiarized: "acknowledged", and: "and", "Get results": "Get results", "Data sent successfully": "Data sent successfully", Step: "Step", "questions are not ready yet": "There are no questions for the audience yet. Please wait", "Add your image": "Add your image", "select emoji": "select emoji", "Please complete the phone number": "Please complete the phone number", "": "", // Пустой ключ для fallback }, }, uz: { translation: { "quiz is inactive": "Test faol emas", "no questions found": "Savollar topilmadi", "quiz is empty": "Test boʻsh", "quiz already completed": "Siz bu testni allaqachon topshirgansiz", "no quiz id": "Test IDsi yoʻq", "quiz data is null": "Test parametrlari yuborilmagan", "invalid request data": "Bunday test mavjud emas", "default message": "Xatolik yuz berdi", "The request could not be sent": "Soʻrov yuborib boʻlmadi", "The number of points could not be sent": "Ballar yuborib boʻlmadi", "Your result": "Sizning natijangiz", "Your points": "Sizning ballaringiz", of: "/", "View answers": "Javoblarni koʻrish", "Find out more": "Batafsil maʼlumot", "Go to website": "Veb-saytga oʻtish", "Question title": "Savol sarlavhasi", "Question without a title": "Sarlavhasiz savol", "Your answer": "Sizning javobingiz", "Add image": "Rasm qoʻshish", "Accepts images": "Rasmlarni qabul qiladi", "Add video": "Video qoʻshish", "Accepts .mp4 and .mov format - maximum 50mb": ".mp4 va .mov formatlarini qabul qiladi - maksimal 50MB", "Add audio file": "Audio fayl qoʻshish", "Accepts audio files": "Audio fayllarni qabul qiladi", "Add document": "Hujjat qoʻshish", "Accepts documents": "Hujjatlarni qabul qiladi", Next: "Keyingi", Prev: "Oldingi", From: "Dan", До: "Gacha", "Enter your answer": "Javobingizni kiriting", "Incorrect file type selected": "Notoʻgʻri fayl turi tanlandi", "File is too big. Maximum size is 50 MB": "Fayl juda katta. Maksimal hajmi 50 MB", "Acceptable file extensions": "Qabul qilinadigan fayl kengaytmalari", "You have uploaded": "Siz yuklagansiz", "The answer was not counted": "Javob hisobga olinmadi", "Select an answer option below": "Quyidagi javob variantlaridan birini tanlang", "Select an answer option on the left": "Chapdagi javob variantlaridan birini tanlang", "Fill out the form to receive your test results": "Test natijalaringizni olish uchun shaklni toʻldiring", Enter: "Kiriting", Name: "Ism", "Phone number": "Telefon raqami", "Last name": "Familiya", Address: "Manzil", "Incorrect email entered": "Notoʻgʻri elektron pochta kiritildi", "Please fill in the fields": "Iltimos, maydonlarni toʻldiring", "Please try again later": "Iltimos, keyinroq urinib koʻring", "Regulation on the processing of personal data": "Shaxsiy maʼlumotlarni qayta ishlash qoidalari", "Privacy Policy": "Maxfiylik siyosati", familiarized: "tanishdim", and: "va", "Get results": "Natijalarni olish", "Data sent successfully": "Ma'lumotlar muvaffaqiyatli yuborildi", Step: "Qadam", "questions are not ready yet": "Tomoshabinlar uchun hozircha savollar yo'q. Iltimos kuting", "Add your image": "Rasmingizni qo'shing", "select emoji": "emoji tanlang", "Please complete the phone number": "Iltimos, telefon raqamini to'liq kiriting", "": "", // Пустой ключ для fallback }, }, }; console.log("🚀 Widget i18n: Starting initialization..."); console.log("🔍 Widget i18n: i18next instance before init:", i18n); console.log("🔍 Widget i18n: i18next isInitialized before init:", i18n.isInitialized); // Проверяем, не инициализирован ли уже i18n if (i18n.isInitialized) { console.log("⚠️ Widget i18n: i18n already initialized, adding resources to existing instance"); // Добавляем ресурсы к существующему экземпляру (Object.keys(r) as Array<"ru" | "en" | "uz">).forEach((lng) => { if (i18n.store.data[lng] && i18n.store.data[lng].translation) { // Объединяем с существующими переводами i18n.store.data[lng].translation = { ...(i18n.store.data[lng].translation as Record), ...r[lng].translation, }; } else { // Добавляем новые переводы i18n.store.data[lng] = { ...(i18n.store.data[lng] as Record), translation: r[lng].translation, }; } }); console.log("✅ Widget i18n: Resources added to existing i18n instance"); console.log("🔍 Widget i18n: Testing translations after adding resources:"); console.log("🔍 Widget i18n: t('Step'):", i18n.t("Step")); console.log("🔍 Widget i18n: t('of'):", i18n.t("of")); console.log("🔍 Widget i18n: t('Prev'):", i18n.t("Prev")); console.log("🔍 Widget i18n: t('Next'):", i18n.t("Next")); } else { // 3. Конфигурация i18n без Backend i18n .use(initReactI18next) .init({ resources: r, // Используем встроенные переводы lng: getLanguageFromURL(), fallbackLng: "ru", supportedLngs: ["en", "ru", "uz"], debug: true, interpolation: { escapeValue: false, }, react: { useSuspense: false, }, detection: { order: ["path"], lookupFromPathIndex: 0, caches: [], }, parseMissingKeyHandler: (key) => { console.warn("⚠️ Widget i18n: Missing translation key:", key); return key; }, missingKeyHandler: (lngs, ns, key) => { console.error("🚨 Widget i18n: Missing i18n key:", { key, languages: lngs, namespace: ns, stack: new Error().stack, }); }, }) .then(() => { console.log("✅ Widget i18n: Initialization completed successfully"); console.log("🔍 Widget i18n: Current language:", i18n.language); console.log("🔍 Widget i18n: Available languages:", i18n.languages); console.log("🔍 Widget i18n: Available keys for ru:", Object.keys(r.ru.translation)); console.log("🔍 Widget i18n: Available keys for en:", Object.keys(r.en.translation)); console.log("🔍 Widget i18n: Available keys for uz:", Object.keys(r.uz.translation)); console.log("🔍 Widget i18n: Looking for keys: Step, of, Prev, Next"); console.log("🔍 Widget i18n: Step in ru:", r.ru.translation.Step); console.log("🔍 Widget i18n: of in ru:", r.ru.translation.of); console.log("🔍 Widget i18n: Prev in ru:", r.ru.translation.Prev); console.log("🔍 Widget i18n: Next in ru:", r.ru.translation.Next); // Проверяем, что ключи доступны через i18n console.log("🔍 Widget i18n: Testing translations through i18n:"); console.log("🔍 Widget i18n: t('Step'):", i18n.t("Step")); console.log("🔍 Widget i18n: t('of'):", i18n.t("of")); console.log("🔍 Widget i18n: t('Prev'):", i18n.t("Prev")); console.log("🔍 Widget i18n: t('Next'):", i18n.t("Next")); // Проверяем состояние i18n console.log("🔍 Widget i18n: i18n.isInitialized:", i18n.isInitialized); console.log("🔍 Widget i18n: i18n.store.data:", i18n.store.data); console.log("🔍 Widget i18n: i18n.store.options:", i18n.store.options); }) .catch((error) => { console.error("❌ Widget i18n: Initialization failed:", error); }); } // 4. Логирование событий i18n.on("languageChanged", (lng) => { console.log("🔄 Widget i18n: Language changed to:", lng); }); i18n.on("initialized", (options) => { console.log("🎯 Widget i18n: Initialized event fired with options:", options); }); i18n.on("loaded", (loaded) => { console.log("📦 Widget i18n: Loaded event fired:", loaded); }); i18n.on("failedLoading", (lng, ns, msg) => { console.error("💥 Widget i18n: Failed loading:", { lng, ns, msg }); }); i18n.on("missingKey", (lngs, namespace, key, res) => { console.warn("⚠️ Widget i18n: Missing key event:", { lngs, namespace, key, res }); }); export default i18n;