This walks the whole loop once: create a package, get the source strings in, translate them, and get the files back out.
The App has no uploader. Files arrive through the project, and only then can they be imported.
.json language files.Name them so the language is recognisable. All of these are understood automatically:
en.jsonen.common.json — language firstcommon.en.json — language lastlocales/fr-BE/common.json — language from the folderThe detected language is only a suggestion; you confirm it before anything is written.
.json files.common exports back to common.json.Repeat for each source file. A package with three source files has three namespaces.
On the package page, click Add language and pick a code
(fr, fr-BE, pt-BR, zh-Hant…).
Each language gets its own card with a progress bar.
If you already have partial translations, import those files the same way as in step 3 — choose the target language instead of the source one. Keys that do not exist in the source language are reported and skipped rather than invented.
Click Translate on a language card to open the editor.
Each row is one key: its name, the source text, the field you type into, and its status. The tabs across the top filter by status and show a live count for each: All, Untranslated, Outdated, Draft, Translated, Reviewed.
AI results are saved as Draft and carry a small sparkle icon. Read them, fix what needs fixing, select them and click Confirm draft. Nothing exports as finished work until a person has confirmed it.
If a translation loses or gains a placeholder, the row turns red and says exactly what is wrong — for example Placeholder mismatch — Missing: %s. The row stays unsaved so you can fix it; the other rows in the same save go through normally.
This is the App's most important rule. A missing %1$s is not a typo, it is a
crash in the application being translated.
A user with the review permission can select rows and click Mark as reviewed. Reviewed is the top status and is what a "this language is finished" claim should mean.
The clock icon on a row shows every change ever made to that string: the old value, the new value, who did it, when, and whether it came from a person, the AI, an import or GitHub. Any previous value can be restored.
Upload the new source file to the project and import it again. The preview will report:
Translators then work the Outdated tab, which is exactly the list of what drifted.
By default, untranslated keys are left out of the export so the application falls back to its own source language — a missing key renders as English, an empty string renders as a blank label. You can change this per package.
locales/{locale}/{namespace}.json.Pull from GitHub fetches the matching files, saves each one into the project's Files, and imports them — the same path a file you upload yourself takes.
Push to GitHub commits the selected languages as one commit.
If someone edited those files in the repository since the last sync, the push stops and lists every file that moved, with a link to each. To continue you must tick "I understand this will overwrite the changes made in the repository". Your version then replaces the repository content, and the acknowledgement is recorded in the package history with your name, the time and the resulting commit.