DEV Community

Jainil Chavda
Jainil Chavda

Posted on

Tablespeak: a menu translator that spells every dish the way the restaurant does

 This is a submission for the Open-Source AI Challenge, Side Hustle theme.

What I Built

Tablespeak is a menu translator for restaurants. You paste a menu in Gujarati, Hindi, English or a mix, pick one of 10 languages, and get a printable menu card.

The part someone would pay for is the glossary. A generic translator guesses dish names. It turns ઊંધિયું into "mixed vegetable curry" and spells khaman three different ways on one menu. With Tablespeak, the owner writes one line per dish:

ઊંધિયું / undhiyu | Undhiyu | Surat's winter specialty: mixed vegetables slow-cooked with green masala

Every matching dish then keeps that exact spelling and description, in every language. Dishes from the glossary get a small turmeric dot on the card, so the owner can see what came from their own dictionary.

The target customer is a small restaurant that wants a menu for tourists, or for staff and customers who read a different Indian language, without paying a translator for every edit.

Live demo: https://tablespeak.vercel.app
Code: https://github.com/Jainil26/tablespeak

How it works

The browser sends the menu and glossary to a small Node server. The server builds a prompt, calls an open-weight model through an OpenAI-compatible API, and returns a menu card. The API key stays on the server, so visitors never see it.

The whole project has zero dependencies: plain HTML, CSS and JavaScript, plus about 100 lines of Node. I built it in two days using Google Antigravity.

Why open models mattered here

I don't own a powerful laptop, so I couldn't run a model locally. Open weights still helped, because they are served by many providers through the same API. I used Qwen 2.5 72B, Llama 3.3 70B and Gemma 3 27B through OpenRouter, and switching between them is a dropdown in the app and one line in the code.

That mattered twice while building:

  1. Free models disappear. Two of my three free model ids started returning 404 partway through, with an error saying the free version was gone. With a closed API that would have meant rewriting the integration. With open models I changed two ids in a config file and kept going.
  2. Models are not equally good in every language. My first Punjabi test came back with English descriptions and English added in brackets next to the Gurmukhi headings. Because I could compare models and control the prompt, I fixed it in two steps: a script-aware prompt that tells the model which writing system to use, and a check on the server that detects when most descriptions are not in the right script and asks the model once more. After that, Punjabi came out correctly.

Other benefits of the open approach:

  • No lock-in. Any OpenAI-compatible endpoint works, so I can change the provider with one environment variable.
  • Private when it needs to be. The same code can point at a local Ollama server on a stronger machine, and a restaurant's menu data would never leave the building.
  • Cheap. A menu is a few thousand tokens, so a translation costs a fraction of a cent. [[ADD your real cost if you checked it on OpenRouter ]]
  • Customizable. The glossary and prompt are plain text, and open weights can be fine-tuned later for one cuisine.

What I learned from comparing models

[[ADD 2-3 honest lines from your own test: which model was best at Gujarati/Punjabi, which kept glossary names most exactly, which invented ingredients, and any speed difference. Even "Qwen was the best default" is fine. ]]

Limitations

  • Output is AI-generated, so the card tells readers to check ingredients and allergens before printing.
  • Open models are stronger in Hindi, Gujarati, Marathi and Bengali than in smaller-resource languages like Malayalam, Kannada and Telugu.
  • It translates menu text, not photos. Uploading a photo of a menu is the next feature I'd add.

Contribute

The repo is open for Hacktoberfest. Good first issues: glossary starter packs for other cuisines, more languages, CSV import and export for the glossary, and tests for the translation logic. Pull requests are welcome.

Thanks for reading!

Top comments (0)