Building NLP for a Language Most Tools Ignore
The default assumes English
Almost every NLP tool, tutorial, and pretrained model quietly assumes the input is English. Tokenizers are tuned for it, sentence splitters expect its punctuation conventions, and the phrase "state of the art" in a paper almost always means state of the art on English benchmarks. None of that is malicious, it is just where the resources happen to be. But it means the moment you build something for Nepali, you stop being able to grab a library off the shelf and trust the defaults.
I ran into this properly at Inspiring Lab, building a RAG pipeline meant to handle both English and Nepali documents, and again on SajhaKhabar, a Nepali news portal with sentiment analysis, category classification, and summarization built in. Both projects taught me the same lesson from different angles: multilingual is not English plus a translation step bolted on, it changes decisions all the way down.
Tokenization is not a solved problem here
Devanagari script, which Nepali is written in, does not use spaces the way English does to mark every word boundary, and it composes characters from combining marks rather than treating each glyph as a single independent unit. A tokenizer built and tuned against English text handles this badly. Words get split in the middle of a conjunct consonant, or two separate words get merged because there was no space to signal a break where English would expect one.
# naive whitespace split, breaks on conjuncts and compounds
text = "म काठमाडौंमा बस्छु"
tokens = text.split() # not reliable for downstream NLP
What actually worked better was a subword tokenizer trained on a Nepali corpus rather than reused from an English pipeline, specifically one built with SentencePiece so it learns Nepali's own statistical patterns instead of inheriting assumptions from a different language's frequency distribution.
Code switching is the normal case, not the edge case
Real Nepali text on the internet is rarely purely Nepali. Comments, headlines, and casual writing mix Nepali and English constantly, sometimes within the same sentence, sometimes with Nepali written in Roman script instead of Devanagari because that is what phone keyboards default to. A sentiment classifier trained only on clean, monolingual Devanagari text falls apart the moment it sees this, which is most of the time in practice.
Handling it meant treating language detection as a per token problem rather than a per document one, and training on a corpus that actually contained the mixed, messy version of the language people use, not a curated clean version that does not represent what shows up in production.
Embeddings and retrieval across two scripts
For the RAG side, the harder problem was retrieval across languages: a query typed in English needing to retrieve a document written in Nepali, or the reverse. Naive keyword search fails immediately here because the surface forms share almost nothing. This is where dense retrieval earns its complexity: a multilingual embedding model that maps semantically similar text from both languages into the same vector space, so a Nepali document can be the top retrieval result for an English query about the same topic.
We used Elasticsearch for the vector search layer, which meant the retrieval side stayed language agnostic once the embeddings were in place. The harder part was upstream of that: parsing and chunking Nepali PDFs and documents cleanly enough that the embeddings had good input to work with, since a lot of Nepali government and institutional documents are scanned images or inconsistently encoded text rather than clean digital text to begin with.
Translation is a tool, not the whole solution
The obvious shortcut is to translate everything into English, run standard English NLP, and translate results back. It works for some things and quietly fails for others. Machine translation of Nepali still struggles with domain specific vocabulary, and translating a summary generated in English back into natural sounding Nepali often produces something grammatically correct but stilted, missing the idiomatic phrasing a native reader expects.
For SajhaKhabar's summarizer with English translation, the more reliable pipeline turned out to be summarizing in the source language first, then translating the shorter summary, rather than translating the full article first and summarizing the English version. Translating less text meant fewer opportunities for translation errors to compound, and the summary stayed closer to what the original article actually emphasized.
Why this is worth doing anyway
There is no shortcut that gets you an English-tier NLP stack for Nepali by just waiting for someone else to build it. The datasets are smaller, the pretrained models are fewer, and most tooling decisions have to be re-checked rather than assumed. But building for a language that most tools ignore forces a kind of rigor that is easy to skip when everything works out of the box. You end up understanding tokenization, embeddings, and retrieval at a level that using an English default never would have required, and that understanding transfers back to every other language you touch afterward, English included.
A Few Terminal Habits I Built Into My Portfolio
Not a code editor redesign, just a real interactive terminal in the hero, a boot sequence, six actual editor themes, and Ctrl+K search: the habits from how I actually work that ended up in this site.
Building Scraping Pipelines That Don't Fall Over
Retrieval quality starts long before the vector database. Notes on rate limits, deduplication, and the silent failures that make scraping pipelines break in production.
How I Built a RAG Pipeline from Scratch
Building DocuLume taught me that chunking strategy and clean source text matter more than the model on top. A walkthrough using ChromaDB and a local embedding model, including the sqlite gotcha that broke my first deploy.