ui-nyla/src/components/UiComponents/VoiceLanguageSelect/VoiceLanguageSelect.tsx
2026-01-29 10:14:33 +01:00

133 lines
4.7 KiB
TypeScript

/**
* VoiceLanguageSelect
*
* Reusable component for selecting voice/speech recognition language.
* Defaults to user's profile language.
* Can be used for speech-to-text, text-to-speech, and translation features.
*/
import React from 'react';
import { useLanguage } from '../../../providers/language/LanguageContext';
import styles from './VoiceLanguageSelect.module.css';
// Voice language options with full locale codes for Google Cloud Speech
export interface VoiceLanguageOption {
code: string; // Full locale code (e.g., 'de-DE')
label: string; // Display label
shortCode: string; // Short code for mapping (e.g., 'de')
flag?: string; // Optional flag emoji
}
// Supported languages for speech recognition
export const voiceLanguages: VoiceLanguageOption[] = [
{ code: 'de-DE', label: 'Deutsch', shortCode: 'de', flag: '🇩🇪' },
{ code: 'de-CH', label: 'Deutsch (Schweiz)', shortCode: 'de', flag: '🇨🇭' },
{ code: 'en-US', label: 'English (US)', shortCode: 'en', flag: '🇺🇸' },
{ code: 'en-GB', label: 'English (UK)', shortCode: 'en', flag: '🇬🇧' },
{ code: 'fr-FR', label: 'Français', shortCode: 'fr', flag: '🇫🇷' },
{ code: 'fr-CH', label: 'Français (Suisse)', shortCode: 'fr', flag: '🇨🇭' },
{ code: 'it-IT', label: 'Italiano', shortCode: 'it', flag: '🇮🇹' },
{ code: 'it-CH', label: 'Italiano (Svizzera)', shortCode: 'it', flag: '🇨🇭' },
{ code: 'es-ES', label: 'Español', shortCode: 'es', flag: '🇪🇸' },
{ code: 'pt-BR', label: 'Português', shortCode: 'pt', flag: '🇧🇷' },
];
// Map user profile language (short code) to default voice language (full code)
const profileToVoiceLanguage: Record<string, string> = {
'de': 'de-DE',
'en': 'en-US',
'fr': 'fr-FR',
'it': 'it-IT',
'es': 'es-ES',
'pt': 'pt-BR',
};
export interface VoiceLanguageSelectProps {
value: string;
onChange: (languageCode: string) => void;
disabled?: boolean;
compact?: boolean; // Compact mode shows only flag/short code
showFlags?: boolean; // Show flag emojis
className?: string;
title?: string;
}
/**
* Get the default voice language based on user's profile language
*/
export const getDefaultVoiceLanguage = (profileLanguage?: string): string => {
if (profileLanguage && profileToVoiceLanguage[profileLanguage]) {
return profileToVoiceLanguage[profileLanguage];
}
return 'de-DE'; // Default fallback
};
export const VoiceLanguageSelect: React.FC<VoiceLanguageSelectProps> = ({
value,
onChange,
disabled = false,
compact = false,
showFlags = true,
className = '',
title = 'Sprache für Spracherkennung',
}) => {
const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
onChange(e.target.value);
};
return (
<div className={`${styles.container} ${compact ? styles.compact : ''} ${className}`}>
<select
className={styles.select}
value={value}
onChange={handleChange}
disabled={disabled}
title={title}
>
{voiceLanguages.map((lang) => (
<option key={lang.code} value={lang.code}>
{showFlags && lang.flag ? `${lang.flag} ` : ''}
{compact ? lang.code.split('-')[0].toUpperCase() : lang.label}
</option>
))}
</select>
</div>
);
};
/**
* Hook to manage voice language state with user profile default
*/
export const useVoiceLanguage = (initialValue?: string) => {
const { currentLanguage } = useLanguage();
// Track if user has manually changed the language
const hasManuallyChanged = React.useRef(false);
// Initialize with user's profile language (or provided initial value)
const [voiceLanguage, setVoiceLanguage] = React.useState<string>(
initialValue || getDefaultVoiceLanguage(currentLanguage)
);
// Update voice language when user profile language changes (only if not manually set)
React.useEffect(() => {
if (!initialValue && !hasManuallyChanged.current) {
const newDefault = getDefaultVoiceLanguage(currentLanguage);
setVoiceLanguage(newDefault);
}
}, [currentLanguage, initialValue]);
// Wrapper to track manual changes
const handleSetVoiceLanguage = React.useCallback((newLanguage: string) => {
hasManuallyChanged.current = true;
setVoiceLanguage(newLanguage);
}, []);
return {
voiceLanguage,
setVoiceLanguage: handleSetVoiceLanguage,
voiceLanguages,
};
};
export default VoiceLanguageSelect;