nyuchimzizi
Mzizi — an open-architecture project of the Bundu Foundation, operated and developed by Nyuchi. Built on the Five African Minerals palette.
Built by Nyuchi Africav4.0.39
In-app language selector with locale display. Prioritizes the 16 Zimbabwean official languages (Shona, Ndebele first), then African languages, then global. Shows current language with flag/code indicator. Critical for a platform serving 54 countries and 2000+ languages.
View the full component source code below.
"use client"
import * as React from "react"
import { cn } from "@/lib/utils"
interface Language {
code: string
name: string
nativeName: string
flag?: string
}
interface LanguageSwitcherProps extends React.ComponentProps<"div"> {
languages?: Language[]
current?: string
onChange?: (code: string) => void
variant?: "dropdown" | "inline"
}
const defaultLanguages: Language[] = [
{ code: "sn", name: "Shona", nativeName: "ChiShona" },
{ code: "nd", name: "Ndebele", nativeName: "IsiNdebele" },
{ code: "en", name: "English", nativeName: "English" },
{ code: "sw", name: "Swahili", nativeName: "Kiswahili" },
{ code: "zu", name: "Zulu", nativeName: "IsiZulu" },
{ code: "xh", name: "Xhosa", nativeName: "IsiXhosa" },
{ code: "fr", name: "French", nativeName: "Français" },
{ code: "pt", name: "Portuguese", nativeName: "Português" },
]
function LanguageSwitcher({
languages = defaultLanguages, current = "en", onChange, variant = "dropdown", loading = false, className, ...props
}: LanguageSwitcherProps) {
const currentLang = languages.find(l => l.code === current)
if (variant === "inline") {
return (
<div data-slot="language-switcher" data-portal="https://design.nyuchi.com/components/language-switcher" className={cn("flex flex-wrap gap-1", className)} role="radiogroup" aria-label="Language" {...props}>
{languages.map(lang => (
<button key={lang.code} role="radio" aria-checked={current === lang.code} onClick={() => onChange?.(lang.code)}
className={cn("h-8 rounded-full px-3 text-xs font-medium transition-colors",
current === lang.code ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground hover:text-foreground"
)}>
{lang.nativeName}
</button>
))}
</div>
)
}
return (
<div data-slot="language-switcher" className={cn("relative", className)} {...props}>
<select
value={current}
onChange={(e) => onChange?.(e.target.value)}
className="h-12 w-full appearance-none rounded-full border border-input bg-input/30 px-4 pr-8 text-sm outline-none focus:border-ring focus:ring-[3px] focus:ring-ring/50"
aria-label="Select language"
>
{languages.map(lang => (
<option key={lang.code} value={lang.code}>{lang.nativeName} ({lang.name})</option>
))}
</select>
<div className="pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground">▾</div>
</div>
)
}
export { LanguageSwitcher }
export type { LanguageSwitcherProps }
npx shadcn@latest add https://mzizi.dev/api/v1/ui/language-switcherFetch this component's metadata and source code from the registry API.
/api/v1/ui/language-switcher