All files / src/components/shared/LanguageSwitcher LanguageSwitcher.tsx

76.47% Statements 13/17
50% Branches 1/2
100% Functions 3/3
76.47% Lines 13/17

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72                            7x 226x 226x   226x                       226x 4x 4x 4x 4x     4x                 4x       226x                     2034x                    
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Globe } from 'lucide-react';
import { updateUserPreferences } from '../../../services/api/userApi';
import { useAuth } from '../../../hooks/useAuth';
import type { UpdatePreferencesRequest } from '../../../types/user';
 
/**
 * Language selector. Tailwind + a native <select> (no MUI): this control sits in the
 * public navigation, which is part of the eager homepage graph, so keeping it MUI-free
 * is what stops @mui/material from being pulled into the public entry chunk. Styling is
 * neutral (transparent bg, inherited text colour) so it reads correctly on both the
 * dark public nav and the light auth pages where it is also used.
 */
const LanguageSwitcher: React.FC = () => {
  const { i18n } = useTranslation();
  const { isAuthenticated } = useAuth();
 
  const languages = [
    { code: 'de', label: 'DE — Deutsch' },
    { code: 'en', label: 'EN — English' },
    { code: 'fr', label: 'FR — Français' },
    { code: 'it', label: 'IT — Italiano' },
    { code: 'rm', label: 'RM — Rumantsch' },
    { code: 'es', label: 'ES — Español' },
    { code: 'fi', label: 'FI — Suomi' },
    { code: 'nl', label: 'NL — Nederlands' },
    { code: 'ja', label: 'JA — 日本語' },
  ];
 
  const handleLanguageChange = async (event: React.ChangeEvent<HTMLSelectElement>) => {
    const newLang = event.target.value;
    await i18n.changeLanguage(newLang);
    document.documentElement.lang = newLang;
    localStorage.setItem('batbern-language', newLang);
 
    // Persist to API only if authenticated (backend is ready, Story 2.6)
    Iif (isAuthenticated) {
      try {
        await updateUserPreferences({ language: newLang as UpdatePreferencesRequest['language'] });
        console.log('[LanguageSwitcher] Language preference saved to backend');
      } catch (error) {
        console.error('[LanguageSwitcher] Failed to persist language preference:', error);
        // Continue anyway - localStorage update was successful
      }
    } else {
      console.log('[LanguageSwitcher] Skipping backend save - user not authenticated');
    }
  };
 
  return (
    <div className="flex items-center gap-2">
      <Globe className="h-4 w-4 flex-shrink-0" aria-hidden="true" />
      <select
        value={i18n.language}
        onChange={handleLanguageChange}
        aria-label="Language selector"
        data-testid="language-selector"
        className="min-w-[160px] cursor-pointer rounded-md border border-current/20 bg-transparent px-3 py-1.5 text-sm text-inherit focus:outline-none focus:ring-2 focus:ring-ring/50"
      >
        {languages.map(({ code, label }) => (
          <option key={code} value={code} className="bg-zinc-800 text-zinc-100">
            {label}
          </option>
        ))}
      </select>
    </div>
  );
};
 
export default LanguageSwitcher;