# Translation coverage board for your app's language files

> One screen showing every text key in every language, what is missing, what went stale, and a button that opens a pull request with the fixes.

- Workflow type: app
- Services: GitHub, DeepL
- Categories: Engineering, Product
- Published: 2026-08-21

## What it does

- Reads the language files straight from your repository and builds a grid with every text key down the side and every language across the top.
- Marks each cell translated, missing, or stale, where stale means the English wording changed after that translation was written.
- Flags any translation where a placeholder like {count} or a piece of inline formatting did not survive, so broken strings never reach a customer.
- Pick a language, press Fill gaps, and a background agent translates only the missing and stale text using your existing brand glossary, then opens a pull request for a native speaker to review.
- Shows your remaining translation character allowance on the page, so you know what each run costs before you start another one.

## What you'll need

- A GitHub account with access to the repository that holds your language files, and permission to push a branch and open a pull request.
- A DeepL API plan, Free or Pro, with an API key.
- Your language files kept in one folder, one file per language, with English as the source.
- Any brand glossary you want applied already set up in your DeepL account. The app reads glossaries you already have; it does not create them.

## Prompt

I want an app my product and engineering team opens every time we ship UI copy, showing how complete the language files in our repository actually are. Nobody on the team should ever be hand editing a locale JSON file to find out what is missing.

The main view is a translation coverage grid. Read our locales folder from GitHub with List Files in a Directory, then call Get a File for each locale file in that folder (en.json, de.json, fr.json, pt-BR.json and so on). Parse each file, flatten nested keys into dotted paths, and build a grid with every translation key from the English source file down the side and every language file across the top. Let me set the repository, the base branch and the locales folder path in app settings, and let me filter the grid by key prefix or by cell state so I can look at just one feature area.

Every cell is one of three states: translated, missing, or stale. Missing means the key exists in the English source file but is absent or empty in that language file. Stale means the English source string changed after that translation was last written. Do not infer staleness from commit timestamps. The app keeps its own stored snapshot of the English value at the moment each translation was produced, and a cell is stale only when the current English value differs from that stored snapshot. Persist a row per key and language holding the translated value, the English snapshot and when it was written, and update it every time the app writes a translation. Keys that already existed in a language file before the app ever touched them have no snapshot, so show those as unverified rather than stale.

Also flag any translation where a placeholder or inline markup did not survive. Compare the English source string and the translated string for interpolation tokens like {count} or {{name}}, ICU plural blocks, and inline HTML or markdown tags. If the set of tokens differs, mark the cell with a placeholder warning and show both strings side by side so someone can see exactly what broke. Put a summary strip above the grid with total key count, coverage percentage per language, and counts of missing, stale and placeholder problems.

Show the DeepL character budget on the page using Check Usage and Limits: characters used, the character limit, and how much is left in the current billing period. Before a fill run starts, estimate the characters it will consume from the length of the strings about to be sent and show that estimate next to the remaining balance, so the team can see what each fill costs before running another one.

Picking a language column and pressing Fill gaps starts a background agent scoped to that one language. The agent first resolves the correct DeepL language code for that file: call List Supported Languages and map the file name to a target code, remembering that target codes accept regional variants like EN-GB, PT-BR and ZH-HANS while the source language is always a base code like EN. Then it loads our brand glossary: call List Glossaries, pick the glossary matching the English to target language pair, and call Retrieve Glossary Entries to read the terms so product terms stay consistent. Treat glossaries as already existing and read only. The app must never offer to create, edit or delete a glossary. If no glossary exists for a pair, say so in the run output and translate without one.

The agent then collects only the missing and stale keys for that language and translates them with Translate Text, passing the glossary id. Translate Text accepts up to 50 strings per request, so batch the keys rather than calling once per key, and keep a stable mapping from each key to its position in the batch so results land back on the right key. Preserve placeholders exactly: keep interpolation tokens and inline tags intact, and re-run the placeholder check on every returned string, holding back anything that comes back broken and reporting it in the app instead of committing it.

When the batch is done the agent writes the result back to the repository. Call List Branches to get the head commit of the base branch, Create a Branch for a new branch such as i18n/fill-de-2026-08-21, merge the new translations into the existing language file content, and write it with Update a File using the blob SHA returned by Get a File. If a language file does not exist yet, use Create a File instead. Then call Create a Pull Request against the base branch, with a body listing how many keys were filled, how many were missing versus stale, which glossary was applied, how many characters were billed, and any strings held back for placeholder problems, so a native speaker reviews it in the normal code review flow instead of a side channel.

The agent's output lands back in the app so the board shows it. Keep a run history with the language, the pull request link and its status, keys filled, characters used, and the strings that were held back. While a run is in progress mark that language column as running, and once the pull request is open show those cells as pending review rather than translated, flipping them to translated when the grid is refreshed after the branch is merged. Give me a Refresh button that re-reads the locale files, and refresh on open. Anyone on the team can open the app, and the run history and stored English snapshots are shared across the whole team rather than per person.

## How to customize

- Point it at a different repository, branch, or language folder, or track more than one repository.
- Choose which languages appear as columns, including regional variants like British English or Brazilian Portuguese.
- Decide whether each Fill gaps run covers missing text only, or missing plus stale, and set the branch name and pull request wording to match your review conventions.

## FAQ

### Do we need a translation management platform for this?

No. The app reads the language files that already live in your repository and writes changes back as a normal pull request, so your source of truth stays in the codebase and reviews happen in code review.

### How does it know a translation has gone stale?

The app stores its own copy of the English wording at the moment each translation was written. When the English string later changes, the stored copy no longer matches and that cell is marked stale. It is a real comparison rather than a guess based on file dates.

### Will it overwrite translations a person already reviewed?

No. A fill run only touches text that is missing or stale for the language you picked. Everything else is left exactly as it is, and the result arrives as a pull request that someone has to approve.

### Does it handle regional languages like Brazilian Portuguese?

Yes. Language files such as pt-BR or en-GB are matched to the matching regional variant when translating, while the English source is read as plain English.

### Can it create a glossary for us?

No. It applies brand glossaries you already have in your DeepL account so product terms stay consistent, and it will tell you when no glossary exists for a language pair rather than making one.

### How do we know what a fill will cost?

The page shows the characters used and remaining in your current billing period, and estimates what a run will consume before you start it.

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