So I was building an e-commerce app some time back. I set up i18n, translated all the UI strings, added a language switcher and everything. I thought I was done.
Then a friend in Japan opened it and sent me a screenshot.
The buttons were in Japanese. The navigation was in Japanese. But every single product name and description was in English. It was coming straight from the database. I had translated the UI but the actual content that users care about was still English.
That's when I realized this is a problem every app has and nobody has actually solved it properly.
What I built
supabase-lingo is an npm package that auto-translates your Supabase database content into 10 languages using the Lingo.dev SDK.
It happens automatically the moment data enters your database.
No manual steps. No batch jobs. No changes to your existing schema.
npm install supabase-lingo
How it works
You mark any column in your Postgres schema as @translatable using a column comment:
COMMENT ON COLUMN products.name IS '@translatable';
COMMENT ON COLUMN products.description IS '@translatable';
shell
Then you run one command:
npx supabase-lingo init
plaintext
That's it. Under the hood supabase-lingo does these things:
- Scans your DB for @translatable columns
- Creates a shadow
_lingo_translationstable so your original tables are never touched - Sets up Postgres triggers on your tables
- Deploys a Supabase Edge Function
- Wires everything together
After that every time you insert a row, the trigger fires, the Edge Function calls the Lingo.dev SDK, and your content gets translated into 10 languages automatically.
The shadow table approach
A lot of translation tools modify your original schema by adding columns like name_ja and name_de. That gets messy very quickly.
supabase-lingo keeps a completely separate _lingo_translations table instead:
table_name | row_id | column_name | locale | value
products | uuid | name | ja | ランニングシューズ
products | uuid | name | ar | أحذية الجري
products | uuid | name | hi | रनिंग शूज़
shell
The CLI
The package comes with a CLI so you can see what is happening:
npx supabase-lingo scan # find @translatable columns
npx supabase-lingo init # set up triggers and shadow table
npx supabase-lingo translate # bulk translate existing rows
npx supabase-lingo status # translation coverage per language
shell
The status command is my favorite. It shows a progress bar per language:
products
ja ████████████████████ 100%
ar ████████████████████ 100%
hi ████████████████████ 100%
de ████████████████████ 100%
Why Lingo.dev
Google Translate works okay for simple words. But for product descriptions with technical terms it sometimes gives weird results. Lingo.dev gives more natural translations especially for languages like Japanese and Arabic where context matters a lot.
The SDK was also easy to integrate. One API call can translate an entire object at once which made the batch translation in the CLI fast and simple.
The live demo
I built a React storefront to show the whole thing working. You can add a product in English and watch it show up in Japanese, Arabic, Hindi, German, French, Spanish, Chinese, Korean, Portuguese and Russian automatically.
Live demo: https://supabase-lingo-demo.vercel.app
GitHub: https://github.com/ShivamChavan01/supabase-lingo
npm: https://npmjs.com/package/supabase-lingo
What I want to build next
Some things I did not get to finish during the hackathon week:
- Auto re-translate when source content is updated.
- A dashboard UI showing translation status across the whole project.
- Support for more databases beyond Supabase.
- Webhook notifications when translations are done.
Final thought
The i18n ecosystem has good tools for translating UI strings. But nobody was solving the database content layer. Every marketplace, every e-commerce app, every content platform has this problem right now.
If you are building on Supabase and shipping to international users, give supabase-lingo a try. It is open source, MIT licensed and live on npm.
Top comments (0)