import React from 'react'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../ui/select'; import { Globe } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import { type Language, useLanguage } from '../../../contexts/LanguageContext'; // Re-export the canonical Language type so consumers can import from either location. export type { Language }; export interface LanguageSelectorProps { /** Whether to show text labels alongside the globe icon */ showLabel?: boolean; /** UI variant style */ variant?: 'minimal' | 'default'; /** Whether to show the globe icon */ showIcon?: boolean; /** Additional CSS classes */ className?: string; /** * Whether to render the selector when only one language is configured. * When `false` (the default), the selector hides itself in monolingual apps. */ showWhenMonolingual?: boolean; } /** * `LanguageSelector` — a self-contained language picker wired to `LanguageContext`. * * The list of languages displayed is read from `LanguageContext.availableLanguages` * (configured via the `availableLanguages` prop on `` or * ``). The component is fully data-driven: pass any number of * languages and they will all appear in the dropdown. * * Changing the selected language: * 1. Updates `LanguageContext` (persists to localStorage) * 2. Calls `i18n.changeLanguage()` (all `useTranslation()` consumers re-render) * 3. Invalidates the React Query cache (data-layer strings refresh) * * **Auto-hide:** When only one language is configured (`isMonolingual === true`), * the component renders `null` by default. Pass `showWhenMonolingual` to override. * * Must be rendered inside ``. */ export function LanguageSelector({ showLabel = false, variant = 'default', showIcon = true, className = '', showWhenMonolingual = false, }: LanguageSelectorProps) { const { language, setLanguage, availableLanguages, isMonolingual } = useLanguage(); const { t } = useTranslation(); // Hide selector when only one language is configured if (isMonolingual && !showWhenMonolingual) { return null; } // Compute display labels with i18n fallback support. // Known codes (pt-BR, en, es) get their localized label from translations; // custom codes use the label provided in the LanguageDefinition. const items = availableLanguages.map(lang => { const knownLabelKey = lang.code === 'pt-BR' ? 'languageSelector.ptBR' : lang.code === 'en' ? 'languageSelector.en' : lang.code === 'es' ? 'languageSelector.es' : null; return { value: lang.code, label: knownLabelKey ? t(knownLabelKey, lang.label) : lang.label, // Fall back to the first two characters of the code if no shortLabel given minimalLabel: lang.shortLabel ?? lang.code.slice(0, 2).toUpperCase(), }; }); const currentItem = items.find(l => l.value === language) ?? items[0]; const displayLabel = variant === 'minimal' ? currentItem.minimalLabel : currentItem.label; return ( ); }