I Tackled the Planet of Lana Language Challenge by Building an AI Translator & Voice Synthesizer A developer has built NovoGen, an open-source translator and speech synthesizer for the fictional language Novo Terali from the game Planet of Lana. The project combines linguistic rules extracted from the official Language Companion booklet with an LLM extrapolation engine and acoustic voice synthesis, and is designed to work offline or scale on serverless infrastructure. I tackled the challenge in a different way, and created this project as my answer. When the indie studio Wishfully released the official Language Companion booklet PoL LanguageCompanion.pdf for Planet of Lana II: Children of the Leaf , they ended it on page 13 with an irresistible invitation to the community: "Congratulations, you’ve reached the end of this intensive crash course in Novo Terali We hope you’ve enjoyed learning a bit more about Lana’s native tongue, and that your understanding of Novo as a whole has deepened in the process. Now that you are completely fluent, we would love to hear from you in your best Novo Terali Share a short or long shoutout in your new favorite language on social media and tag us @planetoflana - we can’t wait to see it " Most players reading that would string together three words from the mini-glossary—like "Tiai Lana " "Hello Lana " —tweet it with a screenshot, and call it a day. I couldn't stop there. The booklet provided around 80 canonical vocabulary words, basic commands, pronouns, numbers, and a handful of translated game scenes. But how can anyone truly be "fluent" when whole swathes of everyday vocabulary and grammar are still undiscovered? Instead of just posting a one-line tweet, I asked myself: What if anyone could translate anything into Novo Terali? What if we could reverse-engineer the linguistic rules from the booklet, marry them with an LLM extrapolation engine, back it with an acoustic voice synthesizer, and build a living, self-healing codex that speaks the language in real time? That question led to NovoGen — an open-source, full-stack conlang translator, speech synthesizer, and dictionary manager for Planet of Lana . Here is the story of how it was engineered, the technical hurdles encountered along the way, and what it takes to bring a fictional language to life with modern web and AI technologies. In the Planet of Lana universe, Novo Terali literally "New Speak" was created on Earth as an accessible auxiliary language designed to unite humanity during the multi-generational Fata te Cora "Seed and Leaf" space mission. Centuries later, on the planet Novo, survivors preserved and evolved it into the melodic dialect spoken by Lana, her sister Elo, and the villagers of Tailo. Before writing a single line of backend code, I extracted and analyzed every rule documented in the booklet: ┌──────────────────────────────────────────────┐ │ NOVO TERALI PHONOTACTICS │ ├──────────────────────────────────────────────┤ │ Vowels: a ah , e eh , i ee , │ │ o oh , u oo pure Italian │ │ Diphthongs: ai, ia, ea, oa, ui unclipped │ │ Consonants: t/d aspirated, rolled 'r', │ │ 'h' voiced, no silent letters │ │ Stress: Light stress on first syllable │ │ Rhythm: Calm, melodic, even pacing │ └──────────────────────────────────────────────┘ -em : Plural/verbal inflection -ari : Agent/actor noun suffix oti- : Honorific or co-prefix One core design philosophy was that NovoGen must never depend exclusively on third-party cloud APIs. If a user runs it offline without an API key, it should function seamlessly using local compute. If deployed to production, it should scale on serverless infrastructure. ┌───────────────────────────────┐ │ Next.js App Router │ │ Tailwind / Vanilla CSS │ └───────────────┬───────────────┘ │ POST /api/translate │ ┌───────────────▼───────────────┐ │ In-Memory Rate Limiter │ │ Sliding-Window, 30 req/min │ └───────────────┬───────────────┘ │ ┌───────────────▼───────────────┐ │ Multi-Tier Translation Engine │ └───────────────┬───────────────┘ │ ┌───────────────────────────┼───────────────────────────┐ │ │ │ 1. Exact SQLite Match 2. Rule Agglutination 3. LLM Extrapolation Canonical Lore DB Suffixes & Modifiers Gemini 3.1 / Ollama │ │ │ └───────────────────────────┼───────────────────────────┘ │ ┌───────────────▼───────────────┐ │ Phonotactic Quarantine Guard │ │ Anti-Gibberish Verification │ └───────────────┬───────────────┘ │ ┌───────────────▼───────────────┐ │ ElevenLabs Voice API │ │ Gigi Voice Model Tuning │ └───────────────────────────────┘ Because the canonical dictionary has only ~80 terms, users translating sentences like "Look at the ancient machine in the forest" require new vocabulary. If you give an LLM free rein, it will hallucinate English words with random accents or invent sounds that violate the fictional world's phonotactics. To solve this, I designed a multi-tier fallback system : novo dictionary.db seeded directly from the companion booklet , return it immediately with is canonical = 1 . llama3.2 or mistral using an ironclad conlang system prompt: js // System instruction excerpt enforced during translation const CONLANG PROMPT = You are the official linguistic translator for Novo Terali from Planet of Lana. Follow these inviolable phonotactic constraints: 1. Every vowel is strictly: a ah , e eh , i ee , o oh , u oo . 2. No consonant clusters exceeding 2 consonants; never use 'x', 'q', or 'z'. 3. Extrapolated roots MUST use open syllables CV or CVC patterns like 'talo', 'suni', 'kora' . 4. Compound from known roots where possible e.g., 'machine' - 'meka-fata' . 5. Canonical vocabulary is SACRED: Never overwrite 'Tiai' Hello , 'Cora' Child/Leaf , etc. Return strictly structured JSON containing translation, IPA phonetics, and grammar breakdown. ; When an extrapolated word is generated, it is tagged as extrapolated and cached in SQLite so that subsequent translations remain 100% consistent across sessions. Once the app went online, a new vulnerability emerged: cache pollution via keyboard mashing . If someone types "leftofkfmv" or "asdfghjkl" , the LLM would dutifully attempt to coin a poetic Novo Terali term for it, saving garbage into the shared SQLite dictionary. To combat this without adding perceptible latency, I built a two-stage Linguistic Quarantine Layer src/lib/validator.ts : / a-z \1{2,}/i . / bcdfghjklmnpqrstvwxz {4,}/i , exempting valid sequences like Set