WORDPRESS
How to Run Polylang Audits with the WordPress Abilities API
Run four read-only Polylang audits with WordPress Abilities API and WP-CLI. Verify access, inputs, pagination, results, and safe REST defaults.
FREE WORDPRESS PLUGIN
Multilingual Abilities
Inspect missing Polylang translation links and bounded language coverage without changing your posts or translation groups.
- Install with Polylang on WordPress 6.9+
- Check Tools → Multilingual Abilities
- Run a permission-aware, bounded audit
Read-only and administrator-gated. No translation, automatic link repair, background scan or bundled MCP server. Coverage is paginated by source posts, not a site-wide total. External REST exposure stays off unless explicitly enabled.

To run a Polylang translation audit through the WordPress Abilities API, use an authenticated WordPress execution context, retrieve the exact ModelGain ability by name, pass its documented input, and read the bounded response before moving to the next source-post page. You do not need an MCP server or a public REST endpoint for this local workflow.
This tutorial uses ModelGain Multilingual Abilities 0.1.0 and the stable wp eval command. It is for WordPress developers and operators who can run authorized WP-CLI commands. If you first need to decide which translations are absent, start with the missing Polylang translations audit overview. Here we focus on actually executing the four abilities, verifying their inputs and interpreting their output without overstating coverage.
At a glance: the four read-only abilities
| Ability name | Question it answers | Required inputs |
|---|---|---|
modelgain-multilingual/list-languages |
Which configured language slugs can I use? | No content inputs |
modelgain-multilingual/find-missing-translations |
Which scanned source posts lack a linked target-language post? | source_language, target_language, post_type |
modelgain-multilingual/audit-language-coverage |
What is each selected post’s linked, unpublished, absent or inaccessible translation state? | source_language, post_type |
modelgain-multilingual/check-translation-links |
Are there structural inconsistencies provable from Polylang’s public translation mappings? | source_language, post_type |
offset and limit (1–100). These are source-post pages, not a site-wide asynchronous crawl.The plugin cannot translate text, generate missing posts, repair links, perform a live hreflang audit or schedule recurring checks. Its native abilities are registered inside WordPress; the official MCP Adapter is an optional separate integration, not bundled with this plugin.
1. Check the prerequisites and execution identity
- Use WordPress 6.9 or newer, PHP 7.4 or newer, with Polylang active and the required languages configured. Production runtimes should still follow supported security-update guidance.
- Install and activate ModelGain Multilingual Abilities. Open Tools → Multilingual Abilities to check provider readiness, ability registration and the external-exposure setting. This screen is not an audit-report runner.
- Use WP-CLI in the correct WordPress installation and select an existing authorized account. The plugin requires
manage_optionsfor every execution, and checks access to individual posts; regular editors cannot assume they can execute the audit. - Keep External REST exposure disabled for a local CLI workflow. A PHP ability can be available locally even when HTTP discovery deliberately hides it.
Run the following from a shell that already has permission to administer the intended installation. Replace YOUR_ADMIN_USERNAME with the existing administrator username; never paste a password, cookie or Application Password into the article’s examples. Specify your normal WP-CLI --path (and --url on multisite) if needed.
wp core version
wp plugin list --status=active --fields=name,version,status
wp --user=YOUR_ADMIN_USERNAME eval '
if ( ! function_exists( "wp_get_ability" ) ) {
WP_CLI::error( "WordPress Abilities API is unavailable" );
}
$names = array(
"modelgain-multilingual/list-languages",
"modelgain-multilingual/find-missing-translations",
"modelgain-multilingual/audit-language-coverage",
"modelgain-multilingual/check-translation-links",
);
foreach ( $names as $name ) {
WP_CLI::log( $name . ": " . ( wp_get_ability( $name ) ? "registered" : "missing" ) );
}
'
What success means: all four exact identifiers return registered in this WordPress process. Registration is a prerequisite, not evidence that the current account is authorized or that the provider is ready. If an identifier is missing, verify plugin activation and site/version before considering REST or MCP changes. The ability registration versus MCP discovery guide addresses that separate failure class.
2. Call list-languages first
Do not guess language codes from the translated page title. This first ability returns default_language and a languages array with each configured slug. For example, French often uses fr, but rely on the site’s actual response.
wp --user=YOUR_ADMIN_USERNAME eval '
$ability = wp_get_ability( "modelgain-multilingual/list-languages" );
if ( ! $ability ) {
WP_CLI::error( "Language ability is not registered" );
}
$result = $ability->execute( array() );
if ( is_wp_error( $result ) ) {
WP_CLI::error( $result->get_error_message() );
}
WP_CLI::log( wp_json_encode( $result, JSON_PRETTY_PRINT ) );
'
Read back: confirm provider_available and that languages contains the desired source and target slugs. When Polylang is unavailable or the account is unauthorized, stop and resolve that prerequisite; do not treat a permission/provider error as an empty content result. See the Polylang public functions reference for the underlying language and translation-mapping model.
3. Find missing English-to-French translation relationships
Use find-missing-translations for a specific source language, target language and Polylang-enabled post type. The following command checks at most 25 English post entries starting at source offset zero:
wp --user=YOUR_ADMIN_USERNAME eval '
$ability = wp_get_ability( "modelgain-multilingual/find-missing-translations" );
if ( ! $ability ) {
WP_CLI::error( "Missing-translations ability is not registered" );
}
$input = array(
"source_language" => "en",
"target_language" => "fr",
"post_type" => "post",
"offset" => 0,
"limit" => 25,
);
$result = $ability->execute( $input );
if ( is_wp_error( $result ) ) {
WP_CLI::error( $result->get_error_message() );
}
WP_CLI::log( wp_json_encode( $result, JSON_PRETTY_PRINT ) );
'
Inspect items, count, has_more and next_offset. Each finding identifies a visible source post and the missing target-language link; count is the number of missing-link findings on this page, not the number of source posts processed across the whole site. A zero finding count with has_more: true means continue scanning, not “all translations exist.”
Also distinguish missing link from missing content. A standalone French draft could exist but be unlinked; conversely an English source may intentionally have no French translation. The API returns relationship evidence, not editorial requirements. Polylang documents how existing translated posts are linked.

