# Find and fix missing Contentful translations in one board

> Your content team opens one board each week, sees exactly which entries are missing German or French, and fills the gaps without leaving the page.

- Workflow type: app
- Services: Contentful, DeepL
- Categories: Marketing, Operations
- Published: 2026-08-21

## What it does

- Lays out every entry as a row and every language as a column, with each cell colour coded so you can see at a glance what is translated, what is missing, and what has gone out of date since the original was last edited.
- Puts a headline count above the grid, like 42 entries missing German and 17 stale in French, with filters by content type, language, and status so you can work one backlog at a time.
- Click any cell to read the original text beside the translation, then hit Translate to fill the gap on the spot. Everything saves as a draft, and publishing is always a separate, deliberate step.
- Tick a whole column of missing cells to translate them in one pass, with the character count shown before the job runs, and use the review button to have a background helper back-translate a finished language and flag anything that drifted.

## What you'll need

- A Contentful account, with access to the space and environment your content lives in
- A DeepL account on either the free or paid API plan
- At least two languages configured in your Contentful space, with one of them set as the default
- Optional: a DeepL glossary listing product and brand names you never want translated

## Prompt

Build me a translation coverage board that my content team opens every week to see which Contentful entries are missing translations and to fill the gaps on the spot. The main surface is a grid with one row per entry and one column per locale, and everything the team needs to act on a gap lives on that one screen.

Build the grid from Contentful. Use List Locales for the column set, and note which locale is marked as the default: that is the source language everything is compared against. Use List Entries for the rows, paging through with skip and limit until you have them all. Use List Content Types to learn the shape of each entry, because that tells you which fields are localized text (Symbol, Text, and RichText fields with localization enabled) and which are not. Only the localized text fields count toward coverage and only those are ever translated.

Colour code every cell as translated, missing, or stale. Missing means the entry has no value for that locale in its translatable fields. Translated means the locale has values for them. Stale is the important one: it means the default-locale text was updated after that locale's version was last written. Contentful does not track per-locale timestamps, so the app has to remember this itself. Whenever the app writes or a user approves a translation, store a record of the entry ID, the locale, a hash or snapshot of the source text at that moment, and the entry's version and updated timestamp. A cell is stale when the current source text no longer matches the snapshot stored for that locale. For entries the app has never touched, take a baseline snapshot the first time you see them and mark them stale once the source moves after that. Persist these records so the board is accurate across sessions and for every member of the team.

Above the grid, give me filters by content type, locale, and status, plus a headline counter that reads like a backlog summary: "42 entries missing German, 17 stale in French". The counter should respect the active filters so the team can narrow to one content type and still see where they stand.

Clicking any cell opens a side panel showing the source text next to the existing translation, field by field, so an editor can compare them directly. When the cell is missing or stale, the panel offers a Translate button. That action sends only the entry's translatable text fields to DeepL Translate Text, then writes the results back into that locale on the same entry using Contentful's Create or Update Entry with ID. Contentful keys field values by locale on the same entry, so this is an update that adds or replaces locale keys on the existing entry, never a parallel entry. Send the current version in the X-Contentful-Version header and handle a version conflict by refetching and retrying rather than clobbering someone else's edit. Always save as a draft: never publish as part of translating, so a human reviews before anything goes live.

Add bulk selection so someone can tick a whole column of missing German cells and translate them in one pass, including a select-all-in-column shortcut that respects the current filters. Before a bulk job runs, show the character count it will consume, taken from the length of the text about to be sent, and put it next to the characters remaining on the plan from DeepL Check Usage and Limits. The team approves the job only after seeing both numbers, so nobody blows through their plan by accident. Run the job with visible progress and a per-entry result, and throttle it: Contentful allows roughly seven requests per second, and DeepL accepts up to fifty strings per translate request, so batch the text and pace the writes.

Let the team attach a DeepL glossary per locale, chosen from a dropdown populated by DeepL List Glossaries, and pass the selected glossary with every translation request so product names stay intact. Use DeepL List Supported Languages to map Contentful locale codes onto DeepL language codes, since they do not match directly: Contentful uses codes like en-US and de-DE, while DeepL wants a base code for the source language and accepts regional variants for the target. Store the mapping so an editor can correct it once if a locale guesses wrong.

Publishing is a separate action from translating. Give me a Publish button that pushes approved locale versions live via Contentful Publish Entry, available on individual entries and on a reviewed selection, and make it clear in the interface that this is the step that reaches the public site.

Add a "review this locale" button that kicks off a background agent for one language. The agent walks the translated entries for that locale, back-translates each one into English with DeepL Translate Text, and compares the result against the original source text. It flags any entry where the meaning drifted, and any entry where a term from the attached glossary got translated when it should have been left alone. The agent writes its findings into a review queue stored in the app, one item per flagged entry with the source text, the translation, the back-translation, and a short plain-English note on what looks wrong. An editor works through that queue from a Review tab, opening the cell in the side panel, and marking each item resolved, retranslating it, or dismissing it as a false positive. Show the queue count as a badge so the team knows there is something waiting.

Two constraints matter throughout. Never translate or modify slugs, IDs, dates, numbers, media, or reference fields: only plain text and rich text fields, and preserve rich text structure so formatting and embedded references survive the round trip. And never publish implicitly: every write the app makes lands as a draft, and only the explicit Publish action makes anything live.

## How to customize

- Choose which content types show up in the board, so the team sees marketing pages and skips configuration entries nobody translates.
- Attach a glossary per language so product names, feature names, and brand terms come through untouched.
- Set how the review helper judges drift, from strict flagging of any wording change to only calling out real changes in meaning.

## FAQ

### Will this publish translations to my live site without me approving them?

No. Every translation the board writes is saved as a draft on the entry, exactly as if someone had typed it into Contentful and not hit publish. Making a translation live is a separate Publish action you choose per entry, so nothing reaches your audience until a person signs off.

### What does a stale translation actually mean?

It means the original text was edited after that language was last written, so the translation is now describing an older version of the content. This is the failure that usually goes unnoticed: the German copy still exists, so most tools show it as done, even though the English moved on weeks ago.

### Will it overwrite translations my human translators already wrote?

Not unless you ask it to. Cells that already have a translation show as done and are skipped by bulk jobs, which only pick up missing and stale cells. You can still open any cell and choose to retranslate it, but that is always a deliberate click.

### Can I stop it from translating our product and brand names?

Yes. You can attach a DeepL glossary to each language, and the board passes it along with every translation so approved terms stay exactly as written. The review helper also flags cases where a protected term got translated anyway.

### How do I avoid burning through my DeepL character allowance by accident?

Before any bulk job runs, the board totals up the characters it is about to send and shows you the number alongside what is left in your current billing period. You approve the job only after seeing both, so a large selection can never quietly drain your plan.

### Does it touch slugs, IDs, or links between entries?

No. The board only ever sends plain text and rich text fields to be translated. Slugs, entry IDs, dates, numbers, media, and references to other entries are left exactly as they are, so your URLs and content relationships do not change.

Use this prompt in General Input: https://www.generalinput.com/prompts/find-and-fix-missing-contentful-translations-in-one-board