Skip to content

.translations.json Reference

.translations.json lives at the root of any repo that uses your-last-translation-tool. It declares one or more translation projects in the repo, each with its own locales directory and source language.

Copy this into your repo root to get started:

{
"projects": [
{
"name": "web",
"localesDir": "apps/web/locales",
"sourceLanguage": "en"
}
]
}

FieldRequiredTypeDescription
$schemanostringOptional advisory schema URL. Validation is by Zod, not the JSON Schema.
projectsyesProject[] (≥ 1)Every translation project the repo ships.

Unknown top-level fields are ignored (forward compatibility).


FieldRequiredDefaultNotes
nameyesHuman label, unique within the file. Shown in the UI.
localesDiryesPath relative to the repo root (e.g. apps/web/locales).
sourceLanguageyesThe language used by developers in code (e.g. en).
fileStructureno{lang}/{namespace}.jsonMVP supports only this value.
format.typenojsonSerialization format. Only json is supported in MVP.
format.nestednofalseIf true, keys nest into objects. If false, flat with keySeparator.
format.keySeparatorno.Separator for flat keys (matches i18next default).
plurals.enablednotrueToggle plural awareness in the editor.
plurals.suffixesnoi18next CLDR (see below)The set of plural suffixes the editor recognizes.
validation.placeholdersno["{{name}}", "{name}"]Placeholder formats checked for round-trip presence.
validation.allowHtmlnotrueIf false, target translations with HTML tags are flagged.
branchPrefixnotranslations/Prefix for new translation branches created by the app.
languageNamesno{}Human labels per language code (e.g. "uk": "Українська").

Unknown per-project fields are ignored.


You do not declare languages in .translations.json. The app scans <localesDir>/* and treats every subfolder matching the BCP 47 pattern as a language:

apps/web/locales/
en/ ← detected
uk/ ← detected
pt-BR/ ← detected
_archive/ ← ignored (doesn't match pattern)
README.md ← ignored (not a directory)

To add a new language, create the folder. No config change needed.


The defaults match i18next 23.14.0 CLDR conventions:

["_zero", "_one", "_two", "_few", "_many", "_other"]

Override with plurals.suffixes if your codebase uses different conventions.


{
"$schema": "https://stape.io/schemas/translations-v1.json",
"projects": [
{
"name": "web",
"localesDir": "apps/web/locales",
"sourceLanguage": "en",
"branchPrefix": "translations/web/"
},
{
"name": "marketing-site",
"localesDir": "apps/marketing/i18n",
"sourceLanguage": "en",
"languageNames": {
"uk": "Українська",
"pt-BR": "Português (Brasil)"
}
}
]
}

The schema is enforced with Zod on app load. Field-level errors surface with JSON-pointer paths (e.g. projects[0].localesDir) so you can jump straight to the offending key. Unknown fields pass through silently.


If you open a repo without .translations.json, the in-app wizard collects the required fields and writes the file to your working tree. It does not run git add, git commit, or git push — those happen through the PR flow.