4. Audit coverage and inspect page-scoped counters
For more detail than a missing-link list, call audit-language-coverage with source_language, post_type, offset and limit. It reports a coverage array for each source post, plus by_language counters and the number of source posts in this page as scanned_count.
wp --user=YOUR_ADMIN_USERNAME eval '
$ability = wp_get_ability( "modelgain-multilingual/audit-language-coverage" );
if ( ! $ability ) {
WP_CLI::error( "Coverage ability is not registered" );
}
$result = $ability->execute( array(
"source_language" => "en",
"post_type" => "post",
"offset" => 0,
"limit" => 25,
) );
if ( is_wp_error( $result ) ) {
WP_CLI::error( $result->get_error_message() );
}
WP_CLI::log( wp_json_encode( $result, JSON_PRETTY_PRINT ) );
'
The possible state values are linked, linked_unpublished, absent, inaccessible and invalid_link. Review the source and target in WordPress before deciding whether to publish, commission a translation or fix a relationship. In particular, linked_unpublished is not an absent translation; inaccessible is not proof that the post is missing.
| Response evidence | Correct interpretation | Next action |
|---|---|---|
linked |
The target relationship is present in the inspected scope | Review editorial quality separately |
linked_unpublished |
A target is linked but not publicly published | Check the target’s editorial status |
absent |
No target relationship was found for that language | Confirm that the language is required |
inaccessible |
The inspected caller cannot verify the target | Review account permissions, not link health |
invalid_link |
The public mapping does not pass the plugin’s structural checks | Inspect both post IDs before changing Polylang links |
5. Inspect translation-map anomalies
The fourth ability, check-translation-links, accepts the same content inputs as the coverage audit. It returns items with each source post’s anomalies array. An empty anomalies array means that the current checks found no provable structural inconsistency for that source, not that the natural-language translation is correct or that every permalink is healthy.
wp --user=YOUR_ADMIN_USERNAME eval '
$ability = wp_get_ability( "modelgain-multilingual/check-translation-links" );
if ( ! $ability ) {
WP_CLI::error( "Link-check ability is not registered" );
}
$result = $ability->execute( array(
"source_language" => "en",
"post_type" => "post",
"offset" => 0,
"limit" => 25,
) );
if ( is_wp_error( $result ) ) {
WP_CLI::error( $result->get_error_message() );
}
WP_CLI::log( wp_json_encode( $result, JSON_PRETTY_PRINT ) );
'
The plugin uses Polylang’s public relationships, including the semantics documented for pll_get_post_translations() and pll_get_post_language(). It does not read hidden Polylang storage, deduce the language of the body text or automatically relink posts. Report any anomaly to the site editor with source ID, language and affected post IDs; make corrections through the normal Polylang editorial process only after independent verification.
6. Pagination: why a successful first request is not a site-wide audit
All three content abilities select a page of source posts. The maximum per request is 100; the examples deliberately use 25. After each call, follow the returned next_offset while has_more is true. For a missing-translation query, do not advance by count, because that counts findings, not scanned sources.
Illustrative example (not a live result): page 1 inspects source offset 0 with limit 25, returns count: 0, has_more: true, next_offset: 25. Page 2 starts at offset 25 and could return three missing relationships. Stopping after the empty first page would miss all three. For coverage, sum by_language counters only across a deliberate, complete, consistently filtered series of pages and label the aggregation yourself; the plugin does not maintain a global report.
For a small, stable editorial sample, manually re-run the command replacing "offset" => 0 with the returned next_offset. If the site is changing while the scan runs, offset pagination can shift; note the scan time and consider a controlled editorial window before interpreting cross-page totals. For reporting examples, see the coverage and missing-translation walkthrough.
7. Troubleshoot failures without opening unnecessary network access
| Symptom | Likely layer to verify | Safe next step |
|---|---|---|
wp_get_ability() does not exist |
WordPress core/version or wrong bootstrap | Check WordPress 6.9+ and WP-CLI target; see the API unavailable guide |
| Expected name returns null | Plugin activation, registration hooks, target site | Check that exact plugin and installation; see registration troubleshooting |
| Execution returns a permission error | Current WordPress identity or post edit capability | Check --user, manage_options and affected post access |
| Invalid input or post type | Actual language slug, enabled post type, input schema | Use list-languages and Polylang post-type settings; keep limit at 100 or less |
| Works in PHP but absent in REST/MCP | Default-private external exposure or a separate adapter | Leave REST off unless truly needed; check the official REST exposure rules |
No findings, has_more: true |
Incomplete scan, not necessarily a content defect | Use next_offset until the bounded series is complete |
Do not enable anonymous REST, weaken permissions, or install a second MCP server just to make a local command run. REST Abilities require authentication and their own permission_callback; external discoverability is not the same as authorization. The WordPress API uses wp_get_ability() and WP_Ability::execute() for native PHP execution. Official PHP reference.
Should you use wp ability run instead?
WordPress documents a convenient wp ability command family, but as of this guide’s review, it is not part of a stable WP-CLI release; the command’s official documentation instructs users to use a nightly or separately installed package. That is why this tutorial uses the established wp eval command. Do not upgrade production WP-CLI to a nightly build solely to run a translation audit. See the official WP-CLI ability command status before changing that decision.
Polylang Pro’s own REST translation endpoints are a separate feature set; they are not the four native abilities shown here. Similarly, a working local PHP command does not imply a working remote MCP handshake. If your actual problem is MCP transport, use the dedicated MCP Adapter connection diagnosis instead.
Operational checklist and next step
- Record the WordPress/Polylang/ModelGain versions and the exact selected site and authorized identity, without saving credentials.
- Confirm four registrations and real configured language slugs; record the post type and source/target scope.
- Inspect one known linked source, one intentional gap and (if available) a draft or inaccessible example; compare actual WordPress editor records with the response.
- Document every requested offset and final
has_more: falsebefore presenting whole-scope totals. Keep editorial exceptions separate from defects. - Leave external access off when not required; review permissions and any future adapter separately.
Download the read-only tools: the ModelGain Multilingual Abilities product page explains the available features, while the official WordPress.org listing provides installation, version, changelog and support details. This tutorial describes what you can execute and verify today—not an automatic translation or link-repair service.