# Translation coverage board for your Contentful locales

> See every entry against every locale in one grid, spot what is missing or out of date, and have an agent draft the gaps for human review.

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

## What it does

- Builds one grid of your Contentful entries against every locale in the space, with each cell marked translated, missing, or stale.
- Marks a translation stale when the source language was edited after that locale was last touched, so quietly outdated copy stops passing as done.
- Shows a coverage percentage per locale along the top and filters by content type, so you can audit just blog posts or just product pages.
- Opens any cell beside its source language for inline editing, and has a Draft translations button that sends an agent to write the missing values and file a Linear review ticket.

## What you'll need

- A Contentful account with access to the space you want to audit
- More than one locale set up in that space, with one of them treated as your source language
- A Linear workspace if you want review tickets filed for drafted translations
- A list of terms that should never be translated, such as product names, brand names, and feature names

## Prompt

I want an app that gives me one screen for translation coverage across my Contentful space. Right now there is no single view of which locales are done, stale, or missing, so coordinating a global launch means opening entries one at a time. The people who live in this app are our localization manager and the content ops team.

The main surface is a coverage grid. Rows are entries, columns are locales. Build it from Contentful List Locales for the columns, List Content Types to label and filter rows, and List Entries for the rows themselves, paging through with skip and limit until every entry is loaded. Contentful stores localized fields keyed by locale code, so fields.title has an en-US key, a de-DE key, and so on, and each cell state comes from reading those per-locale keys on the entry.

Each cell reads as one of three states. Translated means the entry has non-empty content for that locale across its localized fields. Missing means those per-locale keys are absent or empty. Stale means the translation exists but the source locale was updated after that translation was last touched, so compare the entry sys.updatedAt and the source locale field content against when that locale's values last changed. Color the three states distinctly and make the legend obvious, because stale is the state people currently miss entirely.

Along the top of each locale column, show a coverage percentage: the share of the entries currently in view that are fully translated for that locale. The percentage should respond to the filters, so filtering to Blog Post shows blog coverage rather than whole-space coverage. Give me a content type filter, a filter to show only rows with gaps, and a search box for entry titles.

Clicking a cell opens a detail view beside the grid. Load the entry with Get Entry and show the source locale fields on the left and the target locale fields on the right, field by field, so I can see what I am translating from. The target side is editable and I can save inline. Saving writes back with Create or Update Entry with ID, sending the entry's current version in the X-Contentful-Version header. If Contentful returns a 409 version mismatch because somebody else edited the entry, refetch the entry, tell me my copy is out of date, and let me retry rather than silently overwriting their work.

Add a Draft translations button that works on a single entry from the detail view and on a filtered batch from the grid. It kicks off a background agent. The agent reads the source locale fields for each selected entry, drafts the missing locale values in the right tone and roughly the right length for the field it is filling, so a short heading stays short and body copy keeps its structure, then writes the drafts back with Create or Update Entry with ID as unpublished field values on the existing entry.

When the agent finishes a run, it files a review ticket in Linear with Create Issue against a team I pick from List Teams, assigned to the reviewer who is a native speaker of that locale, resolved from Linear List Users. The issue body lists the entries and locales that were drafted and links back to the entry in Contentful and to the matching cell in this app, so the reviewer lands in the right place.

Two rules are non-negotiable. The agent never publishes anything; every draft lands unpublished so a human reviews it before it goes live, and the app should say so plainly wherever drafting is offered. Second, keep a configurable glossary of do-not-translate terms, meaning product names, brand names, and feature names, and the agent must reproduce those terms verbatim in every locale instead of translating them.

Persist the settings the app needs: which locale is the source of truth, which content types are in scope, the do-not-translate glossary, the mapping from locale code to Linear reviewer, and the default Linear team. Also keep a short run history so the board can show which cells the agent recently drafted and which ticket is tracking them, and mark those cells as awaiting review rather than plain translated. Respect Contentful's rate limit of roughly seven requests per second when loading a large space, and back off on a 429 rather than hammering it.

## How to customize

- Choose which locale is the source of truth, and which content types show up on the board.
- Edit the do-not-translate glossary at any time so brand and product names stay identical in every language.
- Pick the Linear team that review tickets land in, and map each locale to the reviewer who speaks it.

## FAQ

### Will the agent publish translations automatically?

No. Every value the agent writes lands as an unpublished draft in Contentful. A person still has to read it and hit publish, so nothing reaches your live site without human review.

### What makes a translation count as stale?

A cell is stale when the source language content was edited more recently than that locale's version was last touched. It means the translation exists but no longer matches what the source now says.

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

Yes. You keep a glossary of do-not-translate terms, and the agent reproduces them exactly as written in every language instead of translating them.

### Do I need Linear to use this?

No. The coverage board, the side-by-side editor, and the drafting agent all work on their own. Linear is only used to file a review ticket for each batch of drafts, so you can skip it if your reviewers work somewhere else.

### Will it work with a space that has dozens of locales?

Yes. The coverage percentages along the top let you see which languages are behind without reading the whole grid, and the content type filter narrows the board to the entries you actually care about.

### Can I still translate things by hand?

Yes. Clicking any cell opens that entry next to its source language so you can write or fix the translation yourself and save it straight back to Contentful.

Use this prompt in General Input: https://www.generalinput.com/prompts/translation-coverage-board-for-your-contentful-locales