Language Switcher
Overview
The LanguageSwitcher component provides a dropdown popover for switching the application locale. It displays the current language with its country flag and allows users to select from all configured locales. The component uses Next.js useRouter for client-side locale transitions and supports 21 languages including RTL languages like Arabic and Hebrew.
Import
import { LanguageSwitcher } from "@/components/language-switcher";
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
compact | boolean | No | false | When true, hides the locale name and chevron icon, showing only the flag. Useful for tight header layouts. |
Supported Locales
The component includes a built-in languageMap with flag images, short names, full names, and RTL indicators for:
| Code | Name | Full Name | RTL |
|---|---|---|---|
en | EN | English | No |
fr | FR | Francais | No |
es | ES | Espanol | No |
zh | ZH | Simplified Chinese | No |
de | DE | Deutsch | No |
ar | AR | Arabic | Yes |
he | HE | Hebrew | Yes |
ru | RU | Russian | No |
uk | UK | Ukrainian | No |
pt | PT | Portuguese | No |
it | IT | Italiano | No |
ja | JA | Japanese | No |
ko | KO | Korean | No |
nl | NL | Nederlands | No |
pl | PL | Polski | No |
tr | TR | Turkish | No |
vi | VI | Vietnamese | No |
th | TH | Thai | No |
hi | HI | Hindi | No |
id | ID | Indonesia | No |
bg | BG | Bulgarian | No |
Only locales present in the LOCALES constant from @/lib/constants are rendered in the dropdown.
Usage Examples
Basic Usage
<LanguageSwitcher />
Compact Mode
<LanguageSwitcher compact />
Inside Navigation
<nav className="flex items-center gap-4">
<ThemeToggler />
<LanguageSwitcher compact={isMobile} />
</nav>
Behavior
- Clicking the trigger button toggles the dropdown popover open/closed.
- Selecting a language calls
router.replace(pathname, { locale })inside astartTransitionto perform a non-blocking locale switch. - Clicking outside the popover or pressing Escape closes the dropdown.
- During transition, all language buttons become disabled with
opacity-50to prevent double-selection. - The currently active locale is highlighted with a primary-colored background and a small indicator dot.
Styling
- Trigger button: Bordered pill with flag image, locale code, and chevron. Uses
border-gray-200 dark:border-gray-700styling. - Dropdown panel: Positioned absolutely to the right with
backdrop-blur-xl,rounded-xl, andshadow-xl. Scrollable with thin scrollbar for many locales. - Active locale:
bg-theme-primary-100 dark:bg-theme-primarywithshadow-mdand a white dot indicator. - Hover state: Subtle
bg-gray-100 dark:bg-gray-800/60background withscale-[1.02]transform. - Flags: Rendered via
next/imageat 16px width withobject-coverand small rounded corners.
Accessibility
- The trigger button has
aria-label="Select language". aria-expandedreflects the open/closed state of the dropdown.aria-controlslinks the trigger to the dropdown panel via a unique ID generated byuseId().- Each language option has
aria-label="Switch to {fullName}"for screen reader context. - The dropdown closes on
Escapekeypress. - Disabled buttons during transitions prevent accidental double interactions.
Related Components
- Navigation Controls - Parent component that conditionally renders the LanguageSwitcher.
- Settings Modal - Alternative location where locale settings may appear.