Pro module13 abilities

WPML ability reference

Reference for the GoBuildWP Pro 1.12.4 source. Installed schemas and policy remain authoritative.

This WPML ability reference lists every call GoBuildWP Pro registers for WPML languages, translation groups and strings, with the exact slug an agent sends and what the plugin's own contract says it does. Of the 13, 8 read, 3 write and 2 are marked destructive in the source.

Read-only, write and destructive groups describe the source annotations. They do not establish a minimum safety profile, human approval or undo support. Those controls are separate: check the installed ability, the connected user and the active site policy before calling it. A read can still return sensitive data. These pages are not evidence that every operation passed an end-to-end runtime test.

What WPML needs before these load

These 13 abilities come with GoBuildWP Pro 1.12.4. Pro registration requires the Freemius SDK to permit premium code and any companion dependency the module checks to be available. The floors below apply to the named dependencies or features; an optional add-on or newer feature floor does not necessarily disable the base module. wppilot/integration-health and the module's setup call describe the installed availability.

Minimum (base)
4.7.0 WPPILOT_PRO_WPML_MIN_VERSION
WPML editions
free, pro
Agent skills shipped
wpml-integration

WPML in practice

Trids, element types and the icl_translations row

WPML does not keep a post's language in post meta. Each translatable element has a row in WPML's icl_translations table holding a language code and a trid, the id of the translation group it belongs to; every member of one group shares that trid. The language and grouping abilities touch that row only through WPML's published hooks (wpml_element_language_details, wpml_set_element_language_details, wpml_get_element_translations), so WPML's own actions and caches stay in step with what the agent changed.

Those hooks disagree about spelling. The write hook and the group lookup want a prefixed element type such as post_page or tax_category, while the details hook wants the bare name. GoBuildWP derives the prefixed form from the post itself, so an agent never passes it to wppilot/wpml-get-content-language, wppilot/wpml-set-content-language or wppilot/wpml-link-content-translations. The one call that takes an element type from the caller, wppilot/wpml-get-translation, expects the bare post type or taxonomy name. An unregistered name is refused with wpml_element_type_not_found, and a registered type WPML does not translate with wpml_element_type_not_translated, so a miss is never mistaken for a missing translation.

Two reads answer the translatable-type question slightly differently. wppilot/wpml-check-setup only walks post types and taxonomies that have an admin interface, while wppilot/wpml-list-translatable-types walks every registered type and adds public and built-in flags. Use the second when a hidden custom post type is involved.

wppilot/wpml-link-content-translations runs inside a database transaction. It first asks MySQL which engine stores icl_translations, and only an InnoDB table is linked; anything that cannot start a transaction gets wpml_atomic_link_unavailable with nothing changed. Inside the transaction it writes the source post, reads it back, then writes and verifies each other member against the same trid. A member that does not come back in the expected language and group rolls every change back, flushes the object cache and returns wpml_translation_link_failed naming the post. A failed commit returns wpml_translation_commit_failed.

Before opening the transaction it refuses a map that would push an existing member out of its slot: if the source post's group already holds a different post for one of the listed languages, the call stops with wpml_translation_language_occupied. Linking also assigns each listed language as it attaches a post, recording the source language as the one it was translated from, so a post reporting has_language: false can go straight into a link without a separate assignment.

For a single post, wppilot/wpml-set-content-language reads the post back after writing and returns wpml_language_assignment_failed if WPML did not keep the language; the source attributes that to a type being switched out of translation between the check and the write. Asking for the language a post already has, with keep_group left on, returns changed: false and writes nothing.

Neither group write can be reversed with wppilot/rollback-change, because the change lives in icl_translations, which the change ledger records as irreversible. Keep the wppilot/wpml-get-content-language output from before the change: it lists every member with its id and whether it was the original, which is what a manual rebuild needs.

String Translation refusals: gettext context, packages and source language

The module registers without WPML String Translation, but every string call refuses with wpml_string_translation_missing unless the add-on is loaded with icl_add_string_translation and the wpml_register_single_string action. wppilot/wpml-check-setup reports it under companions.string_translation.

