Skip to main content

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

FieldTypeDescription
projectIdstringThe Multilocale project every command defaults to
organizationIdstringWritten alongside projectId for reference
formatstringOutput format: json, esm, js, cjs, swift
extensionstringFile extension for translation files
pathsstring[]Where translation files live, if the project has no paths
headerstringText prepended to each generated file
postScriptstringShell 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

  1. the project's own paths, set with projects update --paths or the REST API
  2. paths in multilocale.json
  3. a default: translations/%lang%.<extension> — or %lang%.lproj/Localizable.<extension> for the swift format

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

FormatDescriptionDefault extensionExample output
jsonStandard JSONjson{ "key": "value" }
esmES modulejsexport default { "key": "value" }
jsCommonJSjsmodule.exports = { "key": "value" }
cjsCommonJS (alias)jsmodule.exports = { "key": "value" }
swiftApple .stringsstrings"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.