From 4ac89ba8c01da23e5205c3f72aeec3b1957777ef Mon Sep 17 00:00:00 2001 From: Henry Date: Wed, 25 Jun 2025 17:45:38 +0100 Subject: [PATCH] Fix build and add dyanmic imports --- apps/web/package.json | 1 - apps/web/src/hooks/useLocalisation.ts | 9 +- apps/web/src/locales/de/messages.po | 5 +- apps/web/src/locales/en/messages.po | 4 +- apps/web/src/locales/es/messages.po | 5 +- apps/web/src/locales/fr/messages.po | 5 +- apps/web/src/locales/it/messages.po | 5 +- apps/web/src/locales/nl/messages.po | 5 +- apps/web/src/pages/_app.tsx | 1 + apps/web/src/providers/lingui.tsx | 55 +++++---- apps/web/src/utils/i18n.ts | 53 ++++++++ .../components/UpdateDisplayNameForm.tsx | 26 ++-- pnpm-lock.yaml | 116 ------------------ 13 files changed, 120 insertions(+), 170 deletions(-) create mode 100644 apps/web/src/utils/i18n.ts diff --git a/apps/web/package.json b/apps/web/package.json index 5d070c66..4f16c908 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -57,7 +57,6 @@ "react-dom": "catalog:react18", "react-hook-form": "^7.51.1", "react-icons": "^5.5.0", - "react-intl": "^6.8.9", "react-lottie-player": "^1.5.5", "react-markdown": "^10.1.0", "superjson": "2.2.1", diff --git a/apps/web/src/hooks/useLocalisation.ts b/apps/web/src/hooks/useLocalisation.ts index cfbfed13..7d26d306 100644 --- a/apps/web/src/hooks/useLocalisation.ts +++ b/apps/web/src/hooks/useLocalisation.ts @@ -1,14 +1,21 @@ import { useLingui } from "@lingui/react"; +import type { Locale } from "~/locales"; import { useLinguiContext } from "~/providers/lingui"; +import { activateLocale } from "~/utils/i18n"; export function useLocalisation() { const { i18n } = useLingui(); const { locale, setLocale, availableLocales } = useLinguiContext(); + const handleSetLocale = async (newLocale: Locale) => { + await activateLocale(newLocale); + setLocale(newLocale); + }; + return { locale, - setLocale, + setLocale: handleSetLocale, availableLocales, formatDate: i18n.date, formatNumber: i18n.number, diff --git a/apps/web/src/locales/de/messages.po b/apps/web/src/locales/de/messages.po index 20851da8..21b108ef 100644 --- a/apps/web/src/locales/de/messages.po +++ b/apps/web/src/locales/de/messages.po @@ -399,11 +399,11 @@ msgstr "Diskutiere und arbeite gemeinsam an Karten." msgid "Display name" msgstr "Anzeigename" -#: src/views/settings/components/UpdateDisplayNameForm.tsx:18 +#: src/views/settings/components/UpdateDisplayNameForm.tsx:22 msgid "Display name cannot exceed 280 characters" msgstr "Anzeigename darf nicht länger als 280 Zeichen sein" -#: src/views/settings/components/UpdateDisplayNameForm.tsx:15 +#: src/views/settings/components/UpdateDisplayNameForm.tsx:19 msgid "Display name must be at least 3 characters long" msgstr "Anzeigename muss mindestens 3 Zeichen lang sein" @@ -545,6 +545,7 @@ msgstr "Finden Sie Antworten auf häufige Fragen zum Projekt. Nicht gefunden, wo msgid "For long-term sustainability, we recognise all good open source projects need a source of revenue. Ours comes from the paid cloud offering for workspaces with multiple users (free during the beta) and for custom workspace slugs. There's no obligation to use it, and you can self-host the software on your own infrastructure free of charge." msgstr "Für langfristige Nachhaltigkeit erkennen wir an, dass alle guten Open-Source-Projekte eine Einnahmequelle benötigen. Unsere stammt aus dem kostenpflichtigen Cloud-Angebot für Workspaces mit mehreren Benutzern (kostenlos während der Beta-Phase) und für benutzerdefinierte Workspace-Slugs. Es besteht keine Verpflichtung, dieses Angebot zu nutzen, und Sie können die Software kostenlos auf Ihrer eigenen Infrastruktur selbst hosten." +#: src/views/home/components/Pricing.tsx:32 #: src/views/home/components/Pricing.tsx:32 msgid "Free" msgstr "Kostenlos" diff --git a/apps/web/src/locales/en/messages.po b/apps/web/src/locales/en/messages.po index 04524d99..acf0bdcd 100644 --- a/apps/web/src/locales/en/messages.po +++ b/apps/web/src/locales/en/messages.po @@ -415,11 +415,11 @@ msgstr "Discuss and collaborate on cards." msgid "Display name" msgstr "Display name" -#: src/views/settings/components/UpdateDisplayNameForm.tsx:18 +#: src/views/settings/components/UpdateDisplayNameForm.tsx:22 msgid "Display name cannot exceed 280 characters" msgstr "Display name cannot exceed 280 characters" -#: src/views/settings/components/UpdateDisplayNameForm.tsx:15 +#: src/views/settings/components/UpdateDisplayNameForm.tsx:19 msgid "Display name must be at least 3 characters long" msgstr "Display name must be at least 3 characters long" diff --git a/apps/web/src/locales/es/messages.po b/apps/web/src/locales/es/messages.po index 2f7be312..e355a488 100644 --- a/apps/web/src/locales/es/messages.po +++ b/apps/web/src/locales/es/messages.po @@ -399,11 +399,11 @@ msgstr "Discute y colabora en las tarjetas." msgid "Display name" msgstr "Nombre visible" -#: src/views/settings/components/UpdateDisplayNameForm.tsx:18 +#: src/views/settings/components/UpdateDisplayNameForm.tsx:22 msgid "Display name cannot exceed 280 characters" msgstr "El nombre visible no puede exceder los 280 caracteres" -#: src/views/settings/components/UpdateDisplayNameForm.tsx:15 +#: src/views/settings/components/UpdateDisplayNameForm.tsx:19 msgid "Display name must be at least 3 characters long" msgstr "El nombre visible debe tener al menos 3 caracteres" @@ -545,6 +545,7 @@ msgstr "Encuentra respuestas a preguntas frecuentes sobre el proyecto. ¿No encu msgid "For long-term sustainability, we recognise all good open source projects need a source of revenue. Ours comes from the paid cloud offering for workspaces with multiple users (free during the beta) and for custom workspace slugs. There's no obligation to use it, and you can self-host the software on your own infrastructure free of charge." msgstr "Para la sostenibilidad a largo plazo, reconocemos que todos los buenos proyectos de código abierto necesitan una fuente de ingresos. La nuestra proviene de la oferta de pago en la nube para espacios de trabajo con múltiples usuarios (gratuita durante la beta) y para slugs personalizados de espacios de trabajo. No hay obligación de usarla, y puedes autoalojar el software en tu propia infraestructura sin costo alguno." +#: src/views/home/components/Pricing.tsx:32 #: src/views/home/components/Pricing.tsx:32 msgid "Free" msgstr "Gratis" diff --git a/apps/web/src/locales/fr/messages.po b/apps/web/src/locales/fr/messages.po index 6ed139b7..275a0a0d 100644 --- a/apps/web/src/locales/fr/messages.po +++ b/apps/web/src/locales/fr/messages.po @@ -399,11 +399,11 @@ msgstr "Discutez et collaborez sur les cartes." msgid "Display name" msgstr "Nom d'affichage" -#: src/views/settings/components/UpdateDisplayNameForm.tsx:18 +#: src/views/settings/components/UpdateDisplayNameForm.tsx:22 msgid "Display name cannot exceed 280 characters" msgstr "Le nom d'affichage ne peut pas dépasser 280 caractères" -#: src/views/settings/components/UpdateDisplayNameForm.tsx:15 +#: src/views/settings/components/UpdateDisplayNameForm.tsx:19 msgid "Display name must be at least 3 characters long" msgstr "Le nom d'affichage doit comporter au moins 3 caractères" @@ -545,6 +545,7 @@ msgstr "Trouvez des réponses aux questions fréquentes sur le projet. Vous ne t msgid "For long-term sustainability, we recognise all good open source projects need a source of revenue. Ours comes from the paid cloud offering for workspaces with multiple users (free during the beta) and for custom workspace slugs. There's no obligation to use it, and you can self-host the software on your own infrastructure free of charge." msgstr "Pour une durabilité à long terme, nous reconnaissons que tous les bons projets open source ont besoin d'une source de revenus. La nôtre provient de l'offre cloud payante pour les espaces de travail avec plusieurs utilisateurs (gratuite pendant la bêta) et pour les slugs d'espace de travail personnalisés. Il n'y a aucune obligation de l'utiliser, et vous pouvez auto-héberger le logiciel sur votre propre infrastructure gratuitement." +#: src/views/home/components/Pricing.tsx:32 #: src/views/home/components/Pricing.tsx:32 msgid "Free" msgstr "Gratuit" diff --git a/apps/web/src/locales/it/messages.po b/apps/web/src/locales/it/messages.po index e77d34f6..33dd7978 100644 --- a/apps/web/src/locales/it/messages.po +++ b/apps/web/src/locales/it/messages.po @@ -399,11 +399,11 @@ msgstr "Discuti e collabora sulle schede." msgid "Display name" msgstr "Nome visualizzato" -#: src/views/settings/components/UpdateDisplayNameForm.tsx:18 +#: src/views/settings/components/UpdateDisplayNameForm.tsx:22 msgid "Display name cannot exceed 280 characters" msgstr "Il nome visualizzato non può superare i 280 caratteri" -#: src/views/settings/components/UpdateDisplayNameForm.tsx:15 +#: src/views/settings/components/UpdateDisplayNameForm.tsx:19 msgid "Display name must be at least 3 characters long" msgstr "Il nome visualizzato deve contenere almeno 3 caratteri" @@ -545,6 +545,7 @@ msgstr "Trova risposte alle domande comuni sul progetto. Non trovi quello che st msgid "For long-term sustainability, we recognise all good open source projects need a source of revenue. Ours comes from the paid cloud offering for workspaces with multiple users (free during the beta) and for custom workspace slugs. There's no obligation to use it, and you can self-host the software on your own infrastructure free of charge." msgstr "Per la sostenibilità a lungo termine, riconosciamo che tutti i buoni progetti open source necessitano di una fonte di entrate. La nostra proviene dall'offerta cloud a pagamento per workspace con più utenti (gratuita durante la beta) e per slug di workspace personalizzati. Non c'è alcun obbligo di utilizzarla, e puoi ospitare autonomamente il software sulla tua infrastruttura gratuitamente." +#: src/views/home/components/Pricing.tsx:32 #: src/views/home/components/Pricing.tsx:32 msgid "Free" msgstr "Gratuito" diff --git a/apps/web/src/locales/nl/messages.po b/apps/web/src/locales/nl/messages.po index 2a7dbfb9..83ef9aa7 100644 --- a/apps/web/src/locales/nl/messages.po +++ b/apps/web/src/locales/nl/messages.po @@ -399,11 +399,11 @@ msgstr "Bespreek en werk samen aan kaarten." msgid "Display name" msgstr "Weergavenaam" -#: src/views/settings/components/UpdateDisplayNameForm.tsx:18 +#: src/views/settings/components/UpdateDisplayNameForm.tsx:22 msgid "Display name cannot exceed 280 characters" msgstr "Weergavenaam mag niet langer zijn dan 280 tekens" -#: src/views/settings/components/UpdateDisplayNameForm.tsx:15 +#: src/views/settings/components/UpdateDisplayNameForm.tsx:19 msgid "Display name must be at least 3 characters long" msgstr "Weergavenaam moet minimaal 3 tekens lang zijn" @@ -545,6 +545,7 @@ msgstr "Vind antwoorden op veelgestelde vragen over het project. Kun je niet vin msgid "For long-term sustainability, we recognise all good open source projects need a source of revenue. Ours comes from the paid cloud offering for workspaces with multiple users (free during the beta) and for custom workspace slugs. There's no obligation to use it, and you can self-host the software on your own infrastructure free of charge." msgstr "Voor duurzaamheid op lange termijn erkennen we dat alle goede open source projecten een inkomstenbron nodig hebben. De onze komt van de betaalde cloudoplossing voor werkruimtes met meerdere gebruikers (gratis tijdens de bèta) en voor aangepaste werkruimte-slugs. Je bent niet verplicht om hiervan gebruik te maken en je kunt de software gratis op je eigen infrastructuur hosten." +#: src/views/home/components/Pricing.tsx:32 #: src/views/home/components/Pricing.tsx:32 msgid "Free" msgstr "Gratis" diff --git a/apps/web/src/pages/_app.tsx b/apps/web/src/pages/_app.tsx index 673925d0..78da6b25 100644 --- a/apps/web/src/pages/_app.tsx +++ b/apps/web/src/pages/_app.tsx @@ -1,4 +1,5 @@ import "~/styles/globals.css"; +import "~/utils/i18n"; import type { AppType } from "next/app"; import { Plus_Jakarta_Sans } from "next/font/google"; diff --git a/apps/web/src/providers/lingui.tsx b/apps/web/src/providers/lingui.tsx index 3e5e35e2..bc8f0c3e 100644 --- a/apps/web/src/providers/lingui.tsx +++ b/apps/web/src/providers/lingui.tsx @@ -1,25 +1,10 @@ import type { ReactNode } from "react"; -import { i18n } from "@lingui/core"; import { I18nProvider } from "@lingui/react"; -import { createContext, useContext, useEffect, useRef, useState } from "react"; +import { createContext, useContext, useEffect, useState } from "react"; import type { Locale } from "~/locales"; import { defaultLocale, locales } from "~/locales"; -import { messages as deMessages } from "~/locales/de/messages"; -import { messages as enMessages } from "~/locales/en/messages"; -import { messages as esMessages } from "~/locales/es/messages"; -import { messages as frMessages } from "~/locales/fr/messages"; -import { messages as itMessages } from "~/locales/it/messages"; -import { messages as nlMessages } from "~/locales/nl/messages"; - -const messages = { - en: enMessages, - fr: frMessages, - de: deMessages, - es: esMessages, - it: itMessages, - nl: nlMessages, -}; +import { activateLocale, i18n, initializeI18n } from "~/utils/i18n"; interface LinguiContextType { locale: Locale; @@ -42,19 +27,32 @@ interface LinguiProviderProps { initialLocale?: Locale; } +function detectBrowserLocale(availableLocales: readonly string[]): Locale { + if (typeof navigator === "undefined") { + return defaultLocale; + } + + const browserLanguages = navigator.languages || [navigator.language]; + + for (const browserLang of browserLanguages) { + const langCode = browserLang.split("-")[0]; + + if (langCode && availableLocales.includes(langCode.toLowerCase())) { + return langCode.toLowerCase() as Locale; + } + } + + return defaultLocale; +} + export function LinguiProviderWrapper({ children, initialLocale = defaultLocale, }: LinguiProviderProps) { const [locale, setLocale] = useState(defaultLocale); const [isHydrated, setIsHydrated] = useState(false); - const isInitialised = useRef(false); - if (!isInitialised.current) { - i18n.load(defaultLocale, messages[defaultLocale]); - i18n.activate(defaultLocale); - isInitialised.current = true; - } + initializeI18n(); useEffect(() => { const savedLocale = localStorage.getItem("locale") as Locale; @@ -62,15 +60,18 @@ export function LinguiProviderWrapper({ if (savedLocale && locales.includes(savedLocale)) { setLocale(savedLocale); } else { - setLocale(initialLocale); + const detectedLocale = detectBrowserLocale(locales); + setLocale(detectedLocale); } setIsHydrated(true); }, [initialLocale]); useEffect(() => { - if (isHydrated) { - i18n.load(locale, messages[locale]); - i18n.activate(locale); + if (isHydrated && locale !== defaultLocale) { + activateLocale(locale).then(() => { + localStorage.setItem("locale", locale); + }); + } else if (isHydrated) { localStorage.setItem("locale", locale); } }, [locale, isHydrated]); diff --git a/apps/web/src/utils/i18n.ts b/apps/web/src/utils/i18n.ts new file mode 100644 index 00000000..cd586c07 --- /dev/null +++ b/apps/web/src/utils/i18n.ts @@ -0,0 +1,53 @@ +import { i18n } from "@lingui/core"; + +import type { Locale } from "~/locales"; +import { defaultLocale } from "~/locales"; +import { messages as enMessages } from "~/locales/en/messages"; + +const loadMessages = async (locale: Locale) => { + switch (locale) { + case "en": + return enMessages; + case "fr": + return (await import("~/locales/fr/messages")).messages; + case "de": + return (await import("~/locales/de/messages")).messages; + case "es": + return (await import("~/locales/es/messages")).messages; + case "it": + return (await import("~/locales/it/messages")).messages; + case "nl": + return (await import("~/locales/nl/messages")).messages; + default: + return enMessages; + } +}; + +let isInitialized = false; +const loadedLocales = new Set(); + +export function initializeI18n(locale: Locale = defaultLocale) { + if (!isInitialized) { + i18n.load(defaultLocale, enMessages); + i18n.activate(defaultLocale); + loadedLocales.add(defaultLocale); + isInitialized = true; + } + + return i18n; +} + +export async function activateLocale(locale: Locale) { + if (!loadedLocales.has(locale)) { + const messages = await loadMessages(locale); + i18n.load(locale, messages); + loadedLocales.add(locale); + } + + i18n.activate(locale); + return i18n; +} + +initializeI18n(); + +export { i18n }; diff --git a/apps/web/src/views/settings/components/UpdateDisplayNameForm.tsx b/apps/web/src/views/settings/components/UpdateDisplayNameForm.tsx index f54b452f..fc6af1f5 100644 --- a/apps/web/src/views/settings/components/UpdateDisplayNameForm.tsx +++ b/apps/web/src/views/settings/components/UpdateDisplayNameForm.tsx @@ -8,22 +8,22 @@ import Input from "~/components/Input"; import { usePopup } from "~/providers/popup"; import { api } from "~/utils/api"; -const schema = z.object({ - name: z - .string() - .min(3, { - message: t`Display name must be at least 3 characters long`, - }) - .max(280, { - message: t`Display name cannot exceed 280 characters`, - }), -}); - -type FormValues = z.infer; - const UpdateDisplayNameForm = ({ displayName }: { displayName: string }) => { const utils = api.useUtils(); const { showPopup } = usePopup(); + + const schema = z.object({ + name: z + .string() + .min(3, { + message: t`Display name must be at least 3 characters long`, + }) + .max(280, { + message: t`Display name cannot exceed 280 characters`, + }), + }); + + type FormValues = z.infer; const { register, handleSubmit, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3804393d..83374bd8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -195,9 +195,6 @@ importers: react-icons: specifier: ^5.5.0 version: 5.5.0(react@18.3.1) - react-intl: - specifier: ^6.8.9 - version: 6.8.9(react@18.3.1)(typescript@5.7.2) react-lottie-player: specifier: ^1.5.5 version: 1.5.6(react@18.3.1) @@ -1524,35 +1521,6 @@ packages: '@floating-ui/utils@0.2.8': resolution: {integrity: sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==} - '@formatjs/ecma402-abstract@2.2.4': - resolution: {integrity: sha512-lFyiQDVvSbQOpU+WFd//ILolGj4UgA/qXrKeZxdV14uKiAUiPAtX6XAn7WBCRi7Mx6I7EybM9E5yYn4BIpZWYg==} - - '@formatjs/fast-memoize@2.2.3': - resolution: {integrity: sha512-3jeJ+HyOfu8osl3GNSL4vVHUuWFXR03Iz9jjgI7RwjG6ysu/Ymdr0JRCPHfF5yGbTE6JCrd63EpvX1/WybYRbA==} - - '@formatjs/icu-messageformat-parser@2.9.4': - resolution: {integrity: sha512-Tbvp5a9IWuxUcpWNIW6GlMQYEc4rwNHR259uUFoKWNN1jM9obf9Ul0e+7r7MvFOBNcN+13K7NuKCKqQiAn1QEg==} - - '@formatjs/icu-skeleton-parser@1.8.8': - resolution: {integrity: sha512-vHwK3piXwamFcx5YQdCdJxUQ1WdTl6ANclt5xba5zLGDv5Bsur7qz8AD7BevaKxITwpgDeU0u8My3AIibW9ywA==} - - '@formatjs/intl-displaynames@6.8.5': - resolution: {integrity: sha512-85b+GdAKCsleS6cqVxf/Aw/uBd+20EM0wDpgaxzHo3RIR3bxF4xCJqH/Grbzx8CXurTgDDZHPdPdwJC+May41w==} - - '@formatjs/intl-listformat@7.7.5': - resolution: {integrity: sha512-Wzes10SMNeYgnxYiKsda4rnHP3Q3II4XT2tZyOgnH5fWuHDtIkceuWlRQNsvrI3uiwP4hLqp2XdQTCsfkhXulg==} - - '@formatjs/intl-localematcher@0.5.8': - resolution: {integrity: sha512-I+WDNWWJFZie+jkfkiK5Mp4hEDyRSEvmyfYadflOno/mmKJKcB17fEpEH0oJu/OWhhCJ8kJBDz2YMd/6cDl7Mg==} - - '@formatjs/intl@2.10.15': - resolution: {integrity: sha512-i6+xVqT+6KCz7nBfk4ybMXmbKO36tKvbMKtgFz9KV+8idYFyFbfwKooYk8kGjyA5+T5f1kEPQM5IDLXucTAQ9g==} - peerDependencies: - typescript: ^4.7 || 5 - peerDependenciesMeta: - typescript: - optional: true - '@hapi/bourne@3.0.0': resolution: {integrity: sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==} @@ -4618,9 +4586,6 @@ packages: resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} engines: {node: '>= 0.10'} - intl-messageformat@10.7.7: - resolution: {integrity: sha512-F134jIoeYMro/3I0h08D0Yt4N9o9pjddU/4IIxMMURqbAtI2wu70X8hvG1V48W49zXHXv3RKSF/po+0fDfsGjA==} - ip-address@9.0.5: resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} engines: {node: '>= 12'} @@ -6180,15 +6145,6 @@ packages: peerDependencies: react: '*' - react-intl@6.8.9: - resolution: {integrity: sha512-TUfj5E7lyUDvz/GtovC9OMh441kBr08rtIbgh3p0R8iF3hVY+V2W9Am7rb8BpJ/29BH1utJOqOOhmvEVh3GfZg==} - peerDependencies: - react: ^16.6.0 || 17 || 18 - typescript: ^4.7 || 5 - peerDependenciesMeta: - typescript: - optional: true - react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} @@ -8277,55 +8233,6 @@ snapshots: '@floating-ui/utils@0.2.8': {} - '@formatjs/ecma402-abstract@2.2.4': - dependencies: - '@formatjs/fast-memoize': 2.2.3 - '@formatjs/intl-localematcher': 0.5.8 - tslib: 2.8.1 - - '@formatjs/fast-memoize@2.2.3': - dependencies: - tslib: 2.8.1 - - '@formatjs/icu-messageformat-parser@2.9.4': - dependencies: - '@formatjs/ecma402-abstract': 2.2.4 - '@formatjs/icu-skeleton-parser': 1.8.8 - tslib: 2.8.1 - - '@formatjs/icu-skeleton-parser@1.8.8': - dependencies: - '@formatjs/ecma402-abstract': 2.2.4 - tslib: 2.8.1 - - '@formatjs/intl-displaynames@6.8.5': - dependencies: - '@formatjs/ecma402-abstract': 2.2.4 - '@formatjs/intl-localematcher': 0.5.8 - tslib: 2.8.1 - - '@formatjs/intl-listformat@7.7.5': - dependencies: - '@formatjs/ecma402-abstract': 2.2.4 - '@formatjs/intl-localematcher': 0.5.8 - tslib: 2.8.1 - - '@formatjs/intl-localematcher@0.5.8': - dependencies: - tslib: 2.8.1 - - '@formatjs/intl@2.10.15(typescript@5.7.2)': - dependencies: - '@formatjs/ecma402-abstract': 2.2.4 - '@formatjs/fast-memoize': 2.2.3 - '@formatjs/icu-messageformat-parser': 2.9.4 - '@formatjs/intl-displaynames': 6.8.5 - '@formatjs/intl-listformat': 7.7.5 - intl-messageformat: 10.7.7 - tslib: 2.8.1 - optionalDependencies: - typescript: 5.7.2 - '@hapi/bourne@3.0.0': {} '@headlessui/react@2.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': @@ -11946,13 +11853,6 @@ snapshots: interpret@1.4.0: {} - intl-messageformat@10.7.7: - dependencies: - '@formatjs/ecma402-abstract': 2.2.4 - '@formatjs/fast-memoize': 2.2.3 - '@formatjs/icu-messageformat-parser': 2.9.4 - tslib: 2.8.1 - ip-address@9.0.5: dependencies: jsbn: 1.1.0 @@ -13881,22 +13781,6 @@ snapshots: dependencies: react: 18.3.1 - react-intl@6.8.9(react@18.3.1)(typescript@5.7.2): - dependencies: - '@formatjs/ecma402-abstract': 2.2.4 - '@formatjs/icu-messageformat-parser': 2.9.4 - '@formatjs/intl': 2.10.15(typescript@5.7.2) - '@formatjs/intl-displaynames': 6.8.5 - '@formatjs/intl-listformat': 7.7.5 - '@types/hoist-non-react-statics': 3.3.6 - '@types/react': 18.3.15 - hoist-non-react-statics: 3.3.2 - intl-messageformat: 10.7.7 - react: 18.3.1 - tslib: 2.8.1 - optionalDependencies: - typescript: 5.7.2 - react-is@16.13.1: {} react-is@17.0.2: {}