Skip to main content

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

PropTypeRequiredDefaultDescription
compactbooleanNofalseWhen 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:

CodeNameFull NameRTL
enENEnglishNo
frFRFrancaisNo
esESEspanolNo
zhZHSimplified ChineseNo
deDEDeutschNo
arARArabicYes
heHEHebrewYes
ruRURussianNo
ukUKUkrainianNo
ptPTPortugueseNo
itITItalianoNo
jaJAJapaneseNo
koKOKoreanNo
nlNLNederlandsNo
plPLPolskiNo
trTRTurkishNo
viVIVietnameseNo
thTHThaiNo
hiHIHindiNo
idIDIndonesiaNo
bgBGBulgarianNo

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

  1. Clicking the trigger button toggles the dropdown popover open/closed.
  2. Selecting a language calls router.replace(pathname, { locale }) inside a startTransition to perform a non-blocking locale switch.
  3. Clicking outside the popover or pressing Escape closes the dropdown.
  4. During transition, all language buttons become disabled with opacity-50 to prevent double-selection.
  5. 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-700 styling.
  • Dropdown panel: Positioned absolutely to the right with backdrop-blur-xl, rounded-xl, and shadow-xl. Scrollable with thin scrollbar for many locales.
  • Active locale: bg-theme-primary-100 dark:bg-theme-primary with shadow-md and a white dot indicator.
  • Hover state: Subtle bg-gray-100 dark:bg-gray-800/60 background with scale-[1.02] transform.
  • Flags: Rendered via next/image at 16px width with object-cover and small rounded corners.

Accessibility

  • The trigger button has aria-label="Select language".
  • aria-expanded reflects the open/closed state of the dropdown.
  • aria-controls links the trigger to the dropdown panel via a unique ID generated by useId().
  • Each language option has aria-label="Switch to {fullName}" for screen reader context.
  • The dropdown closes on Escape keypress.
  • Disabled buttons during transitions prevent accidental double interactions.