Update - what shipped, and where it went further than this ticket.
Delivered in #108. Two things in the description below were true when it was written and are not any more, kept in place so the reasoning stays readable rather than silently rewritten:
- The language set is 28, not six. Six was the ceiling of the previous ASR. The backend has since moved to Deepgram Nova-3, which streams 28 - including Russian, Polish, Korean, Ukrainian, Czech and Thai, none of which the old one reached. The rule is unchanged: the picker never offers a language the ASR cannot hear, and a code an older backend does not know is resolved back to English there rather than faked.
- Neither control locks while the assistant runs. This ticket asked for the language picker to lock, on the reasoning that the language is fixed once the ASR sockets open. That turned out to be the wrong call in the same way for both controls: an interview that switches language, and a headset that dies mid-answer, are precisely the cases these controls exist for, and neither is one the candidate can prepare for by restarting - restarting clears the transcript and the suggestion history. The language picker reconnects both sockets (a second or two of gap, announced before the user commits); the microphone swap reconnects nothing, because the device feeds the worklet rather than being a connection parameter. Only the Model control still locks.
The app only works for an interview conducted in English, and there is no way to say otherwise.
Language in src/renderer/types/config.ts has exactly one member:
export enum Language {
English = 'en',
}
RuntimeConfig.language defaults to 'en' and is read by nothing. It is not sent on any request, it is not on the ASR WebSocket URL, and no control surfaces it. A candidate interviewing in Spanish gets an English speech model transcribing Spanish audio - which does not error, it returns confident English words that were never said - and then a suggestion answering the question that mis-transcription invented.
What to add
Make language a real setting and thread it through the three places that decide what language the session runs in.
- Fill out
Language (see the set below) and give it display metadata: English name plus endonym, since a user who has the app in the wrong language recognises "Deutsch" faster than "German".
- A Language control on the control bar, next to Audio and Model - it shapes the input (which speech model transcribes) and the output (what language suggestions come back in), so it belongs with the other two session inputs rather than with the presentation toggles.
language on the live, action and summarize request bodies.
?language= on the ASR streaming WebSocket URL.
The language set
Six: English, Spanish, German, French, Portuguese, Italian. That is what AssemblyAI's universal-streaming-multilingual model covers - superseded, see the update above: 28, the set Deepgram Nova-3 streams. The reason stands either way: offering a language in the picker that the transcription cannot deliver would be worse than not offering it.
Details that decide whether this is usable
The control locks while the assistant is running. Superseded, see the update above. The premise - that a mid-session change would visibly do nothing until restart - was wrong: setLanguage() reconnects the sockets, so the change does land. The Audio control was unlocked for the same reason and does not even need a reconnect. Only Model still follows getDisabled(runningState).
- The current language has to be readable without opening anything. A globe icon alone means the control is only useful to someone who already knows what it is set to; the bar shows the code (
EN, ES) next to it.
- A stored language the build no longer knows about must fall back to English, not be sent verbatim to the backend and the ASR.
- A client that sends no language must keep working. The field is defaulted on the backend, so the wire stays backward compatible in both directions.
Not in scope
Localising the app's own chrome - buttons, labels, dialogs, toasts. That is a separate feature with a separate cost (roughly 45 components and every main-process error string), and it is not what makes the product unusable in Spanish today: an English button on a Spanish interview is an inconvenience, an English transcript of Spanish speech is a wrong answer read out loud. This ticket is the second one.
The app only works for an interview conducted in English, and there is no way to say otherwise.
Languagein src/renderer/types/config.ts has exactly one member:RuntimeConfig.languagedefaults to'en'and is read by nothing. It is not sent on any request, it is not on the ASR WebSocket URL, and no control surfaces it. A candidate interviewing in Spanish gets an English speech model transcribing Spanish audio - which does not error, it returns confident English words that were never said - and then a suggestion answering the question that mis-transcription invented.What to add
Make
languagea real setting and thread it through the three places that decide what language the session runs in.Language(see the set below) and give it display metadata: English name plus endonym, since a user who has the app in the wrong language recognises "Deutsch" faster than "German".languageon the live, action and summarize request bodies.?language=on the ASR streaming WebSocket URL.The language set
Six: English, Spanish, German, French, Portuguese, Italian. That is what AssemblyAI's- superseded, see the update above: 28, the set Deepgram Nova-3 streams. The reason stands either way: offering a language in the picker that the transcription cannot deliver would be worse than not offering it.universal-streaming-multilingualmodel coversDetails that decide whether this is usable
The control locks while the assistant is running.Superseded, see the update above. The premise - that a mid-session change would visibly do nothing until restart - was wrong:setLanguage()reconnects the sockets, so the change does land. The Audio control was unlocked for the same reason and does not even need a reconnect. Only Model still followsgetDisabled(runningState).EN,ES) next to it.Not in scope
Localising the app's own chrome - buttons, labels, dialogs, toasts. That is a separate feature with a separate cost (roughly 45 components and every main-process error string), and it is not what makes the product unusable in Spanish today: an English button on a Spanish interview is an inconvenience, an English transcript of Spanish speech is a wrong answer read out loud. This ticket is the second one.