DEV Community

Jakub
Jakub

Posted on

78 tarot cards x 5 languages: the content pipeline nobody warns you about

Last week I shipped Tarotas, a tarot reading app that supports five languages from day one. Czech, English, Polish, Slovak, German. 78 cards in each. That's 390 card objects, and each card carries a name, upright meaning, reversed meaning, a set of keywords, and a one-paragraph description. Multiply it out and you're looking at roughly 2,000 individual text fields.

I didn't translate them by hand. Obviously.

The source language problem

My first instinct was to write everything in English and translate outward. Wrong call. Tarot has deep roots in specific traditions, and the English terms aren't always the "canonical" ones across languages. The Czech name for The High Priestess is "Velekněžka," and if you translate back from English you get something slightly off.

So I wrote the Czech versions first (that's the language I think in), then generated the other four from Czech as source. This sounds backwards if you're used to EN-first localization, but it meant the source text had the most nuance and the translations could be validated against it.

AI translation with a trust boundary

I used Claude for the bulk translations. The pipeline was dead simple: feed it the Czech card object as JSON with all fields, ask for the target language, get back a JSON object with the same structure. One card at a time, not batched, because batching 78 cards in one prompt led to skipped fields and hallucinated keywords.

The prompt looked like this:

Translate this tarot card from Czech to {lang}.
Keep the JSON structure identical.
For the card name, use the standard tarot name
in {lang} tradition.
For keywords, translate meaning not words.
Enter fullscreen mode Exit fullscreen mode

That last line matters. "Nový začátek" in Czech literally means "new beginning," but the German tarot tradition might use "Aufbruch" (departure, setting out) for the same card. I wanted the AI to pick the term a German tarot reader would actually recognize.

Where the human still wins

I didn't review all 2,000 fields. That would defeat the purpose. Instead I set up three checkpoints:

  1. Card names. I manually verified every Major Arcana name (22 cards x 5 languages = 110 fields). These are the ones people actually search for and would notice if wrong.

  2. Reversed meanings spot-check. Reversed card meanings are where AI gets creative. "Stagnation" becomes "creative blockage" becomes "spiritual paralysis" if you don't catch it early. I checked 10 random Minor Arcana per language.

  3. Keyword deduplication. The AI sometimes generates near-synonyms as separate keywords. "Love" and "romance" on the same card, that kind of thing. I wrote a quick script to flag cards where two keywords had high semantic similarity.

Total human review time: about 4 hours. For 2,000 fields across 5 languages, I can live with that.

The storage side was simple. Postgres (via Supabase), one row per card-language pair:

create table cards (
  id uuid primary key,
  card_number int not null,
  arcana text not null,
  suit text,
  lang text not null,
  name text not null,
  meaning_upright text,
  meaning_reversed text,
  keywords text[],
  description text,
  unique(card_number, lang)
);
Enter fullscreen mode Exit fullscreen mode

390 rows. No joins for a card lookup: where card_number = X and lang = Y. The app reads the browser language or the user's explicit choice, passes it as a parameter, done. If I ever add language number six, it's 78 inserts and zero schema changes.

What it actually cost

The AI translation ran about $3 in API calls. 390 requests, a few hundred tokens each. The human review: 4 hours of my time spread over two evenings. The keyword dedup script: 30 minutes to write, ran in under a second.

I got quotes for professional tarot translation. $0.08 to $0.12 per word, because it's a niche. At roughly 50 words per card across all fields, that's 78 x 50 x 5 x $0.10 = about $1,950. For a product that has 37 visitors so far. Nope.

The AI route isn't flawless. I'm sure a native Polish tarot reader could find something to nitpick. But "mostly right with a clear correction path" beats "can't afford to ship multilingual at all" every single time.

Content scaling with AI is maybe 10% prompting and 90% knowing where the AI will screw up. For tarot, that's proper nouns (card names vary between traditions) and nuanced spiritual terminology (reversed meanings). For your domain, it'll be something completely different. But the pattern holds: translate structured data one object at a time, validate the high-stakes fields manually, accept "good enough" for the rest.

I shipped five languages in a week. The app is live at tarotas.com. It's early, it's small, and I still can't guarantee the German keywords are perfect. But 390 content units are out in the world instead of sitting in a "someday we'll translate" backlog forever.

Jakub, builder @ Inithouse

Top comments (0)