Automation reference and cookbook

The Automation add-on runs declarative workflows using existing Weblate operations. This page describes the workflow structure, triggers, conditions, and actions. See Cookbook for complete examples, including Apply translation memory before machine translation.

Workflow definition

Added in version 2026.10.

Parametrii

Nume

Required

Type or allowed values

version

Yes

1

triggers

Yes

List of (object); maximum items 100; unique items

conditions

No

List of (condition); maximum items 100

actions

Yes

List of (action); maximum items 100

Enter YAML or JSON in the add-on’s Workflow field. The API accepts the same structure as the workflow member of configuration. The JSON Schema describes this representation independently of the editor. Unknown keys are rejected.

version identifies the workflow schema version, not the Weblate release. List the events to subscribe to in triggers, conditions that must pass before any action runs in conditions, and the ordered operations in actions. Omitting conditions is equivalent to an empty list. Empty triggers allows manual execution only; empty actions performs no operations.

Literal settings and expressions

Action settings are literal YAML/JSON values. Only the value of an expression condition is evaluated as CEL. Queries, engine IDs, labels, and other settings do not support CEL expressions, variable substitution, or template syntax such as {{ unit.id }}. A query containing that syntax is not expanded. Use Choose to select actions with different fixed settings. Actions select strings using their scope and optional query.

String scope

Set scope on an action to choose its starting selection. component is the default and retains the existing component-wide behavior. trigger uses the unit affected by a change event; a source-unit change selects its corresponding target-language units. result:ID uses units actually changed or given new suggestions by an earlier action with that id. Set settings.q to filter the selected units further. For trigger and result:ID, omitting q selects the whole scope.

For example, a translation action with id: machine and scope: trigger can be followed by a bulk edit with scope: result:machine. The second action sees only units affected by the first. Source-level edits can select the corresponding target units in a later action.

Workflows using scope: trigger can declare only change triggers. A change without a unit, or a manual run without change context, fails if execution reaches that action. A result:ID action fails if its referenced action did not run, for example because a branch was skipped. Preview marks result scopes as conditional because earlier actions have not run.

Selections are kept only while the run is active. The activity log records affected counts and scoped unit counts (before the q filter), but does not store the full unit ID lists.

Execution context

CEL conditions can access the following fields. Context is captured when the run is scheduled, and only results changes between actions. In particular, unit.state is a snapshot; use matching_strings for current database state. Timestamps are strings, not CEL timestamp objects.

Context fields

Domeniul

Type

Meaning

component.id

integer

Target component ID; always present.

component.slug

string

Target component slug.

component.project

string

Project slug, not a project object.

component.category

string or null

Category slug; null for an uncategorized component.

language.id

integer

Event language ID, when language is available.

language.code

string

Event language code, when language is available.

unit.id

integer

Event unit ID, when unit is available.

unit.state

integer

Captured string state; see String states.

unit.source

string

Source text, truncated to 4,096 characters.

unit.target

string

Target text, truncated to 4,096 characters.

change.id

integer

Triggering change ID, when change is available.

change.action

integer

Numeric ActionEvents value, not the lowercase event name.

change.timestamp

string

Change timestamp in ISO 8601 format with a timezone offset.

actor.id

integer

Recorded actor ID, when actor is available.

actor.username

string

Recorded actor username.

trigger.name

string

Trigger identifier such as change, daily, or manual.

trigger.timestamp

string

Change timestamp, or scheduling time for other triggers; ISO 8601 with a timezone offset.

trigger.revision

string or null

Component local revision recorded when scheduled; null if unavailable.

trigger.unit_ids

list of integers or null

Currently a one-element list when the change references a unit; otherwise null.

trigger.source_unit_ids

list of integers or null

Source-unit IDs corresponding to trigger.unit_ids; otherwise null.

results

object

Initially empty; maps action IDs to successful operation outputs.

Availability depends on the trigger:

  • change supplies change. It supplies unit and language only when the change references them, and actor from the change’s user or, if absent, its author. Any of those optional objects can be null.

  • manual supplies actor when initiated by a user through the UI or API. Other manual entry points may have no actor. change, unit, and language are null.

  • daily, component_update, post_update, post_commit, and post_push have null actor, change, unit, and language.

  • A preview with a change ID uses that change’s context and trigger.name of change. Without one, it uses manual context.

