From f6c009711017a8de19bb923e71c4eaecef774720 Mon Sep 17 00:00:00 2001 From: Colin Dawson Date: Tue, 3 Feb 2026 18:32:32 +0000 Subject: [PATCH] Upgraded the language selector to cope with many more languages --- .../frame/components/LanguageSelector.tsx | 102 ++++++++++++++---- 1 file changed, 84 insertions(+), 18 deletions(-) diff --git a/src/modules/frame/components/LanguageSelector.tsx b/src/modules/frame/components/LanguageSelector.tsx index 7550b55..cb18f6a 100644 --- a/src/modules/frame/components/LanguageSelector.tsx +++ b/src/modules/frame/components/LanguageSelector.tsx @@ -1,4 +1,5 @@ -import { NavDropdown } from "react-bootstrap"; +import { useState } from "react"; +import { NavDropdown, Modal, Form } from "react-bootstrap"; import { availableLocales } from "../../../i18n/generatedLocales"; import i18n from "../../../i18n/i18n"; import profileService from "../../profile/services/profileService"; @@ -39,9 +40,25 @@ function formatLocaleLabel(locale: string) { export function LanguageSelectorMenuItem() { const current = i18n.language; + const [showModal, setShowModal] = useState(false); + const [search, setSearch] = useState(""); + const currentFlag = flagEmoji(current); const currentLabel = formatLocaleLabel(current); + // ⭐ Primary languages you want to show in the main dropdown + const primaryLocales = ["en-GB", "en-US", "fr-FR", "fr-CA", "hi-IN", "ur-PK"]; + + // ⭐ Build the shortlist + const baseLang = current.split("-")[0]; + const baseLangLocale = availableLocales.find((l) => l.startsWith(baseLang)); + + const shortlist = new Set( + [current, baseLangLocale, ...primaryLocales].filter(Boolean) as string[], + ); + + const visibleLocales = availableLocales.filter((l) => shortlist.has(l)); + async function handleSelect(locale: string) { try { await profileService.patchMyProfile({ @@ -49,28 +66,77 @@ export function LanguageSelectorMenuItem() { }); } catch (err) { console.error("Failed to update preferred locale", err); - // Optional: show toast or revert language } i18n.changeLanguage(locale); } - return ( - - {availableLocales.map((locale) => { - const flag = flagEmoji(locale); - const label = formatLocaleLabel(locale); + // ⭐ Filter for modal search + const filteredLocales = availableLocales.filter((locale) => + formatLocaleLabel(locale).toLowerCase().includes(search.toLowerCase()), + ); - return ( - handleSelect(locale)} - > - {flag} {label} - - ); - })} - + return ( + <> + + {visibleLocales.map((locale) => { + const flag = flagEmoji(locale); + const label = formatLocaleLabel(locale); + + return ( + handleSelect(locale)} + > + {flag} {label} + + ); + })} + + + + setShowModal(true)}> + More languages… + + + + {/* ⭐ Modal for full searchable list */} + setShowModal(false)} centered> + + Select Language + + + + setSearch(e.target.value)} + className="mb-3" + /> + + {filteredLocales.map((locale) => { + const flag = flagEmoji(locale); + const label = formatLocaleLabel(locale); + + return ( +
{ + handleSelect(locale); + setShowModal(false); + }} + > + {flag} {label} +
+ ); + })} +
+
+ ); } +export default LanguageSelectorMenuItem;