translations/update-strings writes one or more translations into a locale’s PO file and then recompiles everything WordPress actually reads from it: the MO, the .l10n.php cache and the JSON fragments used by JavaScript.
That second half is the entire point.
At a glance
| Ability | translations/update-strings |
| Toolset | Loco Translate — toolset/loco-translate |
| Group | Loco Translate › Strings |
| Requires | Loco Translate, active on the site |
| Capability | manage_options |
| Safety | Writes data |
| Repeatable | Not idempotent — each call changes the row set, so re-running is not a no-op |
| Ships in | AcrossAI Abilities Manager 0.0.34 and later |
Why editing the PO is not enough
A PO file is source. WordPress never reads it. It reads the compiled MO, and on 6.5+ it reads the .l10n.php cache in preference to that. Edit the PO through the file abilities and both compiled artefacts go stale — the site keeps serving the old strings, and nothing anywhere reports a problem.
The response carries artefacts: bytes written per file, read back from disk rather than reported by Loco. A zero mo_bytes or php_bytes is the signal that the write did not reach what the site loads.
Strings are matched on exact source plus context. Anything that does not match is returned in unmatched rather than silently dropped, so a typo in a source string is visible instead of looking like a successful write.
Translations are stored exactly as sent, backslashes included. Nothing is unescaped on the way in.
Input
| Name | Type | Required | What it is |
|---|---|---|---|
bundle | string | Yes | Bundle id, handle or slug — all three appear in Loco’s own screens. Use core for WordPress itself. |
domain | string | No | Text domain. Omit for the bundle default. |
locale | string | Yes | Locale such as de_DE. |
strings | array | Yes | Rows of source, target and optional context. Source must match the file byte for byte. |
What comes back
| Name | Type | What it is |
|---|---|---|
artefacts | object | Bytes written per artefact — po_bytes, mo_bytes, php_bytes, json_files, json_bytes. Read back from disk rather than reported by Loco, so a zero mo_bytes means the site is still serving the old strings. |
applied_count | integer | How many translations were written. |
unmatched | array | Rows whose source matched nothing in the file. |
unmatched_count | integer | How many did not match. |
file | string | The PO file that was written. |
success | boolean | Whether the call completed. |
message | string | A one-line summary of what happened, suitable for showing a human. |
error_code | string | Present only on failure — a stable machine-readable reason, such as a missing field, a wrong field type or an unmet confirmation. |
Example
Ask your assistant:
Translate “Add to cart” and “Checkout” into French for WooCommerce.
It resolves to one call:
{
"ability": "translations/update-strings",
"parameters": {
"bundle": "woocommerce",
"locale": "fr_FR",
"strings": [
{ "source": "Add to cart", "target": "Ajouter au panier" },
{ "source": "Checkout", "target": "Commander" }
]
}
}Worth knowing
- Check
unmatched_counton every response. A source that does not match writes nothing and is easy to miss. - Check
artefactstoo. Bytes are read from disk, so this is the one honest signal that the site will actually show the new strings. - Never edit a PO through the file abilities. Use this, or repair afterwards with
translations/compile-translations. - Not idempotent in the strict sense — each call rewrites and recompiles — though sending the same translations twice leaves the same result.
Related abilities
- List Translation Strings — find what needs translating
- Recompile Translations — repair a PO edited elsewhere
- Get Translation Status — whether the cache is in play
Get the plugins:
AcrossAI Abilities Manager · AcrossAI MCP Manager
Browse the rest: Every ability, by category