A domain and name pair is only unique together with its gettext context. When the pair matches more than one row, a write is refused with wpml_string_ambiguous instead of picking one; use the string_id from wppilot/wpml-list-strings. Other refusals to recognise are wpml_string_in_package for builder and form strings, wpml_string_source_language when the target language is the string's own source (change the source text with wppilot/wpml-register-string instead), and wpml_string_not_found when nothing matches.

Each write is read back from the icl_string_translations table rather than WPML's per-request cache, and a value or status that did not land returns wpml_string_write_unverified. Line endings are normalised to single newlines before comparing, because WPML stores them that way, so a value that differs only in its line breaks plans as unchanged. Registration is checked the same way; wpml_string_register_unverified points at String Translation's settings for the language that was given.

Status filters map onto WPML's own codes, 10 for complete and 3 for needs-update. The waiting-for-translator and in-progress states that Translation Management sets are reported but cannot be written from here, and a string is never listed as untranslated in its own source language.

Profiles, confirmation and the WPML bulk dry run

Under the Read Only safety profile only the WPML reads remain. Under Production Safe everything loads, since nothing here is classed as critical. The language and group writes are annotated destructive, so the confirmation gate wants confirm: true, or a person's approval when the site's confirmation mode is human. wppilot/wpml-bulk-set-string-translations is deliberately left unannotated so its dry run stays reachable without that gate; the real run enforces confirm itself and answers wppilot_confirmation_required with the item count when it is missing. The single string write and the registration ask for confirm only when they would overwrite an existing different value.

What stays in WPML's Translation Management screens

Translation jobs are not wrapped. The source notes that WPML publishes no stable hook for listing or creating them, and that the batch objects its own screens pass around differ between WPML releases, so sending content to translators, assigning jobs and reviewing them stays in WPML > Translation Management. The module also never changes WPML configuration (languages, translatable types, translation mode), has no term-language write, and leaves WooCommerce Multilingual pricing and attributes alone, although check-setup reports whether WCML is active.

A typical request: link our Spanish contact page to the English one so the switcher shows it. The agent runs wppilot/wpml-check-setup, confirms page is in translated_post_types, finds both ids with wppilot/wpml-list-content (once per language), reads each with wppilot/wpml-get-content-language, and after approval calls wppilot/wpml-link-content-translations with source_language en. On staging, a second read should show one trid with the English page as original, the switcher on the English page should reach the Spanish one, and wppilot/wpml-get-translation with element_type page and language es should resolve the English id to the Spanish id.

WPML reads