When an object is null, its child fields cannot be accessed directly. For example, use unit != null && unit.state == 10 or language != null && language.code == "de". Prefer the typed unit_state, language, and change_action conditions when possible; they handle missing context and event-name conversion for you. See Translate after source changes.

Execution identity and permissions

The usual add-on management permission authorizes configuration, preview, and manual execution. actor records who caused an event; it does not select the account or permissions used to perform actions. Changing a condition on actor only determines whether the workflow runs.

Operations execute with the add-on’s authority within its configured scope, not with the triggering user’s individual translation permissions. Automatic translation receives the Automation add-on bot as its execution user and does not apply per-user operation permission checks. Reused translations can retain their original author attribution. Bulk editing calls the shared operation without a user, rather than impersonating the recorded actor. The activity context retains the actor separately from translation change attribution.

Before a queued run executes, Weblate checks that the add-on is still valid and the component still belongs to its scope. The queued definition and event context are snapshots: editing the workflow after scheduling does not change that run. Operation settings are validated again against the target component at execution.

Testing and execution

Use Preview without changes to validate a workflow and inspect its conditions and planned actions. Inherited automations require a preview component ID. An optional change ID supplies event context and must belong to that component. Preview neither calls translation services nor changes strings. Conditions that depend on unexecuted action results or changed strings are marked unknown, and their branches are shown as conditional. Use Run now for real execution. The Suplimente provides equivalent preview and run operations.

Runs use ordinary Celery tasks and existing operation locks. Separate runs may overlap; there are no execution modes or parallel action blocks. The activity log records the definition, context, conditions, actions, and failures. An error stops later actions without rolling back completed work. Runs are not automatically replayed; after a worker is forcibly terminated, a pending log can remain and must be inspected before manually starting another run. Changes originating from an automation, including follow-up tasks, do not start other automation runs.

Validation and limits

Workflows must contain JSON-compatible values with string mapping keys. YAML aliases, explicit tags, duplicate mapping keys, non-finite numbers, and native YAML date/timestamp values are rejected. Quote a date if a string is intended. Unknown fields are rejected, and action IDs must be unique across the entire workflow, including mutually exclusive branches. Missing required fields and wrong value types are errors; for example, state must be an integer, not "10". Nested mappings and lists also have a structural depth limit of 32.

Generated parameter tables show list limits, uniqueness requirements, numeric bounds, and string patterns from the schema. Item constraints in parentheses apply to each list element. The workflow-wide node and nesting limits below still apply even when each individual list is within its limit.

Definitions are limited to 64 KiB both as submitted and as ASCII-escaped JSON after operation defaults are applied, 100 action/condition nodes, and eight nesting levels. CEL expressions are limited to 4,096 characters and evaluated in a helper process with two seconds of CPU time and five seconds of wall time per invocation. The helper also limits virtual address space to 512 MiB except on macOS, where no memory cap is enforced. The helper fails closed if a required operating-system resource limit cannot be applied. The pinned CEL runtime provides native wheels; Linux installations require a supported glibc platform. No runtime settings or separate service are required. Use Add-on de scriere for unrestricted custom Python logic on self-hosted installations.

Declanșări

Each trigger is an object in the workflow’s triggers list. An instance can subscribe to multiple triggers. Manual execution is always available, even when manual is absent from the list.

daily

Parametrii

Nume

Required

Type or allowed values

trigger

Yes

"daily"

Runs on Daily, respecting BACKGROUND_TASKS.

component_update

Parametrii

Nume

Required

Type or allowed values

trigger

Yes

"component_update"

Runs on Component update, after Weblate updates the component.

post_update

Parametrii

Nume

Required

Type or allowed values

trigger

Yes

"post_update"

Runs on Repository post-update.

post_commit

Parametrii

Nume

Required

Type or allowed values

trigger

Yes

"post_commit"

Runs on Repository post-commit.

post_push

Parametrii

Nume

Required

Type or allowed values

trigger

Yes

"post_push"

Runs on Repository post-push.

manual

Parametrii

Nume

Required

Type or allowed values

trigger

Yes

"manual"

Runs when an administrator selects Run now, or requests manual execution through the Suplimente.

