import { useEffect, useMemo, useState } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { I18nProvider } from "@lingui/react"; import type { Messages } from "@lingui/core"; import { playerQueries } from "@/features/players/queries"; import { createI18n, ensureMessages, hasCachedMessages, i18nMessagesQueryKey, primeMessages, resolveLocale, } from "@/lib/i18n"; /** * Must mount ABOVE AuthProvider: the localized server-query hooks (useMe * included) call useLingui, so this provider cannot depend on auth context. * It reads the same auth query via raw useQuery instead — passively (useMe * is the active fetcher; SSR data is ensured in __root beforeLoad). */ export const LinguiProvider = ({ children }: { children: React.ReactNode }) => { const { queryKey, queryFn } = playerQueries.auth(); const { data } = useQuery({ queryKey, queryFn: async () => { const result = await queryFn(); if (!result.success) throw new Error(result.error.userMessage); return result.data; }, staleTime: 30 * 1000, refetchOnMount: false, refetchOnWindowFocus: false, }); const queryClient = useQueryClient(); const locale = resolveLocale(data?.metadata?.locale); const [catalogVersion, setCatalogVersion] = useState(0); const i18n = useMemo( () => { if (!hasCachedMessages(locale)) { const seeded = queryClient.getQueryData( i18nMessagesQueryKey(locale) ); if (seeded) primeMessages(locale, seeded); } return createI18n(locale); }, // eslint-disable-next-line react-hooks/exhaustive-deps [locale, catalogVersion, queryClient] ); useEffect(() => { if (hasCachedMessages(locale)) return; let cancelled = false; let retryTimer: ReturnType | undefined; const load = () => { ensureMessages(locale).then( () => { if (!cancelled) setCatalogVersion((v) => v + 1); }, () => { if (!cancelled) retryTimer = setTimeout(load, 3000); } ); }; load(); return () => { cancelled = true; if (retryTimer) clearTimeout(retryTimer); }; }, [locale]); useEffect(() => { document.documentElement.lang = locale; }, [locale]); return {children}; };