diff --git a/apps/web/components/I18nLanguageHandler.tsx b/apps/web/components/I18nLanguageHandler.tsx index 81a7fb8859..5c7fe018ee 100644 --- a/apps/web/components/I18nLanguageHandler.tsx +++ b/apps/web/components/I18nLanguageHandler.tsx @@ -1,15 +1,14 @@ +import parser from "accept-language-parser"; import { useSession } from "next-auth/react"; import { useTranslation } from "next-i18next"; import { useEffect } from "react"; +import { CALCOM_VERSION } from "@calcom/lib/constants"; import { trpc } from "@calcom/trpc/react"; -// eslint-disable-next-line turbo/no-undeclared-env-vars -const vercelCommitHash = process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA || "NA"; - -export function useViewerI18n(locale: string) { +function useViewerI18n(locale: string) { return trpc.viewer.public.i18n.useQuery( - { locale, CalComVersion: vercelCommitHash }, + { locale, CalComVersion: CALCOM_VERSION }, { /** * i18n should never be clubbed with other queries, so that it's caching can be managed independently. @@ -21,13 +20,32 @@ export function useViewerI18n(locale: string) { ); } +function useClientLocale(locales: string[]) { + const session = useSession(); + // If the user is logged in, use their locale + if (session.data?.user.locale) return session.data.user.locale; + // If the user is not logged in, use the browser locale + if (typeof window !== "undefined") { + // This is the only way I found to ensure the prefetched locale is used on first render + // FIXME: Find a better way to pick the best matching locale from the browser + return parser.pick(locales, window.navigator.language, { loose: true }) || window.navigator.language; + } + // If the browser is not available, use English + return "en"; +} + +export function useClientViewerI18n(locales: string[]) { + const clientLocale = useClientLocale(locales); + return useViewerI18n(clientLocale); +} + /** * Auto-switches locale client-side to the logged in user's preference */ -const I18nLanguageHandler = () => { - const session = useSession(); +const I18nLanguageHandler = (props: { locales: string[] }) => { + const { locales } = props; const { i18n } = useTranslation("common"); - const locale = useViewerI18n(session.data?.user.locale || "en").data?.locale || i18n.language; + const locale = useClientViewerI18n(locales).data?.locale || i18n.language; useEffect(() => { // bail early when i18n = {} diff --git a/apps/web/components/PageWrapper.tsx b/apps/web/components/PageWrapper.tsx index c076ebd2da..2ac8afca7c 100644 --- a/apps/web/components/PageWrapper.tsx +++ b/apps/web/components/PageWrapper.tsx @@ -6,7 +6,7 @@ import Script from "next/script"; import "@calcom/embed-core/src/embed-iframe"; import LicenseRequired from "@calcom/features/ee/common/components/LicenseRequired"; -import { WEBAPP_URL, IS_CALCOM } from "@calcom/lib/constants"; +import { IS_CALCOM, WEBAPP_URL } from "@calcom/lib/constants"; import { buildCanonical } from "@calcom/lib/next-seo.config"; import type { AppProps } from "@lib/app-providers"; @@ -72,7 +72,7 @@ function PageWrapper(props: AppProps) { } {...seoConfig.defaultNextSeo} /> - +