change

Parametrii

Nume

Required

Type or allowed values

trigger

Yes

"change"

events

Yes

List of (Event name from Selected change events); minimum items 1; unique items

Subscribes to the selected Selected change events. Use lowercase ActionEvents names with underscores, for example source_change or new_source_repo. These distinguish edits in Weblate from uploads and repository imports; source_change alone does not cover all three. Only changes associated with a component can start a run.

Conditions

Every condition in a list must pass. A false workflow-level condition skips the run. Conditions can also select a Choose branch. Conditions concerning unavailable language, unit, or change context return false. An empty condition list passes.

expression

Parametrii

Nume

Required

Type or allowed values

condition

Yes

"expression"

value

Yes

string; maximum length 4096

Evaluates value as CEL and requires a boolean result. CEL supports arithmetic, comparisons, standard functions, and comprehensions, but cannot call Python or access the database, network, or filesystem. Expressions can use the captured execution context and outputs of earlier actions, for example results.machine.updated > 0. Missing fields or expression errors fail the run.

component_category

Parametrii

Nume

Required

Type or allowed values

condition

Yes

"component_category"

value

Yes

string; maximum length 4096

Compares the triggering component’s category slug with value.

language

Parametrii

Nume

Required

Type or allowed values

condition

Yes

"language"

value

Yes

string; maximum length 4096

Compares the event’s language code with value. This tests the trigger context; it does not restrict subsequent actions to that language. Use an action’s search query to restrict the strings it processes.

matching_strings

Parametrii

Nume

Required

Type or allowed values

condition

Yes

"matching_strings"

value

Yes

string; maximum length 4096

Passes when the component currently contains at least one string matching the search query in value. The query runs when the condition is evaluated, so it can observe changes made by earlier actions.

change_action

Parametrii

Nume

Required

Type or allowed values

condition

Yes

"change_action"

value

Yes

Event name from Selected change events

Compares the triggering change’s action with value. Use the lowercase event name, as for change.

unit_state

Parametrii

Nume

Required

Type or allowed values

condition

Yes

"unit_state"

value

Yes

0, 10, 11, 12, 20, 30, 100

Compares the triggering unit’s captured state with the integer value. It uses the event snapshot, not a new query of the unit after earlier actions.

and

Parametrii

Nume

Required

Type or allowed values

condition

Yes

"and"

conditions

Yes

List of (condition); maximum items 100

Passes when every nested condition passes. Evaluation stops at the first false condition. An empty list passes.

or

Parametrii

Nume

Required

Type or allowed values

condition

Yes

"or"

conditions

Yes

List of (condition); maximum items 100

Passes when any nested condition passes. Evaluation stops at the first true condition. An empty list does not pass.

not

Parametrii

Nume

Required

Type or allowed values

condition

Yes

"not"

conditions

Yes

List of (condition); maximum items 100

Negates exactly one nested condition. Empty lists and lists containing multiple conditions are invalid.

Actions

Actions run in list order. Each operation and its batched checks finish before the next action starts. Actions target the component; use Searching for strings queries to narrow them. Queries are evaluated when each action executes.

Optional unique action IDs expose outputs as results.<id>. An ID starts with a lowercase letter and contains up to 64 lowercase letters, digits, or underscores. After a successful operation, its output is stored in the activity log and, when it has an ID, in results.<id> for later CEL conditions. For example, results.memory.updated > 0 tests whether the memory action reported updates. Outputs belong to the current run and are not shared with other runs.

Skipped, failed, and previewed operations do not create result entries. If an action might be skipped, guard access with a presence check such as has(results.memory) && results.memory.updated > 0. A failed operation records an error in the trace and stops later actions; its partial changes are not rolled back. Actions without IDs still record their outputs in the activity log.

The YAML examples below are items to place in the workflow’s actions list. The cookbook provides complete workflow definitions.

Settings and queries are validated against the target component before execution. For inherited workflows, labels must exist in each target project and selected engines must be enabled there.

Traducere automată

Added in version 2026.10.

Parametrii

Nume

Required

Type or allowed values

action

Yes

"weblate.automatic_translation"

id

No

string; pattern ^[a-z][a-z0-9_]{0,63}$

scope

No

