diff --git a/packages/schema/src/operations/Frame.gql b/packages/schema/src/operations/Frame.gql index a6fd41b2d..71e0dca6f 100644 --- a/packages/schema/src/operations/Frame.gql +++ b/packages/schema/src/operations/Frame.gql @@ -1,4 +1,12 @@ query Frame { + websiteSettings { + homePage { + translations { + locale + path + } + } + } mainNavigation: mainNavigations { ...Navigation } diff --git a/packages/ui/src/components/Molecules/LanguageSwitcher.stories.tsx b/packages/ui/src/components/Molecules/LanguageSwitcher.stories.tsx index b8f3298a2..2ca738dc9 100644 --- a/packages/ui/src/components/Molecules/LanguageSwitcher.stories.tsx +++ b/packages/ui/src/components/Molecules/LanguageSwitcher.stories.tsx @@ -1,15 +1,29 @@ -import { Url } from '@custom/schema'; +import { FrameQuery, registerExecutor, Url } from '@custom/schema'; import { Decorator, Meta, StoryObj } from '@storybook/react'; import React from 'react'; import { Translations, TranslationsProvider } from '../../utils/translations'; +import { Default } from '../Routes/Frame.stories'; import { LanguageSwitcher } from './LanguageSwitcher'; -const TranslationsDecorator = ((Story, ctx) => ( - - - -)) as Decorator; +const TranslationsDecorator = ((Story, ctx) => { + registerExecutor(FrameQuery, { + ...Default.args, + websiteSettings: { + homePage: { + translations: [ + { locale: 'en', path: '/en/home' as Url }, + { locale: 'de', path: '/de/home' as Url }, + ], + }, + }, + }); + return ( + + + + ); +}) as Decorator; export default { component: LanguageSwitcher, @@ -35,3 +49,13 @@ export const Full = { en: '/en/english-version' as Url, }, } satisfies Story; + +export const Homepage = { + args: { + de: '/de/home' as Url, + en: '/en/home' as Url, + }, + parameters: { + location: new URL('local:/de'), + }, +} satisfies Story; diff --git a/packages/ui/src/components/Routes/Page.stories.tsx b/packages/ui/src/components/Routes/Page.stories.tsx index 2d47321b0..5db6f1293 100644 --- a/packages/ui/src/components/Routes/Page.stories.tsx +++ b/packages/ui/src/components/Routes/Page.stories.tsx @@ -1,4 +1,10 @@ -import { Locale, registerExecutor, Url, ViewPageQuery } from '@custom/schema'; +import { + FrameQuery, + Locale, + registerExecutor, + Url, + ViewPageQuery, +} from '@custom/schema'; import Landscape from '@stories/landscape.jpg?as=metadata'; import { Meta, StoryObj } from '@storybook/react'; import React from 'react'; @@ -6,6 +12,7 @@ import React from 'react'; import { image } from '../../helpers/image'; import { Mixed, Paragraph } from '../Organisms/PageContent/BlockMarkup.stories'; import { WithCaption } from '../Organisms/PageContent/BlockMedia.stories'; +import { Default as FrameStory } from './Frame.stories'; import { Page } from './Page'; export default { @@ -15,6 +22,7 @@ export default { export const Default = { render: (args) => { registerExecutor(ViewPageQuery, () => args); + registerExecutor(FrameQuery, FrameStory.args); return ; }, args: { diff --git a/packages/ui/src/utils/translations.tsx b/packages/ui/src/utils/translations.tsx index 2783bb8d4..32e861be2 100644 --- a/packages/ui/src/utils/translations.tsx +++ b/packages/ui/src/utils/translations.tsx @@ -1,4 +1,4 @@ -import { Locale, Url } from '@custom/schema'; +import { FrameQuery, Locale, Url } from '@custom/schema'; import React, { createContext, PropsWithChildren, @@ -7,6 +7,9 @@ import React, { useState, } from 'react'; +import { isTruthy } from './isTruthy'; +import { useOperation } from './operation'; + /** * A list of translations for the given page. * A translations consists of the locale and the corresponding path. @@ -36,15 +39,30 @@ export function TranslationsProvider({ } function deepCompare(a: any, b: any) { - return JSON.stringify(a) === JSON.stringify(b); + return ( + a && + b && + Object.keys(a).length === Object.keys(b).length && + Object.keys(a).every((key) => a[key] === b[key]) + ); } export function useTranslations(newTranslations?: Translations) { + const homeTranslations = Object.fromEntries( + useOperation(FrameQuery) + .data?.websiteSettings?.homePage?.translations?.filter(isTruthy) + .map(({ locale, path }) => [locale, path]) || [], + ); const { setTranslations, translations } = useContext(TranslationsContext); useEffect(() => { if (newTranslations && !deepCompare(translations, newTranslations)) { setTranslations(newTranslations); } }, [setTranslations, newTranslations, translations]); - return translations; + + const homePaths = Object.fromEntries( + Object.values(Locale).map((locale) => [locale, `/${locale}` as Url]), + ); + + return deepCompare(homeTranslations, translations) ? homePaths : translations; }