Wpml overview
A community-maintained collection of agent skills for WordPress plugin and theme development.
npx -y skills add Lonsdale201/wp-agent-skills --skill wpml-overviewAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 21 stars21 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Orient a developer making a WordPress plugin or theme compatible with WPML (sitepress-multilingual-cms). Explains WPML's mental model — it translates COPIES (each translation is a separate post/term with its own ID, linked by a trid in icl_translations), unlike live-translation plugins — and the three compatibility mechanisms — (1) a declarative wpml-config.xml, (2) the runtime language hook API (wpml_current_language, wpml_object_id, wpml_switch_language, wpml_permalink), (3) string registration /translation (wpml_register_string / wpml_translate_single_string). Covers detecting WPML with defined('ICL_SITEPRESS_VERSION'), the add-on split (String Translation WPML_ST_VERSION, Translation Management WPML_TM_VERSION, Media WPML_MEDIA_VERSION) and which features need which add-on, plus a decision matrix mapping intent to mechanism. Use when starting WPML compatibility, deciding config vs API vs strings, or detecting WPML / its add-ons.
SKILL.md
9.1 KB, as published. Nobody here has run it
WPML: compatibility overview (orient)
For developers making a plugin or theme work correctly with WPML (the sitepress-multilingual-cms base plugin). This skill orients you — the mental model, how to detect WPML and its add-ons, and which of the three compatibility mechanisms to reach for. The mechanics of each live in dedicated skills (wpml-config, wpml-language-api, wpml-string-translation).
Mental model — WPML translates COPIES
The single most important thing to internalise: WPML creates a separate post/term for each language. A page in English (ID 10) and its Hungarian translation (ID 42) are two distinct WP objects, linked by a shared trid (translation group ID) in the icl_translations table. WPML sets the current language, and WordPress queries return the objects in that language.
This is the opposite of live-translation plugins (e.g. TranslatePress) that translate one page's output on the fly. Consequences for your code:
- To display "the translation of object X in the current language", resolve the translated ID with
wpml_object_id— never assume ID 10 is valid in every language. - IDs, permalinks, and menu items are per-language. Don't cache an absolute URL or an object ID across a request that may switch language.
- Free-form strings your plugin outputs (option values, labels not in a
.pofile) aren't "copied" — they must be registered for translation (String Translation).
Detecting WPML and its add-ons
WPML is not one plugin — the base handles languages and content copies (and bundles the Translation Management workflow); separately-installed add-ons add string/option translation (String Translation) and media (Media Translation).
// Base plugin active? (defines the version constant in its bootstrap)
if ( defined( 'ICL_SITEPRESS_VERSION' ) ) { /* WPML core is active */ }
// Separately-installed add-ons (each defines its own version constant):
defined( 'WPML_ST_VERSION' ); // String Translation — string & option translation
defined( 'WPML_MEDIA_VERSION' ); // Media Translation
// Translation Management: BUNDLED in core WPML (defined in tm.php, loaded via
// Plugins::loadEmbeddedTM) — NOT a separate download. Present whenever core is,
// once enabled in setup. Detect the feature, not a "plugin":
defined( 'WPML_TM_VERSION' );
Verified: ICL_SITEPRESS_VERSION is defined in sitepress.php:35 ('4.9.5') and WPML's own bootstrap guards on it (sitepress.php:26). WPML_TM_VERSION is defined inside core at tm.php:9 (loaded via Plugins::loadEmbeddedTM(), classes/plugins/Plugins.php:86) — TM ships with the base download, unlike ST/Media. The base ships a helper for the ST check — wpml_is_st_loaded() returns defined( 'WPML_ST_VERSION' ) (inc/functions.php:922-924); class_exists( 'WPML_String_Translation' ) is also used internally.
Why this matters: option translation (admin-texts) and all string registration are consumed by String Translation, not base runtime — declaring them does nothing without the ST add-on. Gutenberg-block config, by contrast, is handled by WPML's bundled page-builders add-on (parsed on a base install; only translating block content additionally needs ST). Detect before you depend.
The three compatibility mechanisms
| Mechanism | What it's for | Needs | Skill |
|---|---|---|---|
wpml-config.xml | Declare which custom fields, CPTs, taxonomies, options, shortcodes are translatable/copied | base (custom fields / CPT / taxonomy); ST for admin-texts; bundled page-builders add-on for gutenberg-blocks | wpml-config |
| Runtime language API | Behave per-language: current/active language, resolve translated IDs, switch language, build language URLs | base | wpml-language-api |
| String registration / translation | Translate free-form strings your plugin emits (settings values, dynamic labels) | String Translation add-on | wpml-string-translation |
Decision matrix — intent → mechanism
- "My CPT / taxonomy should be translatable" →
wpml-config.xml<custom-types>/<taxonomies>(base — TM is only for the translation workflow, not for marking a type translatable). - "This post meta should copy / translate / stay put across translations" →
wpml-config.xml<custom-fields action="...">(base). - "My plugin's option (a string in
wp_options) should be translatable" →wpml-config.xml<admin-texts>and String Translation active. - "I output a dynamic label / message that isn't a gettext string" → register it via
wpml_register_string+ translate viawpml_translate_single_string(ST). Static UI strings → normal WordPress i18n (__()), no WPML needed. - "I need to know the current language / show content in it / link to the translation" → runtime API (
wpml_current_language,wpml_object_id,wpml_permalink). - "I query posts and want them in a specific language" →
wpml_switch_languagearound the query, then restore.
Where WPML ships its own compatibility
The base plugin bundles integrations for popular plugins/themes under compatibility/ (gutenberg, jetpack, Flatsome, GoogleSiteKit, disqus, google-sitemap-generator, tiny-compress-images, twentyseventeen, …), wired via compatibility/wpml-compatibility-factory.php. When integrating a well-known plugin, check there first — the pattern may already exist. WPML also hosts remote config for many plugins (the wpml_config_index mechanism), so a plugin can be translatable via WPML.org's hosted wpml-config.xml even without shipping one.
Critical rules
- Detect the right layer.
defined('ICL_SITEPRESS_VERSION')for the base;WPML_ST_VERSION/class_exists('WPML_String_Translation')before anything string/option-translation related. - Prefer declarative config (
wpml-config.xml) over code for custom fields / CPTs / taxonomies / shortcodes — it's what WPML expects and needs no runtime hooks. - Never hardcode a cross-language ID or URL. Resolve with
wpml_object_id/wpml_permalinkat render time. - Static translatable UI text is plain WordPress i18n (
__(),_e()), not WPML. WPML enters only for content copies, options, and dynamic/registered strings. - Degrade gracefully. Your plugin must work with WPML absent and with the base present but an add-on missing.
Cross-references
wpml-config— thewpml-config.xmlfile: custom fields, CPTs, taxonomies, admin-texts, shortcodes.wpml-language-api— runtime language hooks: current/active language,wpml_object_id,wpml_switch_language, permalinks.wpml-string-translation— registering & translating dynamic strings (needs the ST add-on).
What this skill does NOT cover
- Mechanics of each mechanism — see the three dedicated skills.
- WPML's admin UI / translation editor workflow — this is a developer-compatibility family, not an end-user guide.
- Building a language switcher UI — WPML provides
[wpml_language_switcher]/ the LS API; custom switchers are a separate topic. - The internal
icl_translationsschema — you interact via the hook API, not the tables directly. - WooCommerce Multilingual (WCML) — a separate WPML add-on with its own hooks.
References
- Version constant + active-guard: sitepress.php:26,35.
- Public hook registration hub
SitePress::api_hooks(): sitepress.class.php:316-407. - ST-detection helper
wpml_is_st_loaded(): inc/functions.php:922-924. - Bundled compatibility integrations: compatibility/ +
compatibility/wpml-compatibility-factory.php. - WPML coding API docs: https://wpml.org/documentation/support/wpml-coding-api/.
- Official documentation: https://wpml.org/documentation/support/language-configuration-files/