"component", "trigger", string; pattern ^result:[a-z][a-z0-9_]{0,63}$

settings

Yes

object

settings.mode

No

"suggest", "translate", "fuzzy", "approved"

settings.q

No

string; maximum length 4096

settings.auto_source

No

"others", "mt"

settings.component

No

integer or null; minimum 1

settings.engines

No

List of (string; maximum length 4096); maximum items 100

settings.threshold

No

integer; minimum 1; maximum 100

Result fields

Nume

Required

Type or allowed values

component

Yes

integer

updated

Yes

integer

message

Yes

string

warnings

Yes

List of (string; maximum length 1024); maximum items 20

warnings_omitted

Yes

integer; minimum 0

Runs Traducere automată synchronously. auto_source: others reuses translations from other components, optionally restricted by the source component ID. auto_source: mt uses the service IDs in engines; translation memory and AI services use the same mechanism as other providers.

Defaults are auto_source: others, mode: suggest, q: state:<translated, threshold: 80, no source component restriction, and an empty engine list. For a scoped action, omitted q selects its whole scope instead. Provide configured engine IDs when selecting mt.

mode selects suggestions (suggest), translations (translate), strings needing editing (fuzzy), or approved translations (approved). Approval follows each language’s effective review settings. threshold is a minimum score from 1 to 100 for services; each service has its own maximum score.

Example

Apply local translation memory matches scoring at least 95 to strings still needing translation. Enable Memorie de traducere Weblate in the target project before running this action.

- action: weblate.automatic_translation
  id: memory
  settings:
    auto_source: mt
    engines: [weblate-translation-memory]
    threshold: 95
    mode: translate
    q: "state:<translated"

See Apply translation memory before machine translation to follow this pass with a remote translation service.

Outputs

component (integer)

ID of the component processed, not the optional source component.

updated (integer)

Number of translation updates or new suggestions reported across the component’s languages. In suggestion mode, this counts newly created suggestions, not strings whose translation state changed. A translation that exceeds the string’s maximum length can also become a suggestion, even in translation mode. Zero means the operation reported no updates; it is not an error by itself.

message (string)

Human-readable completion summary in English. Use updated for conditions instead of parsing this message.

warnings (list of strings)

Warnings reported by automatic translation, or an empty list when none were reported. At most 20 messages are retained, each truncated to 1,024 characters. A successful action can still have warnings; inspect them when fewer strings were translated than expected.

warnings_omitted (integer)

Number of warning messages omitted beyond the first 20. This does not count characters removed from retained messages.

For example, a successful run might record:

{
  "component": 42,
  "updated": 3,
  "message": "Automatic translation completed, 3 strings were updated.",
  "warnings": [],
  "warnings_omitted": 0
}

A later condition can access these fields through results.memory, for example results.memory.updated > 0 && size(results.memory.warnings) == 0.

Bulk editing

Added in version 2026.10.

Parametrii

Nume

Required

Type or allowed values

action

Yes

"weblate.bulk_edit"

id

No

string; pattern ^[a-z][a-z0-9_]{0,63}$

scope

No

"component", "trigger", string; pattern ^result:[a-z][a-z0-9_]{0,63}$

settings

Yes

object

settings.q

No

string; maximum length 4096

settings.state

No

integer

settings.add_flags

No

string; maximum length 4096

settings.remove_flags

No

string; maximum length 4096

settings.add_translation_flags

No

string; maximum length 4096

settings.remove_translation_flags

No

string; maximum length 4096

settings.add_labels

No

List of (string; maximum length 4096); maximum items 100

settings.remove_labels

No

List of (string; maximum length 4096); maximum items 100

Result fields

Nume

Required

Type or allowed values

component

Yes

integer

updated

Yes

integer

Uses the same operation as Editare în masă. For component scope, q is required and selects strings using Searching for strings. For trigger and result scopes, q is optional and filters the selected strings. state sets an integer string state, or leaves it unchanged with -1 (the default).

String states

State values

Valoare

Meaning

Accepted as a bulk-edit target

-1

Leave unchanged

Yes; default, not an actual unit state

0

Empty

No

10

Necesită editare

Yes

11

Needs editing (needs rewriting)

Yes

12

Needs editing (needs checking)

Yes

20

Tradus

Yes

30

Aprobat

