Upgraded the language selector to cope with many more languages
This commit is contained in:
parent
8cbdf0fedf
commit
f6c0097110
@ -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 { availableLocales } from "../../../i18n/generatedLocales";
|
||||||
import i18n from "../../../i18n/i18n";
|
import i18n from "../../../i18n/i18n";
|
||||||
import profileService from "../../profile/services/profileService";
|
import profileService from "../../profile/services/profileService";
|
||||||
@ -39,9 +40,25 @@ function formatLocaleLabel(locale: string) {
|
|||||||
export function LanguageSelectorMenuItem() {
|
export function LanguageSelectorMenuItem() {
|
||||||
const current = i18n.language;
|
const current = i18n.language;
|
||||||
|
|
||||||
|
const [showModal, setShowModal] = useState(false);
|
||||||
|
const [search, setSearch] = useState("");
|
||||||
|
|
||||||
const currentFlag = flagEmoji(current);
|
const currentFlag = flagEmoji(current);
|
||||||
const currentLabel = formatLocaleLabel(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) {
|
async function handleSelect(locale: string) {
|
||||||
try {
|
try {
|
||||||
await profileService.patchMyProfile({
|
await profileService.patchMyProfile({
|
||||||
@ -49,28 +66,77 @@ export function LanguageSelectorMenuItem() {
|
|||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to update preferred locale", err);
|
console.error("Failed to update preferred locale", err);
|
||||||
// Optional: show toast or revert language
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i18n.changeLanguage(locale);
|
i18n.changeLanguage(locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
// ⭐ Filter for modal search
|
||||||
<NavDropdown align="end" title={`${currentFlag} ${currentLabel}`}>
|
const filteredLocales = availableLocales.filter((locale) =>
|
||||||
{availableLocales.map((locale) => {
|
formatLocaleLabel(locale).toLowerCase().includes(search.toLowerCase()),
|
||||||
const flag = flagEmoji(locale);
|
);
|
||||||
const label = formatLocaleLabel(locale);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NavDropdown.Item
|
<>
|
||||||
key={locale}
|
<NavDropdown align="end" title={`${currentFlag} ${currentLabel}`}>
|
||||||
active={locale === current}
|
{visibleLocales.map((locale) => {
|
||||||
onClick={() => handleSelect(locale)}
|
const flag = flagEmoji(locale);
|
||||||
>
|
const label = formatLocaleLabel(locale);
|
||||||
{flag} {label}
|
|
||||||
</NavDropdown.Item>
|
return (
|
||||||
);
|
<NavDropdown.Item
|
||||||
})}
|
key={locale}
|
||||||
</NavDropdown>
|
active={locale === current}
|
||||||
|
onClick={() => handleSelect(locale)}
|
||||||
|
>
|
||||||
|
{flag} {label}
|
||||||
|
</NavDropdown.Item>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
<NavDropdown.Divider />
|
||||||
|
|
||||||
|
<NavDropdown.Item onClick={() => setShowModal(true)}>
|
||||||
|
More languages…
|
||||||
|
</NavDropdown.Item>
|
||||||
|
</NavDropdown>
|
||||||
|
|
||||||
|
{/* ⭐ Modal for full searchable list */}
|
||||||
|
<Modal show={showModal} onHide={() => setShowModal(false)} centered>
|
||||||
|
<Modal.Header closeButton>
|
||||||
|
<Modal.Title>Select Language</Modal.Title>
|
||||||
|
</Modal.Header>
|
||||||
|
|
||||||
|
<Modal.Body>
|
||||||
|
<Form.Control
|
||||||
|
type="text"
|
||||||
|
placeholder="Search languages…"
|
||||||
|
value={search}
|
||||||
|
onChange={(e) => setSearch(e.target.value)}
|
||||||
|
className="mb-3"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{filteredLocales.map((locale) => {
|
||||||
|
const flag = flagEmoji(locale);
|
||||||
|
const label = formatLocaleLabel(locale);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={locale}
|
||||||
|
className="mb-2"
|
||||||
|
style={{ cursor: "pointer" }}
|
||||||
|
onClick={() => {
|
||||||
|
handleSelect(locale);
|
||||||
|
setShowModal(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{flag} {label}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Modal.Body>
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
export default LanguageSelectorMenuItem;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user