Documentation / Developers
SwiftLing Pro lets other systems read and write translations: an import from a translation agency, a headless editor, a script, an app. SwiftLing itself answers WordPress’s routes in a language and lists the languages, see SwiftLing’s docs/rest-api.md; this is what SwiftLing Pro adds.
Every request is made as a user, with WordPress’s authentication (an application password, or the cookie and nonce of a signed-in user), and may do what that user may do in the translation editor: an administrator or editor translates what they may edit; a translator (Settings › Translators) translates everything, but may not change the posts themselves, so they use the routes of swiftling-pro/v1. These routes work with the originals, also at a language’s address.
A post’s or term’s own texts: swiftling_translations
Posts of the types SwiftLing translates and terms of the lists it translates carry a field swiftling_translations, on WordPress’s routes (wp/v2/posts, wp/v2/pages, wp/v2/categories…) and on WooCommerce’s (wc/v3/products, whose products are posts). By the slug of each language:
"swiftling_translations": {
"de": { "title": "Kontakt", "excerpt": "Schreiben Sie uns", "slug": "kontakt" }
}
A term has name, description and slug. An empty string is no translation; a slug that is empty shows the original’s. A text whose original changed since it was translated reads as empty until it is translated again. A visitor reads only the languages visitors see; whoever translates reads every language.
Written with the post or term, as any other field, it saves translations:
POST /wp-json/wp/v2/posts/12
{ "swiftling_translations": {
"de": { "title": "Kontakt", "excerpt": "Schreiben Sie uns", "slug": "kontakt",
"texts": { "8f14e45fceea167a5a36dedd4bea2543": "Rufen Sie uns an" },
"state": "machine" } } }
titleandexcerpt(nameanddescriptionof a term) are saved by name;textsare the post’s other texts by key, asGET swiftling-pro/v1/textslists them.stateisreviewed(the default) ormachine, for a machine translation someone still checks.- An empty text removes the translation; an empty slug gives back the original’s.
- The first translation of a title gives the post its slug in the language, unless
slugis given.
Everything is checked before anything is saved, so a write is saved whole or not at all:
| Error | When |
|---|---|
swiftling_unknown_texts (400) | A key is no text of the post, or of a version of its original from before the post’s page was last checked. data.keys lists them; list the texts again. |
swiftling_no_original (400) | A text the post does not have, as the excerpt of a post without one. |
swiftling_placeholders (400) | A translation of a text from code asks for a value its original does not give, as %2$s, or holds a % that is no placeholder: the page would stop. data.keys lists them. |
swiftling_slug_subject (400) | A slug for what has no address of its own. |
rest_invalid_param (400) | A language the site is not translated into, or a state of none. |
Through WooCommerce’s routes an error has no data.keys: WooCommerce answers it as its own.
A post never checked is checked on the server first, which takes a second or two.
Any subject: swiftling-pro/v1
A subject is what the translation editor opens: a post (post:12), a template of a block theme (template:twentytwentyfive//archive), a kind of page of a classic theme (view:search), the terms of a list (terms:category), a classic menu (menu:3), or a builder’s subject, such as an options page of Advanced Custom Fields.
GET /wp-json/swiftling-pro/v1/texts?subject=post:12&lang=de
The texts of the subject with their translations into the language, as the editor lists them. The originals are not stored, so the subject’s page is checked on the server first.
{
"subject": { "key": "post:12", "kind": "post", "title": "Kontakt", "url": "https://example.com/kontakt/" },
"texts": [
{ "key": "1f0e3dad99908345f7439f8ffabdffc4", "object": "post:12", "path": "field/post_title",
"section": "page", "kind": "heading", "type": "text", "original": "Kontakt",
"translation": "", "state": "missing", "previous": "", "follows": false }
]
}
typeistext,html,code,url(an address: a link or an image), orformat, a text from code that keeps its original’s placeholders.stateisreviewed,machine,official(WordPress’s or the theme’s own translation),outdated, withprevious, the translation of the original before it changed, ormissing.followsis a menu’s label that shows its page’s translated title while it has none of its own.- A key names the text and the version of its original: a translation of an older version is refused once the page has been checked since.
POST /wp-json/swiftling-pro/v1/texts
{ "subject": "post:12", "lang": "de", "state": "reviewed",
"texts": { "1f0e3dad99908345f7439f8ffabdffc4": "Kontakt" } }
Saves the translations by key, checked as the field’s are. It answers with the states of what was saved, the subject’s state in every language (languages) and a post’s address in the language.
POST /wp-json/swiftling-pro/v1/translate
{ "subject": "post:12", "lang": "de" }
Fills the empty texts of the subject with the translation service and saves them as machine translations, as Translate everything does for a page. With "again": ["machine"] (or reviewed) it translates the texts in those states again instead. It answers how many texts there were, how many were translated, their characters, and the service’s error if it stopped part of the way: what it translated before is kept. A translator may use it unless Settings › Translators says no.
GET /wp-json/swiftling-pro/v1/to-translate?lang=de
What still needs translating in a language: by default what is not translated, partly, outdated or only machine translated. Paged as WordPress’s routes are (page, per_page up to 100, X-WP-Total, X-WP-TotalPages).
| Parameter | |
|---|---|
kind | post (the default: the pages and posts visitors open), template (templates or kinds of pages, and builders’ subjects), terms, menu. |
type | For posts: one post type, as page. |
state | The states to list: missing, partial, outdated, machine, reviewed, duplicate (the language keeps the original, Keep the original in the editor). |
[ { "key": "post:12", "kind": "post", "title": "Kontakt", "state": "missing",
"url": "https://example.com/de/kontakt/", "id": 12, "type": "page" } ]
A subject never checked has no texts known yet, so it is missing.
A shop: swiftling_prices and swiftling_language
WooCommerce’s routes (wc/v3) carry two more fields.
Products and variations have swiftling_prices: the product’s own regular and sale price in each of the shop’s other currencies (Settings › Currencies), by currency code. An empty price has none of its own, so the price is converted from the shop’s.
"swiftling_prices": {
"USD": { "regular": "12.50", "sale": "" },
"GBP": { "regular": "", "sale": "" }
}
Orders have swiftling_language: the language the order was placed in, which its emails to the customer are written in, or null for one made in the admin.
"swiftling_language": { "locale": "de_DE", "slug": "de" }
Both are written with the product or order, as WooCommerce’s own fields: prices as decimals in strings, as WooCommerce writes them, only the kinds and currencies given; the language by its slug or locale ("de"), one of the site’s, the original’s included. They are written before WooCommerce saves, so an order made through the API is saved with its language and its first emails go in it. A currency the shop does not have (swiftling_currency), a price that is no number (swiftling_price) or a language the site does not have (swiftling_language) stops the request with a 400 before anything of it is saved.
Abilities
Where WordPress has the Abilities API (6.9 and later), SwiftLing Pro registers its translation abilities in the category swiftling-translation, for AI agents (through an MCP adapter) and other tools. They are the same steps as the routes above, with the same rights, and run over the Abilities API’s own routes too: GET /wp-json/wp-abilities/v1/abilities/swiftling-pro/get-texts/run?input[subject]=post:12&input[lang]=de.
| Ability | |
|---|---|
swiftling-pro/list-languages | The languages, the original first. Read only. |
swiftling-pro/translation-status | The service, its characters this month, and the pages in each state per language. Read only. |
swiftling-pro/get-texts | subject, lang: as GET swiftling-pro/v1/texts. Read only. |
swiftling-pro/to-translate | lang, kind, type, state, page, per_page: as GET swiftling-pro/v1/to-translate, answering items and total. Read only. |
swiftling-pro/save-translations | subject, lang, texts (key => text), state: as POST swiftling-pro/v1/texts. |
swiftling-pro/machine-translate | subject, lang, again: as POST swiftling-pro/v1/translate. It costs characters with the service. |