Configuration
Two things configure the CLI: the project on multilocale.com, and a
multilocale.json file in your repository.
multilocale.json
The CLI looks for a multilocale.json anywhere under the working directory
(node_modules and build excluded) and uses the first one it finds.
{
"projectId": "your-project-id",
"organizationId": "your-organization-id",
"format": "json",
"extension": "json",
"paths": ["translations/%lang%.json"],
"header": "",
"postScript": ""
}
Fields
| Field | Type | Description |
|---|---|---|
projectId | string | The Multilocale project every command defaults to |
organizationId | string | Written alongside projectId for reference |
format | string | Output format: json, esm, js, cjs, swift |
extension | string | File extension for translation files |
paths | string[] | Where translation files live, if the project has no paths |
header | string | Text prepended to each generated file |
postScript | string | Shell command to run after the download command (post-script also accepted) |
Committing this file is what keeps CI and agent runs from dropping into the interactive project picker, which needs a TTY. When it is missing and the account has exactly one project, the CLI picks that project and writes the file for you.
There is no projectName field: the CLI reads only projectId from this file.
Pass --project <idOrName> to override it for a single command.
Project paths
paths says where a project's translation files live in your codebase. It is
what download writes to, and what import and unused read from. Each entry
uses %lang% as the placeholder for the language code:
translations/%lang%.json
src/locales/%lang%.json
messages/%lang%.json
Setting them
Set them on the project with the CLI:
# On an existing project
multilocale projects update my-app --paths "translations/%lang%.json"
# Several locations at once
multilocale projects update my-app --paths "messages/%lang%.json,src/i18n/%lang%.json"
# Or at creation time
multilocale projects create my-app \
--locales en,es,fr \
--default-locale en \
--paths "translations/%lang%.json"
paths is a project field, not a dashboard setting — app.multilocale.com has no
form for it. Besides the CLI, it can be set over the REST API by sending paths
to PUT /api/projects/:projectId, or kept per-repository in
multilocale.json.
Which one wins
- the project's own
paths, set withprojects update --pathsor the REST API pathsinmultilocale.json- a default:
translations/%lang%.<extension>— or%lang%.lproj/Localizable.<extension>for theswiftformat
The project's paths overrides the local file, so a repository that wants its
own layout should either leave the project's paths empty or keep the two in
agreement. A new account's first project already carries
["translations/%lang%.json"].
If a path matches nothing, import and unused print
No matching files for path … and locale … rather than failing — that message
names exactly what to fix.
Output Formats
| Format | Description | Default extension | Example output |
|---|---|---|---|
json | Standard JSON | json | { "key": "value" } |
esm | ES module | js | export default { "key": "value" } |
js | CommonJS | js | module.exports = { "key": "value" } |
cjs | CommonJS (alias) | js | module.exports = { "key": "value" } |
swift | Apple .strings | strings | "key" = "value"; |
Reshaping the output
The dictionaries Multilocale writes are flat, one file per locale. If your i18n
runtime wants a different shape — nested namespaces, a generated locale list, a
Lingui catalog — do it in a post-script, which runs after every download:
{
"postScript": "node scripts/normalizeMessages.mjs"
}
Keeping the reshape in a script rather than in Multilocale means the file the
CLI writes stays the file the CLI can read back with import.
Android Projects
For Android projects, the CLI detects AndroidManifest.xml and reads/writes
strings.xml files in the standard resource layout:
res/values/strings.xml # Default language
res/values-es/strings.xml # Spanish
res/values-fr/strings.xml # French
No paths configuration is needed for Android projects.