Wpml overview
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.From its SKILL.md
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.
SKILL.md
9.1 KB, ~1.9k tokens by cl100k_base, 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/
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.