diff --git a/apps/dataset-browser/package.json b/apps/dataset-browser/package.json index 1aad4ebee..79d2de05a 100644 --- a/apps/dataset-browser/package.json +++ b/apps/dataset-browser/package.json @@ -32,7 +32,7 @@ "classnames": "2.3.2", "fetch-sparql-endpoint": "4.1.0", "next": "14.0.3", - "next-intl": "3.0.0-beta.19", + "next-intl": "3.1.4", "rdf-object": "1.14.0", "react": "18.2.0", "react-dom": "18.2.0", diff --git a/apps/dataset-browser/src/app/[locale]/dataset-card.tsx b/apps/dataset-browser/src/app/[locale]/dataset-card.tsx index a137dc080..5da1d14da 100644 --- a/apps/dataset-browser/src/app/[locale]/dataset-card.tsx +++ b/apps/dataset-browser/src/app/[locale]/dataset-card.tsx @@ -1,4 +1,4 @@ -import Link from 'next-intl/link'; +import {Link} from '@/navigation'; import {useTranslations} from 'next-intl'; import {Dataset} from '@/lib/datasets'; import {Badge} from '@colonial-collections/ui'; diff --git a/apps/dataset-browser/src/app/[locale]/datasets/[id]/back-button.tsx b/apps/dataset-browser/src/app/[locale]/datasets/[id]/back-button.tsx new file mode 100644 index 000000000..54d3f2005 --- /dev/null +++ b/apps/dataset-browser/src/app/[locale]/datasets/[id]/back-button.tsx @@ -0,0 +1,19 @@ +'use client'; + +import {Link} from '@/navigation'; +import {useListHref} from '@colonial-collections/list-store'; +import {ReactNode} from 'react'; + +export default function BackButton({children}: {children: ReactNode}) { + const href = useListHref(); + + return ( + + {children} + + ); +} diff --git a/apps/dataset-browser/src/app/[locale]/datasets/[id]/page.tsx b/apps/dataset-browser/src/app/[locale]/datasets/[id]/page.tsx index f0eb5fcb0..39cf98986 100644 --- a/apps/dataset-browser/src/app/[locale]/datasets/[id]/page.tsx +++ b/apps/dataset-browser/src/app/[locale]/datasets/[id]/page.tsx @@ -1,5 +1,4 @@ -import {getTranslator, getFormatter} from 'next-intl/server'; -import {useLocale} from 'next-intl'; +import {getTranslations, getFormatter} from 'next-intl/server'; import { PageHeader, PageTitle, @@ -11,14 +10,14 @@ import { LocalizedMarkdown, } from '@colonial-collections/ui'; import { - ChevronLeftIcon, InformationCircleIcon, + ChevronLeftIcon, } from '@heroicons/react/24/solid'; import datasetFetcher from '@/lib/dataset-fetcher-instance'; import {Fragment} from 'react'; import BooleanMeasurement from '@/components/boolean-measurement'; import metricIds from '@/lib/transparency-metrics'; -import {ToFilteredListButton} from '@colonial-collections/ui/list'; +import BackButton from './back-button'; interface Props { params: {id: string}; @@ -30,10 +29,9 @@ export const revalidate = 0; export default async function Details({params}: Props) { const id = decodeURIComponent(params.id); const dataset = await datasetFetcher.getById({id}); - const locale = useLocale(); - const t = await getTranslator(locale, 'Details'); - const tMetrics = await getTranslator(locale, 'TransparencyMetrics'); - const format = await getFormatter(locale); + const t = await getTranslations('Details'); + const tMetrics = await getTranslations('TransparencyMetrics'); + const format = await getFormatter(); if (!dataset) { return
{t('noDataset')}
; @@ -96,10 +94,10 @@ export default async function Details({params}: Props) {
{communities.map(community => ( - + ))}
diff --git a/apps/researcher/src/app/[locale]/layout.tsx b/apps/researcher/src/app/[locale]/layout.tsx index 78c75efa8..2a81ba286 100644 --- a/apps/researcher/src/app/[locale]/layout.tsx +++ b/apps/researcher/src/app/[locale]/layout.tsx @@ -3,9 +3,9 @@ import {ReactNode} from 'react'; import {notFound} from 'next/navigation'; import Navigation from './navigation'; import {NextIntlClientProvider} from 'next-intl'; -import {getTranslator} from 'next-intl/server'; -import {locales} from '@/middleware'; -import {WipMessage} from '@colonial-collections/ui'; +import {getTranslations} from 'next-intl/server'; +import {Link} from '@/navigation'; +import {WipMessage, IntlProvider} from '@colonial-collections/ui'; import {ClerkProvider} from '@clerk/nextjs'; interface Props { @@ -21,7 +21,7 @@ export default async function RootLayout({children, params: {locale}}: Props) { notFound(); } - const t = await getTranslator(locale, 'ScreenReaderMenu'); + const t = await getTranslations('ScreenReaderMenu'); const clerkLocale = (await import(`@/messages/${locale}/clerk`)).default; return ( @@ -29,26 +29,28 @@ export default async function RootLayout({children, params: {locale}}: Props) { - -
- -
-
-
- -
- {children} -
+ + + +
+
+ +
+ {children} +
+
diff --git a/apps/researcher/src/app/[locale]/navigation.tsx b/apps/researcher/src/app/[locale]/navigation.tsx index 99bd3b8e2..6584e7779 100644 --- a/apps/researcher/src/app/[locale]/navigation.tsx +++ b/apps/researcher/src/app/[locale]/navigation.tsx @@ -9,17 +9,13 @@ import { CheckIcon, } from '@heroicons/react/24/outline'; import classNames from 'classnames'; -import {usePathname} from 'next-intl/client'; -import Link from 'next-intl/link'; +import {Link, usePathname} from '@/navigation'; import {useLocale, useTranslations} from 'next-intl'; import {Fragment} from 'react'; import {UserButton, SignInButton, SignedIn, SignedOut} from '@clerk/nextjs'; +import {locales} from '@/navigation'; -interface Props { - locales: string[]; -} - -export default function Navigation({locales}: Props) { +export default function Navigation() { const pathname = usePathname(); const locale = useLocale(); diff --git a/apps/researcher/src/app/[locale]/persons/[id]/page.tsx b/apps/researcher/src/app/[locale]/persons/[id]/page.tsx index d99775910..6b9a127c1 100644 --- a/apps/researcher/src/app/[locale]/persons/[id]/page.tsx +++ b/apps/researcher/src/app/[locale]/persons/[id]/page.tsx @@ -1,11 +1,11 @@ -import {DateTimeFormatOptions, useTranslations, useLocale} from 'next-intl'; -import {getTranslator} from 'next-intl/server'; +import {DateTimeFormatOptions, useTranslations} from 'next-intl'; +import {getTranslations} from 'next-intl/server'; import {PageHeader, PageTitle} from '@colonial-collections/ui'; import personFetcher from '@/lib/person-fetcher-instance'; import {getFormatter} from 'next-intl/server'; import {PersonIcon} from '@/components/icons'; import {H2, H3} from '@/components/titles'; -import {ToFilteredListButton} from '@colonial-collections/ui/list'; +import ToFilteredListButton from '@/components/to-filtered-list-button'; import {decodeRouteSegment} from '@/lib/clerk-route-segment-transformer'; // Revalidate the page @@ -44,14 +44,13 @@ interface Props { export default async function Details({params}: Props) { const id = decodeRouteSegment(params.id); const person = await personFetcher.getById({id}); - const locale = useLocale(); - const t = await getTranslator(locale, 'PersonDetails'); + const t = await getTranslations('PersonDetails'); if (!person) { return
{t('noEntity')}
; } - const format = await getFormatter(locale); + const format = await getFormatter(); const columnClassName = 'px-10 first:pl-0 last:pr-0 space-y-6 flex-1'; const dateFormat: DateTimeFormatOptions = { diff --git a/apps/researcher/src/app/[locale]/persons/page.tsx b/apps/researcher/src/app/[locale]/persons/page.tsx index db0f8b8d0..f14573a78 100644 --- a/apps/researcher/src/app/[locale]/persons/page.tsx +++ b/apps/researcher/src/app/[locale]/persons/page.tsx @@ -1,13 +1,12 @@ import personFetcher from '@/lib/person-fetcher-instance'; -import {useLocale, useTranslations} from 'next-intl'; -import {getTranslator} from 'next-intl/server'; +import {useTranslations} from 'next-intl'; +import {getTranslations} from 'next-intl/server'; import PersonList from './person-list'; import {sortMapping} from './sort-mapping'; import { fromSearchParamsToSearchOptions, getClientSortBy, Type as SearchParamType, - ListStoreUpdater, } from '@colonial-collections/list-store'; import { SearchResult, @@ -33,6 +32,7 @@ import { import {AdjustmentsHorizontalIcon} from '@heroicons/react/20/solid'; import Tabs from '../tabs'; import {ElementType} from 'react'; +import {ListStoreUpdater} from '@/components/list-store-updater'; // Revalidate the page every n seconds export const revalidate = 60; @@ -129,8 +129,7 @@ export default async function Home({searchParams = {}}: Props) { console.error(err); } - const locale = useLocale(); - const t = await getTranslator(locale, 'Constituents'); + const t = await getTranslations('Constituents'); return ( <> diff --git a/apps/researcher/src/app/[locale]/persons/person-card.tsx b/apps/researcher/src/app/[locale]/persons/person-card.tsx index 03e49fce3..0ddfdbf19 100644 --- a/apps/researcher/src/app/[locale]/persons/person-card.tsx +++ b/apps/researcher/src/app/[locale]/persons/person-card.tsx @@ -1,5 +1,5 @@ import {useFormatter, useTranslations} from 'next-intl'; -import Link from 'next-intl/link'; +import {Link} from '@/navigation'; import {Person} from '@/lib/api/persons'; import {PersonIcon} from '@/components/icons'; import {encodeRouteSegment} from '@/lib/clerk-route-segment-transformer'; diff --git a/apps/researcher/src/app/[locale]/tabs.tsx b/apps/researcher/src/app/[locale]/tabs.tsx index ea6c1dc2b..e5db9603e 100644 --- a/apps/researcher/src/app/[locale]/tabs.tsx +++ b/apps/researcher/src/app/[locale]/tabs.tsx @@ -1,9 +1,9 @@ import classNames from 'classnames'; import {ObjectIcon, PersonIcon} from '@/components/icons'; import {useTranslations} from 'next-intl'; -import Link from 'next-intl/link'; +import {Link} from '@/navigation'; import {headers} from 'next/headers'; -import {locales} from '@/middleware'; +import {locales} from '@/navigation'; export default function Tabs() { const t = useTranslations('Tabs'); diff --git a/apps/researcher/src/components/list-store-updater.tsx b/apps/researcher/src/components/list-store-updater.tsx new file mode 100644 index 000000000..1c506d263 --- /dev/null +++ b/apps/researcher/src/components/list-store-updater.tsx @@ -0,0 +1,26 @@ +'use client'; + +import {useRouter} from '@/navigation'; +import { + useSearchParamsUpdate, + useUpdateListStore, +} from '@colonial-collections/list-store'; + +interface Props { + totalCount: number; + offset: number; + limit: number; + query: string; + sortBy?: string; + selectedFilters?: { + [filterKey: string]: (string | number)[] | number | string | undefined; + }; +} + +export function ListStoreUpdater(updateProps: Props) { + const router = useRouter(); + useUpdateListStore(updateProps); + useSearchParamsUpdate(router.replace); + + return null; +} diff --git a/apps/researcher/src/components/to-filtered-list-button.tsx b/apps/researcher/src/components/to-filtered-list-button.tsx new file mode 100644 index 000000000..260554c4f --- /dev/null +++ b/apps/researcher/src/components/to-filtered-list-button.tsx @@ -0,0 +1,24 @@ +'use client'; + +import {Link} from '@/navigation'; +import {useListHref} from '@colonial-collections/list-store'; +import {ReactNode} from 'react'; + +interface Props { + children: ReactNode; + className?: string; +} + +export default function ToFilteredListButton({className, children}: Props) { + const href = useListHref(); + + return ( + + {children} + + ); +} diff --git a/apps/researcher/src/messages/en/messages.json b/apps/researcher/src/messages/en/messages.json index e118825ba..74ea0a993 100644 --- a/apps/researcher/src/messages/en/messages.json +++ b/apps/researcher/src/messages/en/messages.json @@ -104,11 +104,6 @@ "dataset": "In Dataset", "relatedObjects": "Related objects" }, - "Paginator": { - "results": "Showing {start} to {end} of {totalCount} results", - "previous": "Previous", - "next": "Next" - }, "Filters": { "typesFilter": "Types", "subjectsFilter": "Subjects", @@ -120,35 +115,7 @@ "materialsFilter": "Materials", "creatorsFilter": "Makers", "locationsFilter": "Locations of creation", - "dateCreatedFilter": "Date made", - "search": "Search for text", - "filters": "Filters", - "fromYear": "From year", - "tillYear": "Till year", - "expandFilter": "Expand", - "clearAllFilters": "Clear all", - "filterSearchPlaceholder": "Filter on {filterName}", - "accessibilityTypeToFilter": "Type to filter on text.", - "accessibilitySelectToFilter": "Select a checkbox to filter", - "accessibilityClickToSearch": "Click to search", - "filterPlaceholder": "Filter {filterName}", - "orderAlphabetically": "Order alphabetically", - "orderByCount": "Order by count", - "selectedFilters": "Selected filters", - "aboutFacetsHeader": "About these facets", - "aboutFacetsText": "The data of these facet items are collected from multiple datasets. We are in the process of improving the quality of these facets items." - }, - "Sort": { - "relevanceDesc": "Relevance", - "nameAsc": "Name - Ascending", - "nameDesc": "Name - Descending", - "createdAtDesc": "Date created", - "membershipCountDesc": "Number of members", - "accessibilitySelectToChangeOrder": "Select to change the ordering of the result" - }, - "WorkInProgress": { - "message": "This website is a work in progress", - "roadmapLink": "Read about the current status and roadmap of this project." + "dateCreatedFilter": "Date made" }, "Gallery": { "resetZoomButton": "Reset" @@ -211,9 +178,6 @@ "serverError": "Something went wrong while creating the list. Please try again later.", "listSuccessfullyAdded": "List has been added to you community" }, - "Modal": { - "close": "Close" - }, "ObjectList": { "backButton": "Back to community", "noEntity": "List could not be found", @@ -237,5 +201,9 @@ "communityIdTooSmall": "Community is required", "citationTooSmall": "Resource is required", "noCommunities": "You are not yet a member of a community that has permission to add a story. You can create a community or join an existing community." + }, + "WorkInProgress": { + "message": "This website is a work in progress", + "roadmapLink": "Read about the current status and roadmap of this project." } } \ No newline at end of file diff --git a/apps/researcher/src/messages/nl/messages.json b/apps/researcher/src/messages/nl/messages.json index e45cf52fa..d8574cbc7 100644 --- a/apps/researcher/src/messages/nl/messages.json +++ b/apps/researcher/src/messages/nl/messages.json @@ -104,12 +104,7 @@ "dataset": "In dataset", "relatedObjects": "Verwante objecten" }, - "Paginator": { - "results": "Resultaat {start} tot {end} van de {totalCount}", - "previous": "Vorige", - "next": "Volgende" - }, - "Filters": { + "Filters": { "typesFilter": "Types", "subjectsFilter": "Onderwerpen", "birthYearsFilter": "Geboortejaren", @@ -120,35 +115,7 @@ "locationsFilter": "Locaties van creatie", "materialsFilter": "Materialen", "creatorsFilter": "Makers", - "dateCreatedFilter": "Datum gemaakt", - "search": "Zoeken", - "filters": "Filters", - "fromYear": "Van jaar", - "tillYear": "Tot en met jaar", - "expandFilter": "Uitklappen", - "clearAllFilters": "Alles verwijderen", - "filterSearchPlaceholder": "Filteren op {filterName}", - "accessibilityTypeToFilter": "Typ om op tekst te filteren", - "accessibilitySelectToFilter": "Selecteer een selectievakje om te filteren", - "accessibilityClickToSearch": "Klik om te zoeken", - "filterPlaceholder": "Filter {filterName}", - "orderAlphabetically": "Sorteer alfabetisch", - "orderByCount": "Sorteer op aantal", - "selectedFilters": "Geselecteerde filters", - "aboutFacetsHeader": "Over de facetten", - "aboutFacetsText": "De gegevens van deze facetten worden verzameld uit meerdere datasets. We zijn bezig de kwaliteit van deze facetten te verbeteren." - }, - "Sort": { - "relevanceDesc": "Relevantie", - "nameAsc": "Naam - Oplopend", - "nameDesc": "Naam - Aflopend", - "createdAtDesc": "Datum gecreeƫrd", - "membershipCountDesc": "Aantal leden", - "accessibilitySelectToChangeOrder": "Selecteer om de volgorde van het resultaat te wijzigen" - }, - "WorkInProgress": { - "message": "Aan deze website wordt gewerkt", - "roadmapLink": "Lees over de huidige status en roadmap van dit project." + "dateCreatedFilter": "Datum gemaakt" }, "Gallery": { "resetZoomButton": "Reset" @@ -211,9 +178,6 @@ "serverError": "Er is iets misgegaan bij het maken van de lijst. Probeer het later opnieuw.", "listSuccessfullyAdded": "Lijst is aan je community toegevoegd" }, - "Modal": { - "close": "Sluiten" - }, "ObjectList": { "backButton": "Terug naar community", "noEntity": "Lijst kon niet gevonden worden", @@ -237,5 +201,9 @@ "communityIdTooSmall": "Community is vereist", "citationTooSmall": "Bron is vereist", "noCommunities": "U bent nog geen lid van een community die gemachtigd is een verhaal toe te voegen. U kunt een community maken of lid worden van een bestaande community." + }, + "WorkInProgress": { + "message": "Aan deze website wordt gewerkt", + "roadmapLink": "Lees over de huidige status en roadmap van dit project." } } \ No newline at end of file diff --git a/apps/researcher/src/middleware.ts b/apps/researcher/src/middleware.ts index ca978cada..486060234 100644 --- a/apps/researcher/src/middleware.ts +++ b/apps/researcher/src/middleware.ts @@ -1,11 +1,7 @@ import createIntlMiddleware from 'next-intl/middleware'; import {authMiddleware} from '@clerk/nextjs'; - -// Set the available locales here. These values should match a .json file in /messages. -// The const `locales` cannot be set dynamically based on files in /messages, -// because native Node.js APIs are not supported in Next.js middleware. -// So you can't read the filesystem. -export const locales = ['en', 'nl']; +import {locales} from './navigation'; +import {NextRequest} from 'next/server'; export const config = { // Skip all internal paths diff --git a/apps/researcher/src/navigation.ts b/apps/researcher/src/navigation.ts new file mode 100644 index 000000000..9b4203ab7 --- /dev/null +++ b/apps/researcher/src/navigation.ts @@ -0,0 +1,6 @@ +import {createSharedPathnamesNavigation} from 'next-intl/navigation'; + +export const locales = ['en', 'nl'] as const; + +export const {Link, redirect, usePathname, useRouter} = + createSharedPathnamesNavigation({locales}); diff --git a/package-lock.json b/package-lock.json index 6d399b07c..5b5998bb6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,7 +35,7 @@ "classnames": "2.3.2", "fetch-sparql-endpoint": "4.1.0", "next": "14.0.3", - "next-intl": "3.0.0-beta.19", + "next-intl": "3.1.4", "rdf-object": "1.14.0", "react": "18.2.0", "react-dom": "18.2.0", @@ -286,7 +286,7 @@ "classnames": "2.3.2", "fetch-sparql-endpoint": "4.1.0", "next": "14.0.3", - "next-intl": "3.0.0-beta.19", + "next-intl": "3.1.4", "openseadragon": "4.1.0", "rdf-object": "1.14.0", "react": "18.2.0", @@ -2228,18 +2228,18 @@ } }, "node_modules/@formatjs/ecma402-abstract": { - "version": "1.17.2", - "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.17.2.tgz", - "integrity": "sha512-k2mTh0m+IV1HRdU0xXM617tSQTi53tVR2muvYOsBeYcUgEAyxV1FOC7Qj279th3fBVQ+Dj6muvNJZcHSPNdbKg==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.18.0.tgz", + "integrity": "sha512-PEVLoa3zBevWSCZzPIM/lvPCi8P5l4G+NXQMc/CjEiaCWgyHieUoo0nM7Bs0n/NbuQ6JpXEolivQ9pKSBHaDlA==", "dependencies": { - "@formatjs/intl-localematcher": "0.4.2", + "@formatjs/intl-localematcher": "0.5.2", "tslib": "^2.4.0" } }, "node_modules/@formatjs/ecma402-abstract/node_modules/@formatjs/intl-localematcher": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.4.2.tgz", - "integrity": "sha512-BGdtJFmaNJy5An/Zan4OId/yR9Ih1OojFjcduX/xOvq798OgWSyDtd6Qd5jqJXwJs1ipe4Fxu9+cshic5Ox2tA==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.2.tgz", + "integrity": "sha512-txaaE2fiBMagLrR4jYhxzFO6wEdEG4TPMqrzBAcbr4HFUYzH/YC+lg6OIzKCHm8WgDdyQevxbAAV1OgcXctuGw==", "dependencies": { "tslib": "^2.4.0" } @@ -10839,17 +10839,16 @@ } }, "node_modules/next-intl": { - "version": "3.0.0-beta.19", - "resolved": "https://registry.npmjs.org/next-intl/-/next-intl-3.0.0-beta.19.tgz", - "integrity": "sha512-F9ZZ342rDUJE3hOD2ZkKtkbeJNNUQtorN0Wnr2gThgLeeyKchbwm5KgijK4gOU66Yw91V1lRuGEcV6BMJdSaxg==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/next-intl/-/next-intl-3.1.4.tgz", + "integrity": "sha512-/mewUryIPdoZT7j+8ipN2rfWuuNGdl+xiwxWxYkYko0kGY/a2IlcgqaMBKwue5V5M17Vk9bwiydv/2wySJXG8w==", "dependencies": { "@formatjs/intl-localematcher": "^0.2.32", "negotiator": "^0.6.3", - "server-only": "0.0.1", - "use-intl": "3.0.0-beta.3" + "use-intl": "^3.1.4" }, "peerDependencies": { - "next": "^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0", + "next": "^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, @@ -12608,11 +12607,6 @@ "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" }, - "node_modules/server-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz", - "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==" - }, "node_modules/set-function-name": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", @@ -14019,9 +14013,9 @@ } }, "node_modules/use-intl": { - "version": "3.0.0-beta.3", - "resolved": "https://registry.npmjs.org/use-intl/-/use-intl-3.0.0-beta.3.tgz", - "integrity": "sha512-b5c9F6F3Yw7xbdIVdDBj2qh5BHntdr2Obp3c40OTxXOwqDIyjAbOxjezGe7ak8EGo0TEezyN6oPvi6aQWPjDdQ==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/use-intl/-/use-intl-3.1.4.tgz", + "integrity": "sha512-iBIHPetLeEdAuIhAXRI9ukfjjvadP2EWoAEl6IvbWojrwYgcP52A6Al1nyzIwZD7iWBU1T3Ri3Hg4HsV7cWlVA==", "dependencies": { "@formatjs/ecma402-abstract": "^1.11.4", "intl-messageformat": "^9.3.18" @@ -14768,7 +14762,6 @@ "dependencies": { "@testing-library/react": "14.1.2", "jest-environment-jsdom": "29.7.0", - "next-intl": "3.0.0-beta.19", "react": "18.2.0", "zod": "3.22.4", "zustand": "4.3.9" @@ -14834,7 +14827,7 @@ "@heroicons/react": "2.0.18", "classnames": "2.3.2", "next": "14.0.3", - "next-intl": "3.0.0-beta.19", + "next-intl": "3.1.4", "react": "18.2.0", "zustand": "4.4.1" }, diff --git a/packages/list-store/package.json b/packages/list-store/package.json index c93ac6108..9e30aa555 100644 --- a/packages/list-store/package.json +++ b/packages/list-store/package.json @@ -18,7 +18,6 @@ "dependencies": { "@testing-library/react": "14.1.2", "jest-environment-jsdom": "29.7.0", - "next-intl": "3.0.0-beta.19", "react": "18.2.0", "zod": "3.22.4", "zustand": "4.3.9" diff --git a/packages/list-store/src/index.ts b/packages/list-store/src/index.ts index e7fd7ccaf..4b5e951b5 100644 --- a/packages/list-store/src/index.ts +++ b/packages/list-store/src/index.ts @@ -2,4 +2,4 @@ export * from './use-list-store'; export * from './sort'; export * from './search-params'; export * from './use-searchable-facet'; -export * from './list-store-updater'; +export * from './use-list-helpers'; diff --git a/packages/list-store/src/list-store-updater.tsx b/packages/list-store/src/use-list-helpers.tsx similarity index 66% rename from packages/list-store/src/list-store-updater.tsx rename to packages/list-store/src/use-list-helpers.tsx index 04edb979c..7e06f40a5 100644 --- a/packages/list-store/src/list-store-updater.tsx +++ b/packages/list-store/src/use-list-helpers.tsx @@ -1,7 +1,6 @@ 'use client'; -import {useRouter} from 'next-intl/client'; -import {useEffect, useTransition} from 'react'; +import {useEffect, useMemo, useTransition} from 'react'; import {useListStore} from './use-list-store'; import {getUrlWithSearchParams} from './search-params'; @@ -12,60 +11,60 @@ interface Props { query: string; sortBy?: string; selectedFilters?: { - [filterKey: string]: string[] | string | number | undefined; + [filterKey: string]: (string | number)[] | number | string | undefined; }; + routerReplace: (url: string, options?: {scroll?: boolean}) => void; } -export function useSearchParamsUpdate() { - const router = useRouter(); - const [isPending, startTransition] = useTransition(); - - const newDataNeeded = useListStore(s => s.newDataNeeded); +export const useListHref = () => { const query = useListStore(s => s.query); const offset = useListStore(s => s.offset); const sortBy = useListStore(s => s.sortBy); + const baseUrl = useListStore(s => s.baseUrl); const selectedFilters = useListStore(s => s.selectedFilters); - const transitionStarted = useListStore(s => s.transitionStarted); const defaultSortBy = useListStore(s => s.defaultSortBy); - const baseUrl = useListStore(s => s.baseUrl); - useEffect(() => { - if (newDataNeeded && !isPending) { - const url = getUrlWithSearchParams({ + const href = useMemo( + () => + getUrlWithSearchParams({ query, offset, sortBy, filters: selectedFilters, - baseUrl, defaultSortBy, - }); + baseUrl, + }), + [baseUrl, defaultSortBy, offset, query, selectedFilters, sortBy] + ); + + return href; +}; + +export function useSearchParamsUpdate(routerReplace: Props['routerReplace']) { + const [isPending, startTransition] = useTransition(); + const href = useListHref(); + + const newDataNeeded = useListStore(s => s.newDataNeeded); + const transitionStarted = useListStore(s => s.transitionStarted); + + useEffect(() => { + if (newDataNeeded && !isPending) { startTransition(() => { transitionStarted(); - router.replace(url, {scroll: false}); + routerReplace(href, {scroll: false}); }); } - }, [ - isPending, - router, - baseUrl, - defaultSortBy, - newDataNeeded, - query, - offset, - sortBy, - selectedFilters, - transitionStarted, - ]); + }, [href, isPending, newDataNeeded, routerReplace, transitionStarted]); } -const useUpdateListStore = ({ +export const useUpdateListStore = ({ totalCount, offset, limit, query, sortBy, selectedFilters, -}: Props) => { +}: Omit) => { const setNewData = useListStore(s => s.setNewData); useEffect(() => { @@ -79,10 +78,3 @@ const useUpdateListStore = ({ }); }, [limit, offset, query, selectedFilters, setNewData, sortBy, totalCount]); }; - -export function ListStoreUpdater({...updateProps}: Props) { - useUpdateListStore(updateProps); - useSearchParamsUpdate(); - - return null; -} diff --git a/packages/ui/index.tsx b/packages/ui/index.tsx index f2409a51c..95d283b41 100644 --- a/packages/ui/index.tsx +++ b/packages/ui/index.tsx @@ -6,3 +6,4 @@ export * from './wip-message'; export * from './slide-over'; export * from './slide-out'; export * from './notifications'; +export * from './intl-provider'; diff --git a/packages/ui/intl-provider.tsx b/packages/ui/intl-provider.tsx new file mode 100644 index 000000000..8506ab567 --- /dev/null +++ b/packages/ui/intl-provider.tsx @@ -0,0 +1,17 @@ +import {NextIntlClientProvider} from 'next-intl'; +import {ReactNode} from 'react'; + +interface Props { + children: ReactNode; + locale: string; +} + +export async function IntlProvider({children, locale}: Props) { + const messages = (await import(`./messages/${locale}.json`)).default; + + return ( + + {children} + + ); +} diff --git a/packages/ui/list/date-range-facet.tsx b/packages/ui/list/date-range-facet.tsx index fcdfded97..73938019e 100644 --- a/packages/ui/list/date-range-facet.tsx +++ b/packages/ui/list/date-range-facet.tsx @@ -22,7 +22,7 @@ export function DateRangeFacet({ const startDate = selectedFilters[startDateKey]; const endDate = selectedFilters[endDateKey]; - const t = useTranslations('Filters'); + const t = useTranslations('DateRangeFacet'); return ( diff --git a/packages/ui/list/index.tsx b/packages/ui/list/index.tsx index 20aae2dc0..c3fd78d1e 100644 --- a/packages/ui/list/index.tsx +++ b/packages/ui/list/index.tsx @@ -5,7 +5,6 @@ export * from './paginator'; export * from './selected-filters'; export * from './search-field'; export * from './order-selector'; -export * from './to-filtered-list-button'; export * from './multi-select-facet'; export * from './searchable-multi-select-facet'; export * from './date-range-facet'; diff --git a/packages/ui/list/search-field.tsx b/packages/ui/list/search-field.tsx index 2774f09d8..159eb2523 100644 --- a/packages/ui/list/search-field.tsx +++ b/packages/ui/list/search-field.tsx @@ -7,7 +7,7 @@ import {useTranslations} from 'next-intl'; export function SearchField({placeholder = ''}: {placeholder?: string}) { const query = useListStore(s => s.query); const queryChange = useListStore(s => s.queryChange); - const t = useTranslations('Filters'); + const t = useTranslations('SearchField'); const handleQueryChange = (e: React.ChangeEvent) => { queryChange(e.target.value); @@ -28,7 +28,7 @@ export function SearchField({placeholder = ''}: {placeholder?: string}) { /> @@ -37,7 +37,7 @@ export function SearchField({placeholder = ''}: {placeholder?: string}) { } function Label() { - const t = useTranslations('Filters'); + const t = useTranslations('SearchField'); return (