CLI commands
The extension registers two Shopware console commands. nice-translate:run creates a translation job from the shell, and nice-translate:providers reports which providers you configured.
Both commands are available as soon as Shopware installs and activates the extension. Start them from the Shopware project root, like each other bin/console command.
nice-translate:run
Create a translation job and optionally watch its progress.
bin/console nice-translate:run --to=de-DEThe command assembles the same job configuration as the translation wizard and gives it to the message queue. It translates nothing itself.
Options
| Option | Description | Repeatable | Default |
|---|---|---|---|
--entity | The entity to translate, for example product, category, snippet | Yes | product |
--to | The target locale code, for example de-DE, or all for each non-system language | Yes | required, no default |
--from | The source locale code | No | the system language |
--provider | deepl, google, openai, anthropic, gemini, mistral or managed | No | the Default provider setting, otherwise deepl |
--mode | missing fills the empty fields only, all overwrites the existing translations | No | missing |
--scope | all processes each record, missing processes only the records with a minimum of one eligible missing target field | No | all |
--watch, -w | Poll the job and show a progress bar until it finishes | No (flag) | off |
Repeat --entity and --to once for each value: --entity=product --entity=category --to=de-DE --to=fr-FR. Supported content lists the technical entity names that --entity accepts.
The scope selects records, and the mode selects fields. --scope decides which records go into the job. --mode decides whether the run writes a translated field inside those records again.
Validation and error messages
The command stops before it creates a job in these cases:
| Situation | Message |
|---|---|
You gave no --to | Provide at least one target locale, e.g. --to=de-DE (repeatable), or --to=all. |
--mode is not missing or all | Invalid --mode "…". Use "missing" or "all". |
--scope is not all or missing | Invalid --scope "…". Use "all" or "missing". |
--from matches no language | No language found for source locale "…". |
A --to locale matches no language | No language found for locale(s): … |
| The requested targets equal the source | No target languages resolved — the requested locales only match the source language. |
--entity is not a supported content type | The entity "…" is not supported for translation. |
| The provider has no key and no active subscription | … is not configured. Add an API key in the settings first. |
| DeepL or Google cannot map a locale in the run | The locale "…" is not supported by …. |
--to=all resolves to each language in the shop except the system language. The resolved source language always leaves the target set, therefore --from=en-GB --to=all never tries to translate British English into itself.
Options that the command does not expose
--mode is the only job option that the command sets. Everything else keeps the job defaults, which resolve against your settings:
| Behaviour | Value used for a CLI job |
|---|---|
| Protect manual edits | on |
| Skip unchanged content | on |
| Include custom fields | on |
| Apply glossary | on, and also subject to Apply glossary in Settings → Advanced |
| Shorten SEO fields | on |
| Tone and custom instructions | the values from Settings → Providers |
| Field selection | none: each translatable field of the content type, minus the Excluded fields |
| Service tier (managed provider) | Balanced (3 credits per source character) |
If you need a different service tier, or a run without the manual-edit protection, start the job from the wizard. You cannot select individual fields in the wizard either. For that, use options.fields on the job endpoint of the Admin API.
The cost estimates come from the wizard only. A CLI job never gets one.
How the command interacts with the queue
The command writes a Queued job row and dispatches a start message to the low-priority transport of Shopware. The queue workers do the actual translation:
bin/console messenger:consume async low_priority --time-limit=60 --memory-limit=512MThe command prints the id of the new job and a reminder:
The job is processed by the message queue. Make sure workers are running (bin/console messenger:consume).
Two consequences follow:
- Without active workers, the job stays Queued indefinitely, and
--watchnever returns. See Troubleshooting. - If the command cannot dispatch the start message, it is still successful and still prints the job id. The committed Queued row is a durable start marker. The recovery task of the extension dispatches it again on a later tick, if
scheduled-task:runoperates.
--watch
With --watch, the command polls the job row every two seconds and updates a progress bar. After the job reaches a final status, the command prints a summary table with the columns Status, Processed, Failed, Skipped, Total, Characters and Cost:
----------- ----------- -------- --------- ------- ------------ -------------
Status Processed Failed Skipped Total Characters Cost
----------- ----------- -------- --------- ------- ------------ -------------
completed 1240 0 86 1326 412903 10.3226 USD
----------- ----------- -------- --------- ------- ------------ -------------If the job recorded an error message, the command prints it as a warning below the table.
Exit codes: the command returns a failure exit code only when the final status is failed. A job that ends as completed_with_errors or cancelled still exits successfully. A build step that must react to individual record failures must therefore examine the job itself. --watch has no timeout. It waits until the job finishes, or until the job row disappears (The translation job no longer exists., failure exit code).
Examples
Fill the missing German and French translations for products and categories with DeepL, and stay attached to the run:
bin/console nice-translate:run --entity=product --entity=category --to=de-DE --to=fr-FR --provider=deepl --watchA nightly catch-up for everything that is still untranslated, into each language except the system language, with the configured default provider. --scope=missing keeps the job small, because it skips the records that are already complete:
bin/console nice-translate:run --to=all --scope=missingTranslate all product copy from British English into German again with Anthropic Claude, and overwrite the existing German values. The hand-edited translations stay, because the manual-edit protection is on:
bin/console nice-translate:run --entity=product --from=en-GB --to=de-DE --provider=anthropic --mode=allTranslate the storefront snippets into Dutch through modernice All-in-One. A snippet set must exist for the source locale and the target locale, and without them the extension skips the snippets:
bin/console nice-translate:run --entity=snippet --to=nl-NL --provider=managedStart a catch-up for imported categories inside a deployment script, and let the step fail when the job fails:
bin/console nice-translate:run --entity=category --to=all --scope=missing --watchnice-translate:providers
List translation providers and their configuration status.
bin/console nice-translate:providersThe plain output is a table with one row for each registered provider, in registration order:
| Column | Content |
|---|---|
ID | The provider id that you pass to --provider |
Provider | The provider label that the Administration shows |
Configured | yes when a key is stored; for managed, yes means that the subscription is active |
----------- ---------------------- ------------
ID Provider Configured
----------- ---------------------- ------------
deepl DeepL yes
google Google Translate no
openai OpenAI (ChatGPT) no
anthropic Anthropic Claude yes
gemini Google Gemini no
mistral Mistral no
managed modernice All-in-One no
----------- ---------------------- ------------The output also contains the custom providers that another plugin registers. See Custom providers.
--test
bin/console nice-translate:providers --test--test validates the stored credentials against the provider APIs and adds two columns:
| Column | Values |
|---|---|
Credentials | valid or invalid, each with — and the message of the provider when there is one; skipped (not configured) for the providers without a key; error — <message> when the check itself threw |
Quota | <used> / <limit>, or <used> / unlimited when the provider reports no limit, or - when the provider exposes no quota |
Only DeepL and modernice All-in-One report a quota. DeepL returns the characters used and the character limit of the key. The managed provider returns the used credits and the included credits. The extension validates Google Translate, OpenAI, Anthropic, Gemini and Mistral against their model or language listing endpoints, and those endpoints report no quota.
The command tests the keys that you already saved. The Test connection button in Settings → Providers tests the key that the field contains, saved or not.
Permissions and execution context
Console commands operate outside the Administration, in the system context of Shopware. The roles nice_translate.viewer and nice_translate.editor from Permissions (ACL) apply to the Administration and the Admin API. They do not restrict the CLI. Each person with shell access to the shop can create translation jobs.
WARNING
A CLI job has no Administration user as its creator. The Translation job finished Flow Builder trigger therefore carries no mail recipient for these jobs. A Send mail action must address a fixed recipient instead of the job creator. See Events & Flow Builder.
Jobs from the command line appear in Catalogues → AI Translation → Jobs like each other job. They have the same progress, the same error list, and the same Retry failed items and Revert all translations commands.