AbilityWhat it does
wppilot/wpml-check-setupCheck WPML SetupReports the WPML Multilingual CMS version, the configured languages and the default language, which post types and taxonomies are set translatable, and whether the String Translation and WooCommerce Multilingual companions are active. Call this before any other WPML ability. Two things here decide whether later calls can work at all: min_satisfied, and translated_post_types; WPML only carries a language for a post type that is switched on under WPML > Settings > Post Types Translation, and a write against a type that is not listed is refused rather than silently dropped.
wppilot/wpml-get-content-languageGet WPML Content LanguageReads one post's WPML language, its translation-group id (trid), which language it was translated from, and the complete translation group it belongs to. has_language: false means WPML holds no row for this post; it was created without a language, so it is outside every translation group and outside the language switcher. Read this before any language or translation write: it shows the group the write will change. Neither write ability takes the trid as input (they take post ids and language codes), and a post with has_language false can still be given a language with wpml-set-content-language.
wppilot/wpml-get-string-translationsGet WPML String TranslationsReads one WPML string by id: its domain, name, source value and language, and the translation and status in every configured language, including the languages that have none yet. Read this immediately before writing a translation so the value being replaced is known. Requires the WPML String Translation add-on.
wppilot/wpml-get-translationGet WPML TranslationResolves one post or term id into its counterpart in another language. This is the lookup to use when building a link, a menu, or a query that has to land on the right language version of something; not a string translator. Set element_type to a post type (page, post, product) or a taxonomy (category, product_cat); WPML spells this differently here than the language-details abilities do, and this ability takes the bare name. fallback_to_original: true returns the original when the requested language has no translation, which is usually what a link wants; false returns found: false so the caller can decide.
wppilot/wpml-list-contentList WPML ContentLists content of one translatable post type with each item's assigned language, translation-group id, and the complete set of translations that group holds. Pass language to list what exists in that language; WPML scopes queries to the current language, so this switches to it for the query and switches back afterwards. Every row carries a translations map keyed by language code; the languages missing from that map are exactly the ones the item has not been translated into, which is the cheapest way to answer "what still needs translating" without a second call per item. has_language: false marks content WPML has no row for at all: it was created without a language, and it will not appear in the language switcher until one is assigned.
wppilot/wpml-list-languagesList WPML LanguagesLists every language configured in WPML, whether or not the current content has a translation in it: code, native name, translated name, locale, hreflang tag, flag URL, and which one is the site default. The code is the value every other WPML ability expects; not the locale, and not the name.
wppilot/wpml-list-stringsList WPML StringsLists strings registered in WPML String Translation — theme and plugin texts, widget titles, admin options, builder strings — with their domain (WPML calls it context), name, source value and source language, and the translation in every language with its status. Filter by domain, exact name, search (matches the source value or name), and language + language_status (untranslated, needs-update, complete) to answer "what is still untranslated in German". Paginated. Strings with a package_id belong to a page-builder or form package and are translated through WPML's Translation Editor, not here. Requires the WPML String Translation add-on.
wppilot/wpml-list-translatable-typesList WPML Translatable TypesEnumerates every registered post type and taxonomy on the site with whether WPML treats it as translatable. This is the answer to "why did the language write fail" more often than anything else: a post type that is not switched on under WPML > Settings > Post Types Translation carries no language at all, and content created in it is invisible to the language switcher no matter what else is done to it. Filter with only_translatable when you just want the working set. Switching a type on is a WPML admin decision with site-wide consequences, so GoBuildWP reports it and does not change it.

WPML writes

AbilityWhat it does
wppilot/wpml-bulk-set-string-translationsBulk Set WPML String TranslationsWrites up to 100 WPML string translations in one call, each item shaped like wpml-set-string-translation (string_id or domain + name, language, value, optional status). dry_run: true writes nothing and returns, per item, the current value and status, the value it would become, and whether it is a create, update or no-op. A real run requires confirm=true and reports success or failure per item; one failing item does not stop the rest. Not reversible from the change ledger: each item's result carries previous. Requires the WPML String Translation add-on.
wppilot/wpml-register-stringRegister WPML StringRegisters a string with WPML String Translation through the documented wpml_register_single_string action, so it appears in String Translation and can be translated. Use it for text a theme option, builder or custom field shows on the front end that WPML has not picked up yet. Code that outputs the string must also look it up (the wpml_translate_single_string filter with the same domain and name), or the translation will never be shown. Re-registering an existing domain + name with a different value changes the source text and WPML marks its translations as needing update, so that case requires confirm=true. Requires the WPML String Translation add-on.
wppilot/wpml-set-string-translationSet WPML String TranslationWrites the translation of one WPML string into one language through WPML's own icl_add_string_translation(), which also updates the string's status and flushes WPML's caches. Name the string by string_id, or by domain + name. status is complete (default; shown on the site) or needs-update (stored but flagged for review). The change ledger cannot undo this — WPML keeps strings in its own tables — so the result carries previous (the value and status replaced, or null) and replacing an existing different translation is refused without confirm=true. Package strings (page builders, forms) are refused: their translation is applied through WPML's Translation Editor. Requires the WPML String Translation add-on.

Destructive WPML calls

AbilityWhat it does
wppilot/wpml-set-content-languageSet WPML Content LanguageAssigns a configured WPML language to one post. Two distinct outcomes, decided by the post's current state and by keep_group. A post WPML has no row for gets a fresh translation group of its own, which is the fix for content created by an ability that knew nothing about WPML. A post that already sits in a group keeps that group by default, so the language of one member changes without detaching it; pass keep_group: false to move it out into a new group of its own instead. Changing the language of a group member that other translations point at is how a translation set gets split; read the group first. Destructive, and requires confirmation.

For the task-level view of WPML, with worked requests and what to check afterwards, see WPML integration page.