Yes

100

Doar în citire

No

The unit_state condition accepts actual unit states, including 0 and 100, but not -1. Bulk editing only changes eligible editable strings; selecting a read-only string does not make it editable.

Flags and labels

Flag settings are strings containing flags to add or remove. Label settings are lists of label names. Flag defaults are empty strings and label defaults are empty lists. Source flags and labels affect all languages, just as with the bulk-edit add-on; translation flags affect the matching translations, excluding source strings. Removing a translation flag removes its local setting; inherited flags remain in effect.

Use comma-separated flags, with colon-separated parameters, for example add_translation_flags: "max-length:100, check-glossary". To remove a parameterized flag, specify its name, for example remove_translation_flags: "max-length". See Personalizarea comportamentului cu ajutorul stegulețelor for quoting rules and Controale de calitate for available checks. Labels use YAML/JSON lists of existing project label names, for example add_labels: [needs-attention]; this does not create a label.

Example

Mark currently translated German strings as needing editing, leaving other languages and approved strings outside the query unchanged:

- action: weblate.bulk_edit
  id: marked_for_edit
  settings:
    q: "language:de AND state:translated"
    state: 10

See Run an action only when a translation pass updates strings for a conditional bulk-edit example.

Outputs

component (integer)

ID of the component processed.

updated (integer)

Count reported by the bulk-edit operation. State changes, changes to source flags or labels, and changes to translation flags contribute separately. When an action combines these operations, the same string can contribute more than once; this is not a count of distinct affected strings. Source flag and label changes are counted per source string, rather than once per language. Zero means the operation made no changes.

For example, an action that only changes the states of three strings returns:

{"component": 42, "updated": 3}

A later condition can test results.marked_for_edit.updated > 0. This output does not contain unit IDs or a list of the changed strings. A later action must select its strings with its own query.

Sequence

Added in version 2026.10.

Parametrii

Nume

Required

Type or allowed values

sequence

Yes

List of (action); maximum items 100

Groups an ordered list of actions. A sequence finishes before the next sibling action starts. It can contain operations, further sequences, and Choose blocks. It does not introduce parallel execution.

Example

Group two translation passes: reuse other components first, then apply local translation memory to strings still needing translation.

- sequence:
    - action: weblate.automatic_translation
      id: reused
      settings:
        auto_source: others
        mode: translate
        q: "state:<translated"
    - action: weblate.automatic_translation
      id: memory
      settings:
        auto_source: mt
        engines: [weblate-translation-memory]
        threshold: 95
        mode: translate
        q: "state:<translated"

Outputs

A sequence has no output object and does not accept an id. Its successful child actions expose their individual outputs in the shared results object, including to subsequent children and actions outside the sequence. In this example, those entries are results.reused and results.memory; there is no combined update count. A failing child stops the remaining actions.

Choose

Added in version 2026.10.

Parametrii

Nume

Required

Type or allowed values

choose

Yes

List of (object); maximum items 100

choose[].conditions

Yes

List of (condition); maximum items 100

choose[].sequence

Yes

List of (action); maximum items 100

default

No

List of (action); maximum items 100

Evaluates branches in order and executes the first branch whose conditions all pass. Each branch requires both conditions and sequence. Later branches are skipped after a match, even if the matching sequence is empty.

If no branch matches, default runs. Omitting default is equivalent to an empty action list.

Example

For components in the frontend category, mark translated German strings as needing editing. Other components take the empty default branch.

- choose:
    - conditions:
        - condition: component_category
          value: frontend
      sequence:
        - action: weblate.bulk_edit
          id: frontend_edit
          settings:
            q: "language:de AND state:translated"
            state: 10
  default: []

See Run an action only when a translation pass updates strings for a branch that uses an earlier action’s output instead of the component category.

Outputs

A choose block has no output object and does not accept an id. Only successful operations in the selected branch or default branch create result entries. Branch conditions and skipped actions are recorded in the activity trace. In this example, results.frontend_edit exists only if the category matches and the bulk edit succeeds. A later condition can safely check has(results.frontend_edit) && results.frontend_edit.updated > 0. Preview records planned or conditional actions, without creating their outputs.

Cookbook

Apply translation memory before machine translation

Use separate automatic translation actions to give one source priority over another. This example first applies local translation memory matches scoring at least 95, then asks DeepL to translate only strings still needing translation.

Enable Memorie de traducere Weblate and configure DeepL in the target project’s Sugestii automate. Install the Automation add-on and enter this workflow:

version: 1
triggers:
  - trigger: component_update
  - trigger: daily
actions:
  - action: weblate.automatic_translation
    id: memory
    settings:
      auto_source: mt
      engines: [weblate-translation-memory]
      threshold: 95
      mode: translate
      q: "state:<translated"
  - action: weblate.automatic_translation
    id: machine
    settings:
      auto_source: mt
      engines: [deepl]
      threshold: 80
      mode: translate
      q: "state:<translated"

The first action finishes before the second action selects its strings. Both use mode: translate, so a successful first-pass translation no longer matches state:<translated and is not sent to DeepL by the second action. Existing translated or approved strings are excluded from both passes. Untranslated strings and strings needing editing are eligible; use state:empty in both actions if only untranslated strings should be processed.

Each threshold applies only to its action. Set the memory threshold to 100 to accept only exact matches, or lower it to accept less similar matches before trying the remote service. Machine translation scores are service-specific: choose a threshold no higher than the service’s documented maximum score. Replace deepl with another configured service ID to use a different provider, including an AI service.

Keep one engine per action when the order matters. Putting both IDs in one engines list uses the existing Priority of machine translation and translation memory services, not the list order. To try additional providers, append another action with its own engine, threshold, and the same query. To reuse translations from other Weblate components first, prepend an action using auto_source: others instead of auto_source: mt and omit engines.

Changing a pass to mode: suggest leaves the string state unchanged; mode: fuzzy leaves it needing editing. Neither excludes its results from a later state:<translated pass. Keep mode: translate when the intention is to retain each successful pass’s translations.

Use Preview without changes to validate the workflow before using Run now. Preview does not call translation services or predict their results. After a real run, inspect the activity log for each action’s updated count and warnings. A service failure that stops the workflow is recorded as an error; later actions do not run.

Remove or disable overlapping Automatic translation add-ons when replacing them with this workflow. Ordering applies within a single automation run; separate add-ons and concurrent runs can still overlap. The daily trigger respects BACKGROUND_TASKS. Use triggers: [] for manual execution only.

Run an action only when a translation pass updates strings

Action IDs make outputs available to later conditions. For example, append the following item to the previous workflow’s actions list to mark translations from the component as needing editing when the machine translation pass updated at least one string:

- choose:
    - conditions:
        - condition: expression
          value: results.machine.updated > 0
      sequence:
        - action: weblate.bulk_edit
          settings:
            q: "state:translated"
            state: 10
  default: []

The bulk-edit query selects all currently translated strings in the component, including translations that existed before the run and memory matches. It does not select only the strings updated by machine. Narrow the query to the intended strings before using this example. String state 10 means needing editing; it does not approve or request review of translations.

choose executes only the first branch whose conditions pass. Here, the empty default performs no action when the translation pass updated no strings. During preview, the condition is unknown because machine has not executed.

Translate after source changes

This complete workflow listens for source edits in Weblate and new source strings from the repository. It runs only for categorized components matching either frontend or backend, and only when the change includes a nonempty unit. The action reuses other components» translations for German strings needing translation.

version: 1
triggers:
  - trigger: change
    events: [source_change, new_source_repo]
conditions:
  - condition: and
    conditions:
      - condition: or
        conditions:
          - condition: component_category
            value: frontend
          - condition: component_category
            value: backend
      - condition: expression
        value: unit != null && unit.source != ""
actions:
  - action: weblate.automatic_translation
    id: reused
    settings:
      auto_source: others
      mode: translate
      q: "language:de AND state:<translated"

The null guard makes changes without a unit safely skip the workflow. It also means Run now skips this workflow, because real manual execution has no unit context. To inspect the event-driven path without changing strings, use Preview without changes with a change ID belonging to the target component.

The action’s query targets all matching German strings in the component, not only the unit from the triggering change. trigger.unit_ids provides context for conditions; it is not automatically applied to operations and cannot be interpolated into q. The listed events do not cover every kind of source update; select additional Selected change events if the workflow should also respond to uploads or other changes.