Inspiration
I did not start from a dataset. I started from the people sitting around me.
My college takes students from every part of the country, and we arrive speaking different mother tongues into the same lecture hall, where everything is delivered in English. I watched classmates who had cleared the same entrance exam I had — who understood the subject perfectly well — fall behind because of the language it arrived in. They would ask me afterwards what the professor had said. Not what a word meant. What the sentence meant.
Then I saw the live interpretation used in parliament, where a speech reaches every member in their own language as it is being spoken, and the question became obvious: a room where decisions get made has this. Why doesn't a room where people are learning?
The idea: a translator that refuses to translate
Here is the part that makes this different from every other translation project.
Point an ordinary translator at a lecture and it renders eigenvalue as अभिलक्षणिक मान — correct, literary, and a word that appears in no textbook, no exam, and no job interview. The student now understands the sentence and cannot answer the question. You made the lecture easier and the degree harder.
So ProfessorTranslate inverts the usual goal. A translator is normally judged on how completely it translates. This one is built to translate the explanation and refuse to touch the vocabulary — because the terminology is the part that transfers to the exam, the interview, the paper, while the improvised sentence that made it land is the part that exists for four seconds and was never written down anywhere.
Professor: "So the eigenvalue of this matrix tells us how much the eigenvector is stretched."
Student: "तो इस matrix का eigenvalue बताता है कि eigenvector कितना stretch होता है।"
|__ Hindi voice __| |English| |__ Hindi __| |__ English __|
The student understands the sentence and still meets \( \lambda \) called by the name their exam will use — in the subtitles, and in a second English voice inside an otherwise Hindi sentence.
What it does
A professor opens a lecture and speaks normally. Every student joins with a code, picks their own language, and — within about a second — reads and hears the lecture in it. One professor, many languages, in the same room at the same time.
- Live translated audio and subtitles, with protected terms highlighted and voiced in English by a second voice.
- Every student picks their own language, switchable mid-lecture. English, Hindi, Bengali and French today.
- Diagrams from the lecture itself — Wolfram renders the plot the lecturer is describing.
- Spoken descriptions of every diagram, translated the same way, so a student who cannot see the board hears what it shows.
- Lectures archived as text, not audio, so a class replays in a language nobody chose that day, at any speed, or through a screen reader.
- A glossary that builds itself from a PDF of last year's notes or a syllabus URL — and that flags subject vocabulary it does not yet protect, mid-lecture, for the professor to accept in one tap.
How I built it
TypeScript end to end. Three npm workspaces — shared, server, web — with the wire protocol defined once in shared and imported by both sides, so a change to a message shape is a compile error rather than a runtime surprise. React + Vite front end, Express + ws server, deployed as a single host on Render so there is no CORS surface and no second service to keep alive.
The core mechanism. Before a sentence reaches the model, every protected term is cut out and replaced by a sentinel — ⟦0⟧, ⟦1⟧. The model translates only the connective tissue between the sentinels and carries each sentinel to wherever the target grammar wants it; the terms are spliced back afterwards. It is not politely asked to preserve vocabulary — it is never given the vocabulary. A prompt can be ignored; an absence cannot.
That unmasking pass returns the sentence already split into runs — { lang, text, isTerm } — which is the only moment the system knows with certainty which characters are term and which are explanation. One data structure then drives two features that would otherwise drift apart: the highlighting in the subtitles and the voice switching in the audio.
Inference runs on Featherless AI (Qwen3-30B-A3B), streamed token by token so the first translated words appear while the sentence is still generating. Speech in and out uses the browser's Web Speech API — deliberately: it runs on the student's own device, free, with no key, so a lecturer can walk into a hall and use this without their institution having provisioned anything. Wolfram|Alpha renders diagrams and Firecrawl reads syllabus pages into the glossary.
On build quality. 100+ assertions across 8 suites, including probes I wrote specifically because ordinary tests were lying to me: a sustained-lecture harness, a latency profiler that breaks the delay into five separately-measured stages, a reliability run that counts term loss across 162 translations, and a register suite that asserts on the output of the prompt. Every number in this write-up has an npm script behind it.
Challenges I ran into
Every symptom pointed at the wrong cause. So I stopped guessing and built probes.
"There is a lot of repetition" — a live test produced "transverse energy transverse energy transverse energy through and". The cause was event.resultIndex in the Web Speech API. It is documented as where new content begins and universally read as "the first result you have not seen". It is neither: it is the first result that changed, and Chrome keeps pointing at a finalised result while it revises what follows. Nine regression assertions now replay that exact event sequence.
"It is skipping lines" — single-sentence tests passed perfectly while real lectures lost words. A sustained-speech probe measured 8.1% of words silently dropped: the segmenter was waiting for punctuation that conversational speech never provides. Now 222 words in, 222 out.
"It is slow" — five measured stages found the culprit somewhere I did not expect: the system prompt. Cutting it from 1560 characters to 353 dropped time-to-first-token from 1209 ms to 586 ms.
"The simulations are not live" — diagrams never rendered. The concurrency gate read inFlight >= limit - 1, which with three student languages is permanently true. One character.
And the hardest, which was not a bug: the translation was too good. The model's default Hindi was flawless, literary, and harder for a student than the English. Real classroom speech is code-mixed — "अब देखते हैं कि determinant zero हो तो क्या होता है" — so the prompt now carries a banned list of Sanskritised coinages, a ban on transliteration, and worked examples, with everyday English loanwords masked by the same sentinel machinery so they survive in English without being marked as technical terms.
User experience decisions I am glad I made
- The professor approves every diagram before it publishes. An unreviewed generated diagram on two hundred screens teaches the wrong thing very efficiently. Generation is automatic; publication is not.
- A
/checkpage that tells a professor whether the room's hardware can do this before the class arrives, instead of failing in front of 200 people. - Suggested glossary terms are one tap, not a form. Anything that costs a lecturer attention mid-sentence will not be used.
- Nobody has to ask. A student joins with the same code as everyone else and picks a language on their own screen. No request, no disclosure, no visible difference.
- Failures are stated, not swallowed. A device with no Hindi voice produces silence; the app detects that and says so.
Accomplishments that I'm proud of
The central claim is measured, not asserted. Clone the repo and reproduce it:
| Term preservation | 0% loss over 162 translations — npm run test:reliability |
| First translated word on screen | ~600 ms — npm run test:latency |
| Words lost from continuous speech | 0 — 222 in, 222 out — npm run test:sustained |
| Automated checks | 100+ assertions across 8 suites |
And that accessibility fell out of the architecture rather than being bolted on: because lectures are archived as text, a screen reader can read back a class delivered entirely by voice, and every diagram carries a spoken description in the student's own language.
What I learned
Constraining the model beat instructing it. Every hour spent making the prompt more emphatic about preserving terminology was worth less than the ten minutes spent making the terminology unreachable.
Fluency is not usefulness. A translation can be perfect by every linguistic measure and still fail the student it was built for.
A test that passes on one sentence tells you nothing about a lecture. Nearly every real bug lived in duration, concurrency, or fragmentation — none of them reachable by a single-shot test. Building the right probe was consistently faster than reasoning about the symptom.
What's next
This is a prototype, not a product, and I would rather say so than have a judge find out. It runs, it is measured, and it has not yet faced a real class — a mistranslated sentence costs a student more than no translation would. The next step is one supervised pilot in a real lecture, not more features.
After that: animated demonstrations instead of static plots; generated video for concepts a plot cannot carry; spoken definitions protected like terms; glossaries built from photographs of the board; more languages, and instruction in languages other than English; and cloud speech recognition as an option for noisy halls and strong accents.
Built With
- accessibility
- express.js
- featherless-ai
- firecrawl
- node.js
- qwen
- react
- render
- speech-to-text
- tailwindcss
- text-to-speech
- typescript
- vite
- web-speech-api
- websockets
- wolfram-technologies
Log in or sign up for Devpost to join the conversation.