From 2d617314b4ca0b87594d4f373b1d1e69512dcc30 Mon Sep 17 00:00:00 2001 From: Jorge Moya Date: Tue, 14 Jan 2025 11:35:22 -0600 Subject: [PATCH 1/3] feat(core): add locale switcher to Header --- .../header/_actions/switch-locale.ts | 34 +++++++++++++++++++ core/components/header/index.tsx | 13 ++++++- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 core/components/header/_actions/switch-locale.ts diff --git a/core/components/header/_actions/switch-locale.ts b/core/components/header/_actions/switch-locale.ts new file mode 100644 index 0000000000..739d6fa19c --- /dev/null +++ b/core/components/header/_actions/switch-locale.ts @@ -0,0 +1,34 @@ +'use server'; + +import { SubmissionResult } from '@conform-to/react'; +import { parseWithZod } from '@conform-to/zod'; +import { revalidatePath } from 'next/cache'; + +import { localeSchema } from '@/vibes/soul/primitives/navigation/schema'; +import { defaultLocale, redirect } from '~/i18n/routing'; + +export const switchLocale = async (_prevState: SubmissionResult | null, payload: FormData) => { + const submission = parseWithZod(payload, { schema: localeSchema }); + + if (submission.status !== 'success') { + return submission.reply({ formErrors: ['Invalid locale'] }); + } + + await Promise.resolve(); + + revalidatePath('/'); + + if (submission.value.id === defaultLocale) { + redirect({ + href: `/${submission.value.id}`, + locale: submission.value.id, + }); + } else { + redirect({ + href: `/`, + locale: submission.value.id, + }); + } + + return submission.reply({ resetForm: true }); +}; diff --git a/core/components/header/index.tsx b/core/components/header/index.tsx index 07f36ce4d6..dd0d065e49 100644 --- a/core/components/header/index.tsx +++ b/core/components/header/index.tsx @@ -1,5 +1,5 @@ import { cookies } from 'next/headers'; -import { getTranslations } from 'next-intl/server'; +import { getLocale, getTranslations } from 'next-intl/server'; import PLazy from 'p-lazy'; import { cache } from 'react'; @@ -11,8 +11,10 @@ import { graphql, readFragment } from '~/client/graphql'; import { revalidate } from '~/client/revalidate-target'; import { TAGS } from '~/client/tags'; import { logoTransformer } from '~/data-transformers/logo-transformer'; +import { routing } from '~/i18n/routing'; import { search } from './_actions/search'; +import { switchLocale } from './_actions/switch-locale'; import { HeaderFragment } from './fragment'; const GetCartCountQuery = graphql(` @@ -95,6 +97,12 @@ const getCartCount = async () => { export const Header = async () => { const t = await getTranslations('Components.Header'); + const locale = await getLocale(); + + const locales = routing.locales.map((enabledLocales) => ({ + id: enabledLocales, + label: enabledLocales.toLocaleUpperCase(), + })); return ( { openSearchPopupLabel: t('Search.openSearchPopup'), logoLabel: t('home'), cartCount: PLazy.from(getCartCount), + activeLocaleId: locale, + locales, + localeAction: switchLocale, }} /> ); From 80d3200634ff395b27bfd6300690820f2be53462 Mon Sep 17 00:00:00 2001 From: Jorge Moya Date: Tue, 14 Jan 2025 11:39:18 -0600 Subject: [PATCH 2/3] fix: add translation for error --- core/components/header/_actions/switch-locale.ts | 5 ++++- core/messages/en.json | 5 ++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/core/components/header/_actions/switch-locale.ts b/core/components/header/_actions/switch-locale.ts index 739d6fa19c..c58856aa84 100644 --- a/core/components/header/_actions/switch-locale.ts +++ b/core/components/header/_actions/switch-locale.ts @@ -3,15 +3,18 @@ import { SubmissionResult } from '@conform-to/react'; import { parseWithZod } from '@conform-to/zod'; import { revalidatePath } from 'next/cache'; +import { getTranslations } from 'next-intl/server'; import { localeSchema } from '@/vibes/soul/primitives/navigation/schema'; import { defaultLocale, redirect } from '~/i18n/routing'; export const switchLocale = async (_prevState: SubmissionResult | null, payload: FormData) => { + const t = await getTranslations('Components.Header.Locale'); + const submission = parseWithZod(payload, { schema: localeSchema }); if (submission.status !== 'success') { - return submission.reply({ formErrors: ['Invalid locale'] }); + return submission.reply({ formErrors: [t('invalidLocale')] }); } await Promise.resolve(); diff --git a/core/messages/en.json b/core/messages/en.json index e23cacb1fe..2f23ae03dc 100644 --- a/core/messages/en.json +++ b/core/messages/en.json @@ -507,9 +507,8 @@ "login": "Login", "logout": "Log out" }, - "LocaleSwitcher": { - "chooseCountryAndLanguage": "Choose your country and language", - "goToSite": "Go to site" + "Locale": { + "invalidLocale": "Invalid locale" }, "MiniCart": { "cart": "Cart", From 9fd43e08a2ad1d41f22612622893f793ad950f4e Mon Sep 17 00:00:00 2001 From: Jorge Moya Date: Tue, 14 Jan 2025 15:09:33 -0600 Subject: [PATCH 3/3] chore: add context comment --- core/components/header/_actions/switch-locale.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/components/header/_actions/switch-locale.ts b/core/components/header/_actions/switch-locale.ts index c58856aa84..3146478ddb 100644 --- a/core/components/header/_actions/switch-locale.ts +++ b/core/components/header/_actions/switch-locale.ts @@ -21,6 +21,9 @@ export const switchLocale = async (_prevState: SubmissionResult | null, payload: revalidatePath('/'); + // Since `redirect` doesn't prepend the local to the redirect url + // when navigating the a default locale link, we need to prepend + // it ourselves to ensure the redirect happens. if (submission.value.id === defaultLocale) { redirect({ href: `/${submission.value.id}`,