логи
This commit is contained in:
parent
785e56f9b0
commit
0c9b6e5b7a
@ -22,6 +22,9 @@ import { HelmetProvider } from "react-helmet-async";
|
|||||||
import "moment/dist/locale/ru";
|
import "moment/dist/locale/ru";
|
||||||
import { useQuizStore, setQuizData, addquizid } from "@/stores/useQuizStore";
|
import { useQuizStore, setQuizData, addquizid } from "@/stores/useQuizStore";
|
||||||
import { initDataManager, statusOfQuiz } from "@/utils/hooks/useQuestionFlowControl";
|
import { initDataManager, statusOfQuiz } from "@/utils/hooks/useQuestionFlowControl";
|
||||||
|
|
||||||
|
console.log("🚀 QuizAnswerer: Component module loaded");
|
||||||
|
|
||||||
moment.locale("ru");
|
moment.locale("ru");
|
||||||
const localeText = ruRU.components.MuiLocalizationProvider.defaultProps.localeText;
|
const localeText = ruRU.components.MuiLocalizationProvider.defaultProps.localeText;
|
||||||
|
|
||||||
@ -42,6 +45,13 @@ function QuizAnswererInner({
|
|||||||
className,
|
className,
|
||||||
disableGlobalCss = false,
|
disableGlobalCss = false,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
|
console.log("🔧 QuizAnswererInner: Component function called with props:", {
|
||||||
|
quizId,
|
||||||
|
preview,
|
||||||
|
changeFaviconAndTitle,
|
||||||
|
disableGlobalCss,
|
||||||
|
});
|
||||||
|
|
||||||
const [quizViewStore] = useState(createQuizViewStore);
|
const [quizViewStore] = useState(createQuizViewStore);
|
||||||
const [rootContainerWidth, setRootContainerWidth] = useState<number>(() => window.innerWidth);
|
const [rootContainerWidth, setRootContainerWidth] = useState<number>(() => window.innerWidth);
|
||||||
const rootContainerRef = useRef<HTMLDivElement>(null);
|
const rootContainerRef = useRef<HTMLDivElement>(null);
|
||||||
@ -51,18 +61,21 @@ function QuizAnswererInner({
|
|||||||
const r = useQuizStore();
|
const r = useQuizStore();
|
||||||
const { settings, questions } = useQuizStore();
|
const { settings, questions } = useQuizStore();
|
||||||
|
|
||||||
|
console.log("🔍 QuizAnswererInner: Component state initialized");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
console.log("🔧 QuizAnswererInner: addquizid effect triggered");
|
||||||
addquizid(quizId);
|
addquizid(quizId);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log(settings);
|
console.log("🔍 QuizAnswererInner: Debug effect - settings:", settings);
|
||||||
console.log(questions);
|
console.log("🔍 QuizAnswererInner: Debug effect - questions:", questions);
|
||||||
console.log("r");
|
console.log("🔍 QuizAnswererInner: Debug effect - r:", r);
|
||||||
console.log(r);
|
|
||||||
}, [questions, settings]);
|
}, [questions, settings]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
console.log("🔧 QuizAnswererInner: Metrics effect triggered");
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
vkMetrics.quizOpened();
|
vkMetrics.quizOpened();
|
||||||
yandexMetrics.quizOpened();
|
yandexMetrics.quizOpened();
|
||||||
@ -72,7 +85,7 @@ function QuizAnswererInner({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
//Хук на случай если данные переданы нам сразу, а не "нам нужно их запросить"
|
//Хук на случай если данные переданы нам сразу, а не "нам нужно их запросить"
|
||||||
if (quizSettings !== undefined) {
|
if (quizSettings !== undefined) {
|
||||||
console.log("QuizAnswerer: calling setQuizData with quizSettings");
|
console.log("🔧 QuizAnswererInner: setQuizData effect triggered with quizSettings");
|
||||||
setQuizData(quizSettings);
|
setQuizData(quizSettings);
|
||||||
initDataManager({
|
initDataManager({
|
||||||
status: quizSettings.settings.status,
|
status: quizSettings.settings.status,
|
||||||
@ -82,6 +95,7 @@ function QuizAnswererInner({
|
|||||||
}, [quizSettings]);
|
}, [quizSettings]);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
|
console.log("🔧 QuizAnswererInner: Layout effect triggered");
|
||||||
if (rootContainerRef.current) setRootContainerWidth(rootContainerRef.current.clientWidth);
|
if (rootContainerRef.current) setRootContainerWidth(rootContainerRef.current.clientWidth);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -98,19 +112,44 @@ function QuizAnswererInner({
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
console.log("🔍 QuizAnswererInner: About to render, current state:");
|
||||||
|
console.log("🔍 QuizAnswererInner: isLoading:", isLoading);
|
||||||
|
console.log("🔍 QuizAnswererInner: error:", error);
|
||||||
|
console.log("🔍 QuizAnswererInner: settings keys count:", Object.keys(settings).length);
|
||||||
|
console.log("🔍 QuizAnswererInner: questions length:", questions.length);
|
||||||
|
|
||||||
console.log("settings");
|
console.log("settings");
|
||||||
console.log(settings);
|
console.log(settings);
|
||||||
if (isLoading && !questions.length) return <LoadingSkeleton />;
|
if (isLoading && !questions.length) {
|
||||||
|
console.log("🔍 QuizAnswererInner: Rendering LoadingSkeleton");
|
||||||
|
return <LoadingSkeleton />;
|
||||||
|
}
|
||||||
console.log("error");
|
console.log("error");
|
||||||
console.log(error);
|
console.log(error);
|
||||||
if (error) return <ApologyPage error={error} />;
|
if (error) {
|
||||||
|
console.log("🔍 QuizAnswererInner: Rendering ApologyPage due to error");
|
||||||
|
return <ApologyPage error={error} />;
|
||||||
|
}
|
||||||
|
|
||||||
if (Object.keys(settings).length == 0) return <ApologyPage error={new Error("quiz data is null")} />;
|
if (Object.keys(settings).length == 0) {
|
||||||
if (questions.length === 0) return <ApologyPage error={new Error("No questions found")} />;
|
console.log("🔍 QuizAnswererInner: Rendering ApologyPage due to empty settings");
|
||||||
|
return <ApologyPage error={new Error("quiz data is null")} />;
|
||||||
|
}
|
||||||
|
if (questions.length === 0) {
|
||||||
|
console.log("🔍 QuizAnswererInner: Rendering ApologyPage due to no questions");
|
||||||
|
return <ApologyPage error={new Error("No questions found")} />;
|
||||||
|
}
|
||||||
|
|
||||||
if (questions.length === 1 && settings.cfg.noStartPage && statusOfQuiz != "ai")
|
if (questions.length === 1 && settings.cfg.noStartPage && statusOfQuiz != "ai") {
|
||||||
|
console.log("🔍 QuizAnswererInner: Rendering ApologyPage due to quiz is empty");
|
||||||
return <ApologyPage error={new Error("quiz is empty")} />;
|
return <ApologyPage error={new Error("quiz is empty")} />;
|
||||||
if (!quizId) return <ApologyPage error={new Error("no quiz id")} />;
|
}
|
||||||
|
if (!quizId) {
|
||||||
|
console.log("🔍 QuizAnswererInner: Rendering ApologyPage due to no quiz id");
|
||||||
|
return <ApologyPage error={new Error("no quiz id")} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("🔍 QuizAnswererInner: Rendering main quiz container");
|
||||||
|
|
||||||
const quizContainer = (
|
const quizContainer = (
|
||||||
<Box
|
<Box
|
||||||
@ -152,6 +191,8 @@ function QuizAnswererInner({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
export default function QuizAnswerer(props: Props) {
|
export default function QuizAnswerer(props: Props) {
|
||||||
|
console.log("🔧 QuizAnswerer: Main component function called with props:", props);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HelmetProvider>
|
<HelmetProvider>
|
||||||
<LocalizationProvider
|
<LocalizationProvider
|
||||||
|
@ -15,7 +15,18 @@ export const Footer = ({ stepNumber, nextButton, prevButton }: FooterProps) => {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { questions, settings } = useQuizStore();
|
const { questions, settings } = useQuizStore();
|
||||||
const questionsAmount = questions.filter(({ type }) => type !== "result").length;
|
const questionsAmount = questions.filter(({ type }) => type !== "result").length;
|
||||||
const { t } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
|
|
||||||
|
// Диагностика i18n в Footer
|
||||||
|
console.log("🔍 Footer: useTranslation called");
|
||||||
|
console.log("🔍 Footer: i18n instance:", i18n);
|
||||||
|
console.log("🔍 Footer: i18n.isInitialized:", i18n.isInitialized);
|
||||||
|
console.log("🔍 Footer: i18n.language:", i18n.language);
|
||||||
|
console.log("🔍 Footer: Testing translations:");
|
||||||
|
console.log("🔍 Footer: t('Step'):", t("Step"));
|
||||||
|
console.log("🔍 Footer: t('of'):", t("of"));
|
||||||
|
console.log("🔍 Footer: t('Prev'):", t("Prev"));
|
||||||
|
console.log("🔍 Footer: t('Next'):", t("Next"));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
|
@ -21,9 +21,13 @@ import unscreen from "@/ui_kit/unscreen";
|
|||||||
import { changeNextLoading, useQuizStore } from "@/stores/useQuizStore";
|
import { changeNextLoading, useQuizStore } from "@/stores/useQuizStore";
|
||||||
import { polyfillCountryFlagEmojis } from "country-flag-emoji-polyfill";
|
import { polyfillCountryFlagEmojis } from "country-flag-emoji-polyfill";
|
||||||
|
|
||||||
|
console.log("🚀 ViewPublicationPage: Component module loaded");
|
||||||
|
|
||||||
polyfillCountryFlagEmojis();
|
polyfillCountryFlagEmojis();
|
||||||
|
|
||||||
export default function ViewPublicationPage() {
|
export default function ViewPublicationPage() {
|
||||||
|
console.log("🔧 ViewPublicationPage: Component function called");
|
||||||
|
|
||||||
const { settings, recentlyCompleted, quizId, preview, changeFaviconAndTitle } = useQuizStore();
|
const { settings, recentlyCompleted, quizId, preview, changeFaviconAndTitle } = useQuizStore();
|
||||||
const answers = useQuizViewStore((state) => state.answers);
|
const answers = useQuizViewStore((state) => state.answers);
|
||||||
const ownVariants = useQuizViewStore((state) => state.ownVariants);
|
const ownVariants = useQuizViewStore((state) => state.ownVariants);
|
||||||
@ -42,7 +46,12 @@ export default function ViewPublicationPage() {
|
|||||||
useYandexMetrics(settings?.cfg?.yandexMetricsNumber, preview);
|
useYandexMetrics(settings?.cfg?.yandexMetricsNumber, preview);
|
||||||
useVKMetrics(settings?.cfg?.vkMetricsNumber, preview);
|
useVKMetrics(settings?.cfg?.vkMetricsNumber, preview);
|
||||||
|
|
||||||
|
console.log("🔍 ViewPublicationPage: Component state initialized");
|
||||||
|
console.log("🔍 ViewPublicationPage: currentQuizStep:", currentQuizStep);
|
||||||
|
console.log("🔍 ViewPublicationPage: currentQuestion:", currentQuestion);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
console.log("🔧 ViewPublicationPage: unscreen effect triggered");
|
||||||
const root = document.getElementById("root");
|
const root = document.getElementById("root");
|
||||||
const overlay = document.getElementById("hideoverlay");
|
const overlay = document.getElementById("hideoverlay");
|
||||||
|
|
||||||
@ -70,7 +79,8 @@ export default function ViewPublicationPage() {
|
|||||||
if (settings.cfg.antifraud && recentlyCompleted) throw new Error("Quiz already completed");
|
if (settings.cfg.antifraud && recentlyCompleted) throw new Error("Quiz already completed");
|
||||||
if (currentQuizStep === "startpage" && settings.cfg.noStartPage) currentQuizStep = "question";
|
if (currentQuizStep === "startpage" && settings.cfg.noStartPage) currentQuizStep = "question";
|
||||||
|
|
||||||
if (!currentQuestion)
|
if (!currentQuestion) {
|
||||||
|
console.log("🔍 ViewPublicationPage: No current question, rendering error");
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={quizThemes[settings.cfg.theme || "StandardTheme"].theme}>
|
<ThemeProvider theme={quizThemes[settings.cfg.theme || "StandardTheme"].theme}>
|
||||||
<Typography
|
<Typography
|
||||||
@ -81,21 +91,27 @@ export default function ViewPublicationPage() {
|
|||||||
</Typography>
|
</Typography>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const currentAnswer = answers.find(({ questionId }) => questionId === currentQuestion.id);
|
const currentAnswer = answers.find(({ questionId }) => questionId === currentQuestion.id);
|
||||||
|
|
||||||
|
console.log("🔍 ViewPublicationPage: About to render quiz step:", currentQuizStep);
|
||||||
|
|
||||||
let quizStepElement: ReactElement;
|
let quizStepElement: ReactElement;
|
||||||
switch (currentQuizStep) {
|
switch (currentQuizStep) {
|
||||||
case "startpage": {
|
case "startpage": {
|
||||||
|
console.log("🔍 ViewPublicationPage: Rendering startpage");
|
||||||
quizStepElement = <StartPageViewPublication />;
|
quizStepElement = <StartPageViewPublication />;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "question": {
|
case "question": {
|
||||||
if (currentQuestion.type === "result") {
|
if (currentQuestion.type === "result") {
|
||||||
|
console.log("🔍 ViewPublicationPage: Rendering result form");
|
||||||
quizStepElement = <ResultForm resultQuestion={currentQuestion} />;
|
quizStepElement = <ResultForm resultQuestion={currentQuestion} />;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("🔍 ViewPublicationPage: Rendering question");
|
||||||
quizStepElement = (
|
quizStepElement = (
|
||||||
<Question
|
<Question
|
||||||
key={currentQuestion.id}
|
key={currentQuestion.id}
|
||||||
|
@ -10,7 +10,15 @@ interface Props {
|
|||||||
|
|
||||||
export default function NextButton({ isNextButtonEnabled, moveToNextQuestion }: Props) {
|
export default function NextButton({ isNextButtonEnabled, moveToNextQuestion }: Props) {
|
||||||
const { settings, nextLoading } = useQuizStore();
|
const { settings, nextLoading } = useQuizStore();
|
||||||
const { t } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
|
|
||||||
|
// Диагностика i18n в NextButton
|
||||||
|
console.log("🔍 NextButton: useTranslation called");
|
||||||
|
console.log("🔍 NextButton: i18n instance:", i18n);
|
||||||
|
console.log("🔍 NextButton: i18n.isInitialized:", i18n.isInitialized);
|
||||||
|
console.log("🔍 NextButton: i18n.language:", i18n.language);
|
||||||
|
console.log("🔍 NextButton: Testing translation:");
|
||||||
|
console.log("🔍 NextButton: t('Next'):", t("Next"));
|
||||||
|
|
||||||
return nextLoading ? (
|
return nextLoading ? (
|
||||||
<Skeleton
|
<Skeleton
|
||||||
|
@ -13,7 +13,16 @@ export default function PrevButton({ isPreviousButtonEnabled, moveToPrevQuestion
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { settings } = useQuizStore();
|
const { settings } = useQuizStore();
|
||||||
const isMobileMini = useRootContainerSize() < 382;
|
const isMobileMini = useRootContainerSize() < 382;
|
||||||
const { t } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
|
|
||||||
|
// Диагностика i18n в PrevButton
|
||||||
|
console.log("🔍 PrevButton: useTranslation called");
|
||||||
|
console.log("🔍 PrevButton: i18n instance:", i18n);
|
||||||
|
console.log("🔍 PrevButton: i18n.isInitialized:", i18n.isInitialized);
|
||||||
|
console.log("🔍 PrevButton: i18n.language:", i18n.language);
|
||||||
|
console.log("🔍 PrevButton: Testing translation:");
|
||||||
|
console.log("🔍 PrevButton: t('Prev'):", t("Prev"));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
disabled={!isPreviousButtonEnabled}
|
disabled={!isPreviousButtonEnabled}
|
||||||
|
@ -2,15 +2,23 @@ import { Box } from "@mui/material";
|
|||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import QuizAnswerer from "../lib/components/QuizAnswerer";
|
import QuizAnswerer from "../lib/components/QuizAnswerer";
|
||||||
|
|
||||||
|
console.log("🚀 App: Component module loaded");
|
||||||
|
|
||||||
// const defaultQuizId = "45ef7f9c-784d-4e58-badb-f6b337f08ba0"; // branching
|
// const defaultQuizId = "45ef7f9c-784d-4e58-badb-f6b337f08ba0"; // branching
|
||||||
// const defaultQuizId = "b7dafa46-a535-4beb-b289-65253d14a951"; //looooong header
|
// const defaultQuizId = "b7dafa46-a535-4beb-b289-65253d14a951"; //looooong header
|
||||||
const defaultQuizId = "3c49550d-8c77-4788-bc2d-42586a261514"; //тест визуала
|
const defaultQuizId = "3c49550d-8c77-4788-bc2d-42586a261514"; //тест визуала
|
||||||
// const defaultQuizId = "ad7f5a87-b833-4f5b-854e-453706ed655c"; // linear
|
// const defaultQuizId = "ad7f5a87-b833-4f5b-854e-453706ed655c"; // linear
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
|
console.log("🔧 App: Component function called");
|
||||||
|
|
||||||
const quizId = useParams().quizId || "";
|
const quizId = useParams().quizId || "";
|
||||||
const currentUrl = window.location.pathname.slice(1);
|
const currentUrl = window.location.pathname.slice(1);
|
||||||
|
|
||||||
|
console.log("🔍 App: quizId from params:", quizId);
|
||||||
|
console.log("🔍 App: currentUrl:", currentUrl);
|
||||||
|
console.log("🔍 App: final quizId:", quizId || currentUrl || "");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
|
@ -2,6 +2,10 @@ import i18n from "i18next";
|
|||||||
import { initReactI18next } from "react-i18next";
|
import { initReactI18next } from "react-i18next";
|
||||||
import Backend from "i18next-http-backend";
|
import Backend from "i18next-http-backend";
|
||||||
|
|
||||||
|
console.log("🚀 Main i18n: Starting main i18n initialization...");
|
||||||
|
console.log("🔍 Main i18n: i18next instance before init:", i18n);
|
||||||
|
console.log("🔍 Main i18n: i18next isInitialized before init:", i18n.isInitialized);
|
||||||
|
|
||||||
// 1. Функция для принудительного определения языка из URL
|
// 1. Функция для принудительного определения языка из URL
|
||||||
const getLanguageFromURL = (): string => {
|
const getLanguageFromURL = (): string => {
|
||||||
const path = window.location.pathname;
|
const path = window.location.pathname;
|
||||||
@ -10,11 +14,12 @@ const getLanguageFromURL = (): string => {
|
|||||||
const langMatch = path.match(/^\/(en|ru|uz)(\/|$)/i);
|
const langMatch = path.match(/^\/(en|ru|uz)(\/|$)/i);
|
||||||
|
|
||||||
if (langMatch) {
|
if (langMatch) {
|
||||||
//console.log("Язык из URL:", langMatch[1]);
|
const detectedLang = langMatch[1].toLowerCase();
|
||||||
return langMatch[1].toLowerCase();
|
console.log("🔍 Main i18n: Detected language from URL:", detectedLang, "path:", path);
|
||||||
|
return detectedLang;
|
||||||
}
|
}
|
||||||
|
|
||||||
//console.log('Язык не указан в URL, используем "ru"');
|
console.log('🔍 Main i18n: Language not specified in URL, using "ru"');
|
||||||
return "ru"; // Жёсткий фолбэк
|
return "ru"; // Жёсткий фолбэк
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -46,11 +51,11 @@ i18n
|
|||||||
caches: [], // Не использовать localStorage
|
caches: [], // Не использовать localStorage
|
||||||
},
|
},
|
||||||
parseMissingKeyHandler: (key) => {
|
parseMissingKeyHandler: (key) => {
|
||||||
console.warn("Missing translation:", key);
|
console.warn("⚠️ Main i18n: Missing translation:", key);
|
||||||
return key; // Вернёт ключ вместо ошибки
|
return key; // Вернёт ключ вместо ошибки
|
||||||
},
|
},
|
||||||
missingKeyHandler: (lngs, ns, key) => {
|
missingKeyHandler: (lngs, ns, key) => {
|
||||||
console.error("🚨 Missing i18n key:", {
|
console.error("🚨 Main i18n: Missing i18n key:", {
|
||||||
key,
|
key,
|
||||||
languages: lngs,
|
languages: lngs,
|
||||||
namespace: ns,
|
namespace: ns,
|
||||||
@ -59,34 +64,41 @@ i18n
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
console.log("i18n initialized. Current language:", i18n.language);
|
console.log("✅ Main i18n: Initialization completed successfully");
|
||||||
console.log("Loading translations from:", `/locales/${i18n.language}.json`);
|
console.log("🔍 Main i18n: Current language:", i18n.language);
|
||||||
|
console.log("🔍 Main i18n: Loading translations from:", `/locales/${i18n.language}.json`);
|
||||||
|
console.log("🔍 Main i18n: i18n.isInitialized:", i18n.isInitialized);
|
||||||
|
console.log("🔍 Main i18n: i18n.store.data:", i18n.store.data);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error("Ошибка i18n:", err);
|
console.error("❌ Main i18n: Initialization failed:", err);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 3. Логирование всех событий
|
// 3. Логирование всех событий
|
||||||
i18n.on("languageChanged", (lng) => {
|
i18n.on("languageChanged", (lng) => {
|
||||||
console.log("Язык изменён на:", lng);
|
console.log("🔄 Main i18n: Language changed to:", lng);
|
||||||
|
});
|
||||||
|
|
||||||
|
i18n.on("initialized", (options) => {
|
||||||
|
console.log("🎯 Main i18n: Initialized event fired with options:", options);
|
||||||
});
|
});
|
||||||
|
|
||||||
i18n.on("failedLoading", (lng, ns, msg) => {
|
i18n.on("failedLoading", (lng, ns, msg) => {
|
||||||
console.error(`Ошибка загрузки ${lng}.json:`, msg);
|
console.error(`💥 Main i18n: Failed loading ${lng}.json:`, msg);
|
||||||
|
|
||||||
// Если не удалось загрузить русский, пробуем английский
|
// Если не удалось загрузить русский, пробуем английский
|
||||||
if (lng === "ru") {
|
if (lng === "ru") {
|
||||||
console.log("Пробуем загрузить английский язык как fallback");
|
console.log("🔄 Main i18n: Trying to load English as fallback");
|
||||||
i18n.changeLanguage("en");
|
i18n.changeLanguage("en");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
i18n.on("loaded", (loaded) => {
|
i18n.on("loaded", (loaded) => {
|
||||||
console.log("Переводы загружены:", loaded);
|
console.log("📦 Main i18n: Translations loaded:", loaded);
|
||||||
});
|
});
|
||||||
|
|
||||||
i18n.on("missingKey", (lngs, namespace, key, res) => {
|
i18n.on("missingKey", (lngs, namespace, key, res) => {
|
||||||
console.warn("Отсутствует ключ перевода:", { lngs, namespace, key, res });
|
console.warn("⚠️ Main i18n: Missing key event:", { lngs, namespace, key, res });
|
||||||
});
|
});
|
||||||
|
|
||||||
export default i18n;
|
export default i18n;
|
||||||
|
@ -5,249 +5,322 @@ import { initReactI18next } from "react-i18next";
|
|||||||
const getLanguageFromURL = (): string => {
|
const getLanguageFromURL = (): string => {
|
||||||
const path = window.location.pathname;
|
const path = window.location.pathname;
|
||||||
const langMatch = path.match(/^\/(en|ru|uz)(\/|$)/i);
|
const langMatch = path.match(/^\/(en|ru|uz)(\/|$)/i);
|
||||||
return langMatch ? langMatch[1].toLowerCase() : "ru"; // Фолбэк на 'ru'
|
const detectedLang = langMatch ? langMatch[1].toLowerCase() : "ru"; // Фолбэк на 'ru'
|
||||||
|
console.log("🔍 Widget i18n: Detected language from URL:", detectedLang, "path:", path);
|
||||||
|
return detectedLang;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 2. Локали, встроенные прямо в конфиг
|
// 2. Локали, встроенные прямо в конфиг
|
||||||
|
|
||||||
const r = {
|
const r = {
|
||||||
ru: {
|
ru: {
|
||||||
"quiz is inactive": "Квиз не активирован",
|
translation: {
|
||||||
"no questions found": "Нет созданных вопросов",
|
"quiz is inactive": "Квиз не активирован",
|
||||||
"quiz is empty": "Квиз пуст",
|
"no questions found": "Нет созданных вопросов",
|
||||||
"quiz already completed": "Вы уже прошли этот опрос",
|
"quiz is empty": "Квиз пуст",
|
||||||
"no quiz id": "Отсутствует id квиза",
|
"quiz already completed": "Вы уже прошли этот опрос",
|
||||||
"quiz data is null": "Не были переданы параметры квиза",
|
"no quiz id": "Отсутствует id квиза",
|
||||||
"invalid request data": "Такого квиза не существует",
|
"quiz data is null": "Не были переданы параметры квиза",
|
||||||
"default message": "Что-то пошло не так",
|
"invalid request data": "Такого квиза не существует",
|
||||||
"The request could not be sent": "Заявка не может быть отправлена",
|
"default message": "Что-то пошло не так",
|
||||||
"The number of points could not be sent": "Количество баллов не может быть отправлено",
|
"The request could not be sent": "Заявка не может быть отправлена",
|
||||||
"Your result": "Ваш результат",
|
"The number of points could not be sent": "Количество баллов не может быть отправлено",
|
||||||
"Your points": "Ваши баллы",
|
"Your result": "Ваш результат",
|
||||||
of: "из",
|
"Your points": "Ваши баллы",
|
||||||
"View answers": "Посмотреть ответы",
|
of: "из",
|
||||||
"Find out more": "Узнать подробнее",
|
"View answers": "Посмотреть ответы",
|
||||||
"Go to website": "Перейти на сайт",
|
"Find out more": "Узнать подробнее",
|
||||||
"Question title": "Заголовок вопроса",
|
"Go to website": "Перейти на сайт",
|
||||||
"Question without a title": "Вопрос без названия",
|
"Question title": "Заголовок вопроса",
|
||||||
"Your answer": "Ваш ответ",
|
"Question without a title": "Вопрос без названия",
|
||||||
"Add image": "Добавить изображение",
|
"Your answer": "Ваш ответ",
|
||||||
"Accepts images": "Принимает изображения",
|
"Add image": "Добавить изображение",
|
||||||
"Add video": "Добавить видео",
|
"Accepts images": "Принимает изображения",
|
||||||
"Accepts .mp4 and .mov format - maximum 50mb": "Принимает .mp4 и .mov формат — максимум 50мб",
|
"Add video": "Добавить видео",
|
||||||
"Add audio file": "Добавить аудиофайл",
|
"Accepts .mp4 and .mov format - maximum 50mb": "Принимает .mp4 и .mov формат — максимум 50мб",
|
||||||
"Accepts audio files": "Принимает аудиофайлы",
|
"Add audio file": "Добавить аудиофайл",
|
||||||
"Add document": "Добавить документ",
|
"Accepts audio files": "Принимает аудиофайлы",
|
||||||
"Accepts documents": "Принимает документы",
|
"Add document": "Добавить документ",
|
||||||
Next: "Далее",
|
"Accepts documents": "Принимает документы",
|
||||||
Prev: "Назад",
|
Next: "Далее",
|
||||||
From: "От",
|
Prev: "Назад",
|
||||||
До: "До",
|
From: "От",
|
||||||
"Enter your answer": "Введите свой ответ",
|
До: "До",
|
||||||
"Incorrect file type selected": "Выбран некорректный тип файла",
|
"Enter your answer": "Введите свой ответ",
|
||||||
"File is too big. Maximum size is 50 MB": "Файл слишком большой. Максимальный размер 50 МБ",
|
"Incorrect file type selected": "Выбран некорректный тип файла",
|
||||||
"Acceptable file extensions": "Допустимые расширения файлов",
|
"File is too big. Maximum size is 50 MB": "Файл слишком большой. Максимальный размер 50 МБ",
|
||||||
"You have uploaded": "Вы загрузили",
|
"Acceptable file extensions": "Допустимые расширения файлов",
|
||||||
"The answer was not counted": "Ответ не был засчитан",
|
"You have uploaded": "Вы загрузили",
|
||||||
"Select an answer option below": "Выберите вариант ответа ниже",
|
"The answer was not counted": "Ответ не был засчитан",
|
||||||
"Select an answer option on the left": "Выберите вариант ответа слева",
|
"Select an answer option below": "Выберите вариант ответа ниже",
|
||||||
"Fill out the form to receive your test results": "Заполните форму, чтобы получить результаты теста",
|
"Select an answer option on the left": "Выберите вариант ответа слева",
|
||||||
Enter: "Введите",
|
"Fill out the form to receive your test results": "Заполните форму, чтобы получить результаты теста",
|
||||||
Name: "Имя",
|
Enter: "Введите",
|
||||||
"Phone number": "Номер телефона",
|
Name: "Имя",
|
||||||
"Last name": "Фамилия",
|
"Phone number": "Номер телефона",
|
||||||
Address: "Адрес",
|
"Last name": "Фамилия",
|
||||||
"Incorrect email entered": "Введена некорректная почта",
|
Address: "Адрес",
|
||||||
"Please fill in the fields": "Пожалуйста, заполните поля",
|
"Incorrect email entered": "Введена некорректная почта",
|
||||||
"Please try again later": "повторите попытку позже",
|
"Please fill in the fields": "Пожалуйста, заполните поля",
|
||||||
"Regulation on the processing of personal data": "Положением об обработке персональных данных",
|
"Please try again later": "повторите попытку позже",
|
||||||
"Privacy Policy": "Политикой конфиденциальности",
|
"Regulation on the processing of personal data": "Положением об обработке персональных данных",
|
||||||
familiarized: "ознакомлен",
|
"Privacy Policy": "Политикой конфиденциальности",
|
||||||
and: "и",
|
familiarized: "ознакомлен",
|
||||||
"Get results": "Получить результаты",
|
and: "и",
|
||||||
"Data sent successfully": "Данные успешно отправлены",
|
"Get results": "Получить результаты",
|
||||||
Step: "Шаг",
|
"Data sent successfully": "Данные успешно отправлены",
|
||||||
"questions are not ready yet": "Вопросы для аудитории пока не готовы. Подождите",
|
Step: "Шаг",
|
||||||
"Add your image": "Добавьте своё изображение",
|
"questions are not ready yet": "Вопросы для аудитории пока не готовы. Подождите",
|
||||||
"select emoji": "выберите смайлик",
|
"Add your image": "Добавьте своё изображение",
|
||||||
"Please complete the phone number": "Пожалуйста, заполните номер телефона до конца",
|
"select emoji": "выберите смайлик",
|
||||||
"": "", // Пустой ключ для fallback
|
"Please complete the phone number": "Пожалуйста, заполните номер телефона до конца",
|
||||||
|
"": "", // Пустой ключ для fallback
|
||||||
|
},
|
||||||
},
|
},
|
||||||
en: {
|
en: {
|
||||||
"quiz is inactive": "Quiz is inactive",
|
translation: {
|
||||||
"no questions found": "No questions found",
|
"quiz is inactive": "Quiz is inactive",
|
||||||
"quiz is empty": "Quiz is empty",
|
"no questions found": "No questions found",
|
||||||
"quiz already completed": "You've already completed this quiz",
|
"quiz is empty": "Quiz is empty",
|
||||||
"no quiz id": "Missing quiz ID",
|
"quiz already completed": "You've already completed this quiz",
|
||||||
"quiz data is null": "No quiz parameters were provided",
|
"no quiz id": "Missing quiz ID",
|
||||||
"invalid request data": "This quiz doesn't exist",
|
"quiz data is null": "No quiz parameters were provided",
|
||||||
"default message": "Something went wrong",
|
"invalid request data": "This quiz doesn't exist",
|
||||||
"The request could not be sent": "Request could not be sent",
|
"default message": "Something went wrong",
|
||||||
"The number of points could not be sent": "Points could not be submitted",
|
"The request could not be sent": "Request could not be sent",
|
||||||
"Your result": "Your result",
|
"The number of points could not be sent": "Points could not be submitted",
|
||||||
"Your points": "Your points",
|
"Your result": "Your result",
|
||||||
of: "of",
|
"Your points": "Your points",
|
||||||
"View answers": "View answers",
|
of: "of",
|
||||||
"Find out more": "Learn more",
|
"View answers": "View answers",
|
||||||
"Go to website": "Go to website",
|
"Find out more": "Learn more",
|
||||||
"Question title": "Question title",
|
"Go to website": "Go to website",
|
||||||
"Question without a title": "Untitled question",
|
"Question title": "Question title",
|
||||||
"Your answer": "Your answer",
|
"Question without a title": "Untitled question",
|
||||||
"Add image": "Add image",
|
"Your answer": "Your answer",
|
||||||
"Accepts images": "Accepts images",
|
"Add image": "Add image",
|
||||||
"Add video": "Add video",
|
"Accepts images": "Accepts images",
|
||||||
"Accepts .mp4 and .mov format - maximum 50mb": "Accepts .mp4 and .mov format - maximum 50MB",
|
"Add video": "Add video",
|
||||||
"Add audio file": "Add audio file",
|
"Accepts .mp4 and .mov format - maximum 50mb": "Accepts .mp4 and .mov format - maximum 50MB",
|
||||||
"Accepts audio files": "Accepts audio files",
|
"Add audio file": "Add audio file",
|
||||||
"Add document": "Add document",
|
"Accepts audio files": "Accepts audio files",
|
||||||
"Accepts documents": "Accepts documents",
|
"Add document": "Add document",
|
||||||
Next: "Next",
|
"Accepts documents": "Accepts documents",
|
||||||
Prev: "Previous",
|
Next: "Next",
|
||||||
From: "From",
|
Prev: "Previous",
|
||||||
До: "To",
|
From: "From",
|
||||||
"Enter your answer": "Enter your answer",
|
До: "To",
|
||||||
"Incorrect file type selected": "Invalid file type selected",
|
"Enter your answer": "Enter your answer",
|
||||||
"File is too big. Maximum size is 50 MB": "File is too large. Maximum size is 50 MB",
|
"Incorrect file type selected": "Invalid file type selected",
|
||||||
"Acceptable file extensions": "Allowed file extensions",
|
"File is too big. Maximum size is 50 MB": "File is too large. Maximum size is 50 MB",
|
||||||
"You have uploaded": "You've uploaded",
|
"Acceptable file extensions": "Allowed file extensions",
|
||||||
"The answer was not counted": "Answer wasn't counted",
|
"You have uploaded": "You've uploaded",
|
||||||
"Select an answer option below": "Select an answer option below",
|
"The answer was not counted": "Answer wasn't counted",
|
||||||
"Select an answer option on the left": "Select an answer option on the left",
|
"Select an answer option below": "Select an answer option below",
|
||||||
"Fill out the form to receive your test results": "Fill out the form to receive your test results",
|
"Select an answer option on the left": "Select an answer option on the left",
|
||||||
Enter: "Enter",
|
"Fill out the form to receive your test results": "Fill out the form to receive your test results",
|
||||||
Name: "Name",
|
Enter: "Enter",
|
||||||
"Phone number": "Phone number",
|
Name: "Name",
|
||||||
"Last name": "Last name",
|
"Phone number": "Phone number",
|
||||||
Address: "Address",
|
"Last name": "Last name",
|
||||||
"Incorrect email entered": "Invalid email entered",
|
Address: "Address",
|
||||||
"Please fill in the fields": "Please fill in the fields",
|
"Incorrect email entered": "Invalid email entered",
|
||||||
"Please try again later": "Please try again later",
|
"Please fill in the fields": "Please fill in the fields",
|
||||||
"Regulation on the processing of personal data": "Personal Data Processing Regulation",
|
"Please try again later": "Please try again later",
|
||||||
"Privacy Policy": "Privacy Policy",
|
"Regulation on the processing of personal data": "Personal Data Processing Regulation",
|
||||||
familiarized: "acknowledged",
|
"Privacy Policy": "Privacy Policy",
|
||||||
and: "and",
|
familiarized: "acknowledged",
|
||||||
"Get results": "Get results",
|
and: "and",
|
||||||
"Data sent successfully": "Data sent successfully",
|
"Get results": "Get results",
|
||||||
Step: "Step",
|
"Data sent successfully": "Data sent successfully",
|
||||||
"questions are not ready yet": "There are no questions for the audience yet. Please wait",
|
Step: "Step",
|
||||||
"Add your image": "Add your image",
|
"questions are not ready yet": "There are no questions for the audience yet. Please wait",
|
||||||
"select emoji": "select emoji",
|
"Add your image": "Add your image",
|
||||||
"Please complete the phone number": "Please complete the phone number",
|
"select emoji": "select emoji",
|
||||||
"": "", // Пустой ключ для fallback
|
"Please complete the phone number": "Please complete the phone number",
|
||||||
|
"": "", // Пустой ключ для fallback
|
||||||
|
},
|
||||||
},
|
},
|
||||||
uz: {
|
uz: {
|
||||||
"quiz is inactive": "Test faol emas",
|
translation: {
|
||||||
"no questions found": "Savollar topilmadi",
|
"quiz is inactive": "Test faol emas",
|
||||||
"quiz is empty": "Test boʻsh",
|
"no questions found": "Savollar topilmadi",
|
||||||
"quiz already completed": "Siz bu testni allaqachon topshirgansiz",
|
"quiz is empty": "Test boʻsh",
|
||||||
"no quiz id": "Test IDsi yoʻq",
|
"quiz already completed": "Siz bu testni allaqachon topshirgansiz",
|
||||||
"quiz data is null": "Test parametrlari yuborilmagan",
|
"no quiz id": "Test IDsi yoʻq",
|
||||||
"invalid request data": "Bunday test mavjud emas",
|
"quiz data is null": "Test parametrlari yuborilmagan",
|
||||||
"default message": "Xatolik yuz berdi",
|
"invalid request data": "Bunday test mavjud emas",
|
||||||
"The request could not be sent": "Soʻrov yuborib boʻlmadi",
|
"default message": "Xatolik yuz berdi",
|
||||||
"The number of points could not be sent": "Ballar yuborib boʻlmadi",
|
"The request could not be sent": "Soʻrov yuborib boʻlmadi",
|
||||||
"Your result": "Sizning natijangiz",
|
"The number of points could not be sent": "Ballar yuborib boʻlmadi",
|
||||||
"Your points": "Sizning ballaringiz",
|
"Your result": "Sizning natijangiz",
|
||||||
of: "/",
|
"Your points": "Sizning ballaringiz",
|
||||||
"View answers": "Javoblarni koʻrish",
|
of: "/",
|
||||||
"Find out more": "Batafsil maʼlumot",
|
"View answers": "Javoblarni koʻrish",
|
||||||
"Go to website": "Veb-saytga oʻtish",
|
"Find out more": "Batafsil maʼlumot",
|
||||||
"Question title": "Savol sarlavhasi",
|
"Go to website": "Veb-saytga oʻtish",
|
||||||
"Question without a title": "Sarlavhasiz savol",
|
"Question title": "Savol sarlavhasi",
|
||||||
"Your answer": "Sizning javobingiz",
|
"Question without a title": "Sarlavhasiz savol",
|
||||||
"Add image": "Rasm qoʻshish",
|
"Your answer": "Sizning javobingiz",
|
||||||
"Accepts images": "Rasmlarni qabul qiladi",
|
"Add image": "Rasm qoʻshish",
|
||||||
"Add video": "Video qoʻshish",
|
"Accepts images": "Rasmlarni qabul qiladi",
|
||||||
"Accepts .mp4 and .mov format - maximum 50mb": ".mp4 va .mov formatlarini qabul qiladi - maksimal 50MB",
|
"Add video": "Video qoʻshish",
|
||||||
"Add audio file": "Audio fayl qoʻshish",
|
"Accepts .mp4 and .mov format - maximum 50mb": ".mp4 va .mov formatlarini qabul qiladi - maksimal 50MB",
|
||||||
"Accepts audio files": "Audio fayllarni qabul qiladi",
|
"Add audio file": "Audio fayl qoʻshish",
|
||||||
"Add document": "Hujjat qoʻshish",
|
"Accepts audio files": "Audio fayllarni qabul qiladi",
|
||||||
"Accepts documents": "Hujjatlarni qabul qiladi",
|
"Add document": "Hujjat qoʻshish",
|
||||||
Next: "Keyingi",
|
"Accepts documents": "Hujjatlarni qabul qiladi",
|
||||||
Prev: "Oldingi",
|
Next: "Keyingi",
|
||||||
From: "Dan",
|
Prev: "Oldingi",
|
||||||
До: "Gacha",
|
From: "Dan",
|
||||||
"Enter your answer": "Javobingizni kiriting",
|
До: "Gacha",
|
||||||
"Incorrect file type selected": "Notoʻgʻri fayl turi tanlandi",
|
"Enter your answer": "Javobingizni kiriting",
|
||||||
"File is too big. Maximum size is 50 MB": "Fayl juda katta. Maksimal hajmi 50 MB",
|
"Incorrect file type selected": "Notoʻgʻri fayl turi tanlandi",
|
||||||
"Acceptable file extensions": "Qabul qilinadigan fayl kengaytmalari",
|
"File is too big. Maximum size is 50 MB": "Fayl juda katta. Maksimal hajmi 50 MB",
|
||||||
"You have uploaded": "Siz yuklagansiz",
|
"Acceptable file extensions": "Qabul qilinadigan fayl kengaytmalari",
|
||||||
"The answer was not counted": "Javob hisobga olinmadi",
|
"You have uploaded": "Siz yuklagansiz",
|
||||||
"Select an answer option below": "Quyidagi javob variantlaridan birini tanlang",
|
"The answer was not counted": "Javob hisobga olinmadi",
|
||||||
"Select an answer option on the left": "Chapdagi javob variantlaridan birini tanlang",
|
"Select an answer option below": "Quyidagi javob variantlaridan birini tanlang",
|
||||||
"Fill out the form to receive your test results": "Test natijalaringizni olish uchun shaklni toʻldiring",
|
"Select an answer option on the left": "Chapdagi javob variantlaridan birini tanlang",
|
||||||
Enter: "Kiriting",
|
"Fill out the form to receive your test results": "Test natijalaringizni olish uchun shaklni toʻldiring",
|
||||||
Name: "Ism",
|
Enter: "Kiriting",
|
||||||
"Phone number": "Telefon raqami",
|
Name: "Ism",
|
||||||
"Last name": "Familiya",
|
"Phone number": "Telefon raqami",
|
||||||
Address: "Manzil",
|
"Last name": "Familiya",
|
||||||
"Incorrect email entered": "Notoʻgʻri elektron pochta kiritildi",
|
Address: "Manzil",
|
||||||
"Please fill in the fields": "Iltimos, maydonlarni toʻldiring",
|
"Incorrect email entered": "Notoʻgʻri elektron pochta kiritildi",
|
||||||
"Please try again later": "Iltimos, keyinroq urinib koʻring",
|
"Please fill in the fields": "Iltimos, maydonlarni toʻldiring",
|
||||||
"Regulation on the processing of personal data": "Shaxsiy maʼlumotlarni qayta ishlash qoidalari",
|
"Please try again later": "Iltimos, keyinroq urinib koʻring",
|
||||||
"Privacy Policy": "Maxfiylik siyosati",
|
"Regulation on the processing of personal data": "Shaxsiy maʼlumotlarni qayta ishlash qoidalari",
|
||||||
familiarized: "tanishdim",
|
"Privacy Policy": "Maxfiylik siyosati",
|
||||||
and: "va",
|
familiarized: "tanishdim",
|
||||||
"Get results": "Natijalarni olish",
|
and: "va",
|
||||||
"Data sent successfully": "Ma'lumotlar muvaffaqiyatli yuborildi",
|
"Get results": "Natijalarni olish",
|
||||||
Step: "Qadam",
|
"Data sent successfully": "Ma'lumotlar muvaffaqiyatli yuborildi",
|
||||||
"questions are not ready yet": "Tomoshabinlar uchun hozircha savollar yo'q. Iltimos kuting",
|
Step: "Qadam",
|
||||||
"Add your image": "Rasmingizni qo'shing",
|
"questions are not ready yet": "Tomoshabinlar uchun hozircha savollar yo'q. Iltimos kuting",
|
||||||
"select emoji": "emoji tanlang",
|
"Add your image": "Rasmingizni qo'shing",
|
||||||
"Please complete the phone number": "Iltimos, telefon raqamini to'liq kiriting",
|
"select emoji": "emoji tanlang",
|
||||||
"": "", // Пустой ключ для fallback
|
"Please complete the phone number": "Iltimos, telefon raqamini to'liq kiriting",
|
||||||
|
"": "", // Пустой ключ для fallback
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// 3. Конфигурация i18n без Backend
|
console.log("🚀 Widget i18n: Starting initialization...");
|
||||||
i18n
|
console.log("🔍 Widget i18n: i18next instance before init:", i18n);
|
||||||
.use(initReactI18next)
|
console.log("🔍 Widget i18n: i18next isInitialized before init:", i18n.isInitialized);
|
||||||
.init({
|
|
||||||
resources: r, // Используем встроенные переводы
|
// Проверяем, не инициализирован ли уже i18n
|
||||||
lng: getLanguageFromURL(),
|
if (i18n.isInitialized) {
|
||||||
fallbackLng: "ru",
|
console.log("⚠️ Widget i18n: i18n already initialized, adding resources to existing instance");
|
||||||
supportedLngs: ["en", "ru", "uz"],
|
|
||||||
debug: true,
|
// Добавляем ресурсы к существующему экземпляру
|
||||||
interpolation: {
|
(Object.keys(r) as Array<"ru" | "en" | "uz">).forEach((lng) => {
|
||||||
escapeValue: false,
|
if (i18n.store.data[lng] && i18n.store.data[lng].translation) {
|
||||||
},
|
// Объединяем с существующими переводами
|
||||||
react: {
|
i18n.store.data[lng].translation = {
|
||||||
useSuspense: false,
|
...(i18n.store.data[lng].translation as Record<string, string>),
|
||||||
},
|
...r[lng].translation,
|
||||||
detection: {
|
};
|
||||||
order: ["path"],
|
} else {
|
||||||
lookupFromPathIndex: 0,
|
// Добавляем новые переводы
|
||||||
caches: [],
|
i18n.store.data[lng] = {
|
||||||
},
|
...(i18n.store.data[lng] as Record<string, any>),
|
||||||
parseMissingKeyHandler: (key) => {
|
translation: r[lng].translation,
|
||||||
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 initialized. Current language:", i18n.language);
|
|
||||||
console.log("Available languages:", i18n.languages);
|
|
||||||
console.log("Available keys for ru:", Object.keys(r.ru));
|
|
||||||
console.log("Available keys for en:", Object.keys(r.en));
|
|
||||||
console.log("Available keys for uz:", Object.keys(r.uz));
|
|
||||||
console.log("Looking for keys: Step, of, Prev, Next");
|
|
||||||
console.log("Step in ru:", r.ru.Step);
|
|
||||||
console.log("of in ru:", r.ru.of);
|
|
||||||
console.log("Prev in ru:", r.ru.Prev);
|
|
||||||
console.log("Next in ru:", r.ru.Next);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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. Логирование событий
|
// 4. Логирование событий
|
||||||
i18n.on("languageChanged", (lng) => {
|
i18n.on("languageChanged", (lng) => {
|
||||||
console.log("Language changed to:", 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;
|
export default i18n;
|
||||||
|
10
src/main.tsx
10
src/main.tsx
@ -2,8 +2,14 @@ import { createRoot } from "react-dom/client";
|
|||||||
import { RouteObject, RouterProvider, createBrowserRouter } from "react-router-dom";
|
import { RouteObject, RouterProvider, createBrowserRouter } from "react-router-dom";
|
||||||
import App from "./App";
|
import App from "./App";
|
||||||
import { StrictMode, lazy } from "react";
|
import { StrictMode, lazy } from "react";
|
||||||
|
|
||||||
|
console.log("🚀 Main: Starting main application...");
|
||||||
|
console.log("🔍 Main: About to import main i18n...");
|
||||||
|
|
||||||
import "./i18n/i18n";
|
import "./i18n/i18n";
|
||||||
|
|
||||||
|
console.log("✅ Main: Main i18n imported successfully");
|
||||||
|
|
||||||
const routes: RouteObject[] = [
|
const routes: RouteObject[] = [
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
@ -38,8 +44,12 @@ const router = createBrowserRouter(routes);
|
|||||||
|
|
||||||
const root = createRoot(document.getElementById("root")!);
|
const root = createRoot(document.getElementById("root")!);
|
||||||
|
|
||||||
|
console.log("🔧 Main: About to render application...");
|
||||||
|
|
||||||
root.render(
|
root.render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<RouterProvider router={router} />
|
<RouterProvider router={router} />
|
||||||
</StrictMode>
|
</StrictMode>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.log("✅ Main: Application rendered successfully");
|
||||||
|
@ -2,8 +2,14 @@ import QuizAnswerer from "@/components/QuizAnswerer";
|
|||||||
import { createRoot } from "react-dom/client";
|
import { createRoot } from "react-dom/client";
|
||||||
// eslint-disable-next-line react-refresh/only-export-components
|
// eslint-disable-next-line react-refresh/only-export-components
|
||||||
export * from "./widgets";
|
export * from "./widgets";
|
||||||
|
|
||||||
|
console.log("🚀 Widget: Starting widget initialization...");
|
||||||
|
console.log("🔍 Widget: About to import i18nWidget...");
|
||||||
|
|
||||||
import "./i18n/i18nWidget";
|
import "./i18n/i18nWidget";
|
||||||
|
|
||||||
|
console.log("✅ Widget: i18nWidget imported successfully");
|
||||||
|
|
||||||
// old widget
|
// old widget
|
||||||
const widget = {
|
const widget = {
|
||||||
create({
|
create({
|
||||||
@ -15,11 +21,18 @@ const widget = {
|
|||||||
quizId: string;
|
quizId: string;
|
||||||
changeFaviconAndTitle: boolean;
|
changeFaviconAndTitle: boolean;
|
||||||
}) {
|
}) {
|
||||||
const element = document.getElementById(selector);
|
console.log("🔧 Widget: create() called with:", { selector, quizId, changeFaviconAndTitle });
|
||||||
if (!element) throw new Error("Element for widget doesn't exist");
|
|
||||||
|
|
||||||
|
const element = document.getElementById(selector);
|
||||||
|
if (!element) {
|
||||||
|
console.error("❌ Widget: Element for widget doesn't exist:", selector);
|
||||||
|
throw new Error("Element for widget doesn't exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("✅ Widget: Element found, creating root...");
|
||||||
const root = createRoot(element);
|
const root = createRoot(element);
|
||||||
|
|
||||||
|
console.log("🔧 Widget: Rendering QuizAnswerer component...");
|
||||||
root.render(
|
root.render(
|
||||||
<QuizAnswerer
|
<QuizAnswerer
|
||||||
quizId={quizId}
|
quizId={quizId}
|
||||||
@ -27,7 +40,10 @@ const widget = {
|
|||||||
disableGlobalCss
|
disableGlobalCss
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
console.log("✅ Widget: QuizAnswerer component rendered successfully");
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log("✅ Widget: Widget object created and exported");
|
||||||
|
|
||||||
export default widget;
|
export default widget;
|
||||||
|
Loading…
Reference in New Issue
Block a user