Claude Skill

wpml-overview

Orient a developer making a WordPress plugin or theme

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download lonsdale201-wp-agent-skills-wpml_wpml-overview-52f6020.zip · 3 KB
Part of lonsdale201/wp-agent-skills — 226 skills

Install

skills CLI npx skills add https://github.com/Lonsdale201/wp-agent-skills/tree/main/wpml/wpml-overview
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install lonsdale201-wp-agent-skills@llmmart
Git git clone https://github.com/Lonsdale201/wp-agent-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole lonsdale201/wp-agent-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

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 .po file) 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 via wpml_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_language around 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_permalink at 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 — the wpml-config.xml file: 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_translations schema — you interact via the hook API, not the tables directly.
  • WooCommerce Multilingual (WCML) — a separate WPML add-on with its own hooks.

References

Files (wp-agent-skills)
  • SKILL.md 9.1 KB
    ---
    name: wpml-overview
    description: 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.
    metadata:
      wp-skills-author: "Soczó Kristóf"
      wp-skills-contact: "mailto:lonsdale201@hotmail.com"
      wp-skills-plugin: "sitepress-multilingual-cms"
      wp-skills-plugin-version-tested: "4.9.5"
      wp-skills-php-min: "7.4"
      wp-skills-last-updated: "2026-07-03"
    ---
    
    # 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 `.po` file) 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).
    
    ```php
    // 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](sitepress.php) (`'4.9.5'`) and WPML's own bootstrap guards on it ([sitepress.php:26](sitepress.php)). `WPML_TM_VERSION` is defined inside core at [tm.php:9](tm.php) (loaded via `Plugins::loadEmbeddedTM()`, [classes/plugins/Plugins.php:86](Plugins.php)) — 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](functions.php)); `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 via `wpml_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_language`** around the query, then restore.
    
    ## Where WPML ships its own compatibility
    
    The base plugin bundles integrations for popular plugins/themes under [compatibility/](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_permalink` at 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`** — the `wpml-config.xml` file: 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_translations` schema** — 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](sitepress.php).
    - Public hook registration hub `SitePress::api_hooks()`: [sitepress.class.php:316-407](sitepress.class.php).
    - ST-detection helper `wpml_is_st_loaded()`: [inc/functions.php:922-924](functions.php).
    - Bundled compatibility integrations: [compatibility/](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/>
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related