Configuring languages
The language list is the one setting that decides both what the room can hear and what you pay. Every language you turn on is a live, per-minute translation session the moment the service starts — whether or not anyone is listening to it. This page is how to build that list deliberately.
Updated for v0.6.0-beta.6, with screenshots captured from that release. Room names and settings shown are examples.
Two kinds of "language"
Two different things are called a language here, and they are set in two different places:
- Translation languages — what the speaker's words are turned into. You choose these on the operator page, under Languages (global). Each one is a paid session while it is on. This page is about these.
- The phone's own wording — the buttons and messages on the listener page ("Preferred language", "Tap to listen"). The phone picks this by itself from its OS language, out of the eight the page is written in: English, Spanish, French, Haitian Creole, Portuguese, Swahili, Khmer and Lao. Nothing to configure, nothing billed. When someone picks a preferred translation language that is one of those eight, the page wording follows it too.
There is no per-language on/off on the phone. A phone can only offer what you have turned on.
Add a language
Languages ship off. A fresh install has an empty list and the phones say "No languages are available yet — the service has not been set up." until you add one.
- Open the operator page (
/operator, with your PIN) and find the Languages (global) card, just under API keys. - Tap + Add language. Two menus appear: the provider that will do the translating (Gemini is the default; OpenAI; or your own Local stack) and the language. The list shows the English name, the language's own name and its code, sorted by English name; languages you have already added are hidden from it.
- Tap Add. The new row appears with its box ticked — added languages are on straight away. Untick it if you are only preparing for later.
Every row carries a small tag — gemini, openai or
local — because the provider is chosen per language, not for the
whole room. Spanish on OpenAI and Portuguese on Gemini in the same service is
perfectly normal. The tag cannot be edited: to move a language to another
provider, ✕ remove the row (it asks first) and add it again.
The last entry in the language menu is ➕ Custom…. Type a language code and the language's native name, and the row is created like any other. This is for a language that is not in the built-in list; whether the provider can actually speak it is between you and the provider — see below.
Which languages, which provider
The built-in menu has 45 languages. Not every provider handles all of them, and the menu tells you where it can.
- Gemini (default) — offered for every language in the list. It is also the provider the service prefers for the transcript of what the speaker said, so if you run a mix, at least one Gemini language is a good idea.
- OpenAI — the realtime translation model officially covers a shorter list: Arabic, Chinese, English, French, German, Hindi, Indonesian, Italian, Japanese, Korean, Portuguese, Russian, Spanish and Vietnamese. Pick OpenAI as the provider and the language menu shrinks to those fourteen. Anything else on OpenAI has to go in as a Custom code — allowed, because the provider's list changes faster than ours, but check it with real speech before Sunday.
- Local stack — your own translation server on the LAN or a rented GPU box. Its translator knows several hundred languages, so anything in the menu is accepted; the limit is which voices the stack has installed (the reference build ships voices for en, es, fr, pt and sw, with ht, km and lo as operator-supplied add-ons). Test in Service settings only proves the stack is reachable — it does not check voices.
The provider's own Test button, next to its key in the API keys card, is the ground truth. A language the menu is unsure about, or a Custom code, is proven by hearing it, not by the list.
Turning one on or off
The tick box on each row is not a preference that waits for the next service. It acts immediately, and it acts on the bill:
- While the engine is running, ticking a language opens its translation session within seconds, in the main service and in every running group whose menu includes it. Unticking closes those sessions everywhere at once. So does ✕ Remove.
- While the engine is stopped, the boxes only decide what ▶ Start translating will open: one session per ticked language.
- A ticked language is billed from the moment its session is live until it closes — whether or not any phone has chosen it. The main service does not wait for a listener. Four ticked languages and nobody in the room is still four sessions.
The card's own help (the ? in its corner) puts the arithmetic bluntly: four languages and two running groups can mean twelve parallel sessions. How that turns into dollars, and the auto-stop that guards against a forgotten engine, is on the cost & charging page. The short version for this page: the list should be the languages this room needs today, not every language you might ever need. Untick, don't remove — an unticked row costs nothing and is one tap away next time.
If you tap Start and a language's provider has no key, the language does not silently fail: it is listed under the sessions as "fr · didn't start — missing gemini API key" with a note to add the key and Restart. The other languages start normally.
Languages in groups
A group — a class, a youth room, a breakout — has a language menu of its own, but it is always a subset of the global list. When you create a group, its language boxes start all ticked, which means something specific: the group follows the service list. Add a language globally next month and the group offers it too, without anyone editing the group.
Untick a box in the group and it stops following: it now has a fixed menu of exactly what you left ticked. That is the right choice for a class that only ever needs Spanish while the main hall runs five languages, because each running group opens a session per language on its menu — a follow-all group under a five-language service is five more sessions.
Attendee groups (the ones people create from their phones) are gentler: they open a session for a language only when someone in the group actually picks it. Operator-made groups open theirs at start. Both are covered in setting up and managing groups and private groups.
The speaker's language
Everything above is about the target. The language the speaker
actually talks in is the Speaker’s language row in Service settings, and its
default, auto, is right for almost everyone: the provider works
out what it is hearing.
auto unless detection keeps guessing wrong.Set it to a code (es, pt-BR, ko…) when
a service is entirely in one language and auto-detection keeps drifting — a
heavy accent, lots of proper names, a bilingual speaker who codeswitches. A
fixed source is passed to every provider session, so it applies to every
target language at once. It takes effect when sessions next start; press
Restart if the engine is already running.
Local language detection
Normally the app learns which language is being spoken from the provider's
transcript — which needs a billed session open and arrives a few seconds
late. Local language detection runs a small model on the operator
machine instead: it reacts in about a second and works before the engine is
started, so the "hearing: es" tag on the operator page can be right from the
first sentence. It needs Python with torch and
speechbrain installed on that machine; without them the box does
nothing harmful — the app quietly falls back to the transcripts. It does not
change what is translated, only how quickly the app knows what it is hearing.
Voices & models
Each provider has one row in Service settings: model, voice, and the $/min rate the cost meter uses. The voice is one voice for every language on that provider — you cannot pick a different voice per language.
- OpenAI — model
gpt-realtime-translate, voicealloyby default. Any voice name the model accepts can go in the box. - Gemini — model
gemini-3.5-live-translate-preview, voiceKoreby default. Gemini's prebuilt voices have names like Kore, Puck, Charon, Aoede; the voice's gender is fixed by the name. - Local stack — no voice setting here; the stack uses whatever voice
it has installed for each language. Its row is the
ws://endpoint and a Test button, plus Simultaneous: translate and speak while the person is still talking (about two seconds behind instead of five to nine, at the cost of choppier phrasing). Local stack only.
Model and voice changes apply the next time the engine or a group starts, not to sessions already open. Change them, save, then Restart. The $/min box changes nothing about the audio; it only feeds the running cost estimate on the operator page — set it to what your account is actually billed.
What the phone shows
The phone's first screen has a Preferred language menu at the top. It lists exactly the languages that are currently ticked — unticked and removed languages never reach the phone — using each language's own name (Español, not Spanish). The choice is remembered on the phone, carries into whichever group the person joins, and is pre-selected there if the group offers it. Below the menu come the groups and the main service. The phone reads the list when the page loads, so after you change it, phones that are already open need a reload to see the difference.
Once inside a service, the page is captions first. Audio is off until the person taps "🔇 Audio off — captions only. Tap to listen (use earbuds)"; the earbuds line is there because a phone speaker playing translation into a room feeds the microphone and the translator starts hearing itself. If the service has not been started yet the page says "You're in — waiting for the service to begin…" and picks up on its own when you press Start.
Under the captions there can be a Speak section — "your language will be projected". It appears on the main service only while Allow participants speaking from phones is ticked on the presenter page for that room. Classes have their own saved speaking switch too. What the person says is translated into the same language list and shown on the projector, so a question from the floor reaches everyone; there is nothing extra to enable per language.
The projector
The projector page (/projector) shows captions without audio.
Register a browser display using the corner gear, or enable an attached
screen on This computer. On Playout devices, choose the display’s
room, the languages it shows, its layout and whether the join QR is visible.
It can show the hall or a class, and two screens can split the languages
between them. Its language choices come from its assigned room.
When something's wrong
A language is missing from the phone
The voice is wrong — wrong gender, wrong sound
It's translating into the wrong language
It's mis-detecting what the speaker is saying
auto, the provider
decides what it hears, and a strong accent, a bilingual speaker or a run
of names can tip it. If the whole service is in one language, set Source
lang to that code and Restart — every session then knows what to expect.
Turning on Local language detection makes the operator page's
"hearing:" tag react faster, but it does not tell the provider what to
translate from; Speaker’s language does.One language says "connecting" and never goes live
Captions arrive but there's no audio
Something not covered here? Write to support@lithos.community with the language, its provider tag, and what the session list on the operator page says, and we'll sort it out.