# How FluidVoice Handles Different Languages: A Complete Technical Guide

> Discover how FluidVoice handles different languages technically. Learn about VoiceEngineLanguageCatalog, model routing, and pipeline application for multilingual speech recognition.

- Repository: [ALTIC/FluidVoice](https://github.com/altic-dev/FluidVoice)
- Tags: technical-guide
- Published: 2026-08-16

---

**FluidVoice manages multilingual speech recognition through a central `VoiceEngineLanguageCatalog` that defines language metadata, generates model-specific routes, and applies user selections to the transcription pipeline.**

The [FluidVoice](https://github.com/altic-dev/FluidVoice) iOS application supports dozens of languages across multiple speech-to-text engines including Apple Speech, Whisper, Cohere, Nemotron, and Parakeet. This article examines the complete architecture—from language definitions through UI selection to provider-level execution—based on the actual source code implementation.

---

## The VoiceEngineLanguageCatalog: Central Language Registry

All language handling in FluidVoice originates in [[`VoiceEngineLanguageCatalog.swift`](https://github.com/altic-dev/FluidVoice/blob/main/VoiceEngineLanguageCatalog.swift)](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/Persistence/VoiceEngineLanguageCatalog.swift). This file contains three critical responsibilities: static language definitions, route generation for available models, and persisting user selections.

### Language Definitions Structure

The catalog maintains a comprehensive list of supported languages through the `languageDefinitions` property. Each language carries:

- **`id`** – unique identifier (e.g., `"en"`, `"es"`, `"ja"`)
- **`displayName`** – localized human-readable name
- **`aliases`** – alternative names for search matching
- **`isPopular`** – flag for prominent UI placement

```swift
// Conceptual representation based on implementation patterns
struct LanguageDefinition {
    let id: String
    let displayName: String
    let aliases: [String]
    let isPopular: Bool
}

```

The catalog exposes convenience accessors for different UI contexts:

```swift
// Retrieve all languages with at least one compatible model route
let allLanguages = VoiceEngineLanguageCatalog.allLanguages()

// Get prominently displayed languages for onboarding
let popularLanguages = VoiceEngineLanguageCatalog.popularLanguages()

// Search with normalized query matching against name, ID, and aliases
let searchResults = VoiceEngineLanguageCatalog.searchableLanguages(query: "espanol")

```

---

## LanguageBinding: Mapping Languages to Speech Engines

The inner **`LanguageBinding`** enum defines how each speech engine consumes language information. This abstraction allows the same language definition to route differently depending on the target provider.

| Binding Type | Behavior | Example ID |
|-------------|----------|-----------|
| **`automatic`** | Engine infers language from audio | `whisper-automatic` |
| **`appleSpeech`** | Uses Apple-specific locale identifier | `apple-speech-en-US` |
| **`cohere`** | Explicit language code for Cohere API | `cohere-en` |
| **`nemotron`** | Explicit language code for Nemotron API | `nemotron-es` |
| **`whisper`** | Explicit language code for Whisper model | `whisper-fr` |

*Reference: [`LanguageBinding` enum definition](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/Persistence/VoiceEngineLanguageCatalog.swift#L19-L38)*

Each binding generates a unique route identifier through its `id` computation, ensuring no collisions between different engine-language combinations.

---

## Route Generation: Building Compatible Pipelines

The **`routeCandidates(for:)`** method transforms a language definition into actionable transcription pipelines. This function evaluates:

1. **Model availability** – whether Parakeet V3, Cohere, Nemotron, or Whisper support the language
2. **Apple Speech compatibility** – checking both modern analyzer locales and legacy speech recognition locales
3. **User preference eligibility** – filtering to routes actually usable by installed models

```swift
// Generate all possible routes for a specific language
if let japanese = VoiceEngineLanguageCatalog.language(id: "ja") {
    let candidates = VoiceEngineLanguageCatalog.routeCandidates(for: japanese)
    
    // candidates might include:
    // - Whisper-japanese (automatic or explicit)
    // - Nemotron-japanese
    // - Apple Speech with ja-JP locale
}

```

The returned `[VoiceEngineLanguageRoute]` objects encapsulate both the language and the specific binding required by each engine. Routes are then filtered against `SettingsStore.shared.availableModels`, ensuring only operational pipelines are presented to users.

*Reference: [`routeCandidates` implementation](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/Persistence/VoiceEngineLanguageCatalog.swift#L31-L66)*

---

## Persisting Selections: The Apply Mechanism

Once a user selects a language-route combination, **`apply(_:, to:)`** commits the choice to persistent storage. This method:

1. Extracts the `LanguageDefinition` and `LanguageBinding` from the route
2. Updates `SettingsStore.shared.selectedLanguage`
3. Sets the appropriate model-specific language property (e.g., `selectedWhisperLanguage`, `selectedNemotronLanguage`)
4. Triggers transcription engine reconfiguration

```swift
// Apply a selected route to configure the transcription pipeline
let selectedRoute: VoiceEngineLanguageRoute = /* user selection */
VoiceEngineLanguageCatalog.apply(selectedRoute)

```

The `SettingsStore` persists these values across app launches and makes them observable for real-time UI updates.

*Reference: [`apply` method](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/Persistence/VoiceEngineLanguageCatalog.swift#L15-L30)*

---

## UI Integration: Onboarding and Language Selection

FluidVoice's onboarding flow surfaces language selection through [[`WelcomeView.swift`](https://github.com/altic-dev/FluidVoice/blob/main/WelcomeView.swift)](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/UI/WelcomeView.swift) and [[`OnboardingTryoutStepView.swift`](https://github.com/altic-dev/FluidVoice/blob/main/OnboardingTryoutStepView.swift)](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/UI/OnboardingTryoutStepView.swift).

### WelcomeView Language Interface

The welcome screen presents:

- **Popular languages** as tappable cards for immediate selection
- **Search interface** querying `searchableLanguages(query:)` with debounced input
- **Full language list** for manual browsing

```swift
// Simplified representation of WelcomeView language selection
struct LanguageSelectionSection: View {
    @State private var searchQuery = ""
    
    var body: some View {
        if searchQuery.isEmpty {
            PopularLanguagesGrid(
                languages: VoiceEngineLanguageCatalog.popularLanguages()
            )
        } else {
            SearchResultsList(
                languages: VoiceEngineLanguageCatalog.searchableLanguages(query: searchQuery)
            )
        }
    }
}

```

*Reference: [WelcomeView language UI section](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/UI/WelcomeView.swift#L667-L775)*

### Try-It-Out Flow

After language selection, [`OnboardingTryoutStepView`](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/UI/OnboardingTryoutStepView.swift) displays example prompts in the chosen language and initiates a test transcription. This validates that the selected route functions correctly before completing onboarding.

*Reference: [OnboardingTryoutStepView examples and flow](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/UI/OnboardingTryoutStepView.swift#L6-L35)*

---

## Provider-Level Language Execution

Individual speech engines consume the persisted language settings through model-specific properties in [[`SettingsStore.swift`](https://github.com/altic-dev/FluidVoice/blob/main/SettingsStore.swift)](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/Persistence/SettingsStore.swift). The **`NemotronProvider`** exemplifies this pattern:

```swift
// NemotronProvider checking and applying language configuration
func setTargetLanguageIfNeeded() async throws {
    let targetLanguage = SettingsStore.shared.selectedNemotronLanguage
    
    // Only update if language actually changed
    if currentLanguage != targetLanguage {
        try await apiClient.setLanguage(targetLanguage)
        currentLanguage = targetLanguage
    }
}

```

Similar patterns exist across [`WhisperProvider`](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/Services/WhisperProvider.swift), [`CohereProvider`](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/Services/CohereProvider.swift), and the Apple Speech integration. Each provider maps the generic `LanguageDefinition` to engine-specific parameters.

*Reference: [NemotronProvider language switch implementation](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/Services/NemotronProvider.swift#L471-L473)*

---

## Adding New Language Support

The modular architecture enables straightforward language expansion:

1. **Add definition** – append to `languageDefinitions` in [`VoiceEngineLanguageCatalog.swift`](https://github.com/altic-dev/FluidVoice/blob/main/VoiceEngineLanguageCatalog.swift)
2. **Declare model support** – update `routeCandidates(for:)` to include new language-model combinations
3. **Configure provider mappings** – ensure each relevant provider can consume the new language code

No UI changes are required unless the language qualifies for the "popular" designation.

---

## Summary

- **`VoiceEngineLanguageCatalog`** serves as the single source of truth for language metadata and routing
- **`LanguageBinding`** abstracts engine-specific language consumption patterns
- **`routeCandidates(for:)`** dynamically generates compatible transcription pipelines
- **`apply(_:, to:)`** persists selections to `SettingsStore` for cross-session retention
- **Onboarding UI** leverages catalog search and popular language APIs for intuitive selection
- **Provider implementations** execute language-specific configuration at runtime

---

## Frequently Asked Questions

### How does FluidVoice detect which languages are available on a device?

The catalog filters `routeCandidates` against `SettingsStore.shared.availableModels`, which reflects installed transcription engines and their capabilities. Apple Speech availability additionally checks `SFSpeechRecognizer.supportedLocales()` at runtime.

### Can FluidVoice automatically detect spoken language without user selection?

Yes. The **`LanguageBinding.automatic`** option enables Whisper and other models to infer language from audio content. This route appears in candidate generation when the underlying model supports auto-detection.

### What happens when a selected language has no compatible models?

The `allLanguages()` and `popularLanguages()` methods pre-filter to languages with at least one viable route. If model availability changes (e.g., via in-app purchase or update), the catalog automatically adjusts presented options.

### How are language names localized for different UI languages?

The `displayName` property in `LanguageDefinition` returns localized strings through the standard iOS localization infrastructure. Aliases support cross-language search—entering "espanol" matches Spanish regardless of device language.