diff --git a/apps/compliance-portal/src/components/TopBar/TopBarUserMenu.tsx b/apps/compliance-portal/src/components/TopBar/TopBarUserMenu.tsx index cd4fe3428..c3daae9b0 100644 --- a/apps/compliance-portal/src/components/TopBar/TopBarUserMenu.tsx +++ b/apps/compliance-portal/src/components/TopBar/TopBarUserMenu.tsx @@ -58,7 +58,6 @@ const topBarUserMenuFragment = graphql` fragment TopBarUserMenu_identity on Identity { fullName email - locale } `; @@ -136,7 +135,12 @@ export function TopBarUserMenu({ identityKey }: TopBarUserMenuProps) { }} > {URL_LOCALES.map(code => ( - + {URL_LOCALE_LABELS[code]} ))} diff --git a/apps/compliance-portal/src/lib/i18n/useChangeLocale.ts b/apps/compliance-portal/src/lib/i18n/useChangeLocale.ts index a8d275dd9..156243091 100644 --- a/apps/compliance-portal/src/lib/i18n/useChangeLocale.ts +++ b/apps/compliance-portal/src/lib/i18n/useChangeLocale.ts @@ -44,11 +44,18 @@ export function useChangeLocale() { locale: UrlLocale, options: ChangeLocaleOptions = {}, ) => { + // Persist and navigate without sequencing them: awaiting the mutation + // before navigation left a frame where Identity.locale already matched + // the new choice but the URL still had the old prefix, flashing the + // mismatch callout. updateLocale writes the store optimistically, and + // flushSync applies the URL change in the same paint. if (options.persist) { - await updateLocale(locale); + void updateLocale(locale); } if (locale !== currentLocale) { - void navigate(replaceLocaleInPathname(pathname, locale) + search); + void navigate(replaceLocaleInPathname(pathname, locale) + search, { + flushSync: true, + }); } }, [currentLocale, navigate, pathname, search, updateLocale]); diff --git a/apps/compliance-portal/src/lib/i18n/useUpdateLocale.ts b/apps/compliance-portal/src/lib/i18n/useUpdateLocale.ts index 6856bbe06..560884cd8 100644 --- a/apps/compliance-portal/src/lib/i18n/useUpdateLocale.ts +++ b/apps/compliance-portal/src/lib/i18n/useUpdateLocale.ts @@ -53,6 +53,11 @@ export function useUpdateLocale() { await commit( { variables: { input: { locale } }, + // Keep the Relay store in sync with the URL during locale switches so + // the mismatch callout never paints a one-frame desync. + optimisticUpdater: (store) => { + store.getRoot().getLinkedRecord("viewer")?.setValue(locale, "locale"); + }, }, feedback, );