agentsclimarketplace

Wpml config

Skill Lonsdale201/wp-agent-skills/wpml/wpml-config

A community-maintained collection of agent skills for WordPress plugin and theme development.

Install
npx -y skills add Lonsdale201/wp-agent-skills --skill wpml-config

Assembled 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

Make a WordPress plugin/theme translatable with WPML by shipping a wpml-config.xml file. Covers the sections WPML honors — custom-fields/custom-field action="translate|copy|copy-once|ignore" (post meta), custom-term-fields (term meta), custom-fields-texts (translatable sub-keys inside serialized/JSON meta), custom-types /custom-type translate="0|1" with display-as-translated and automatic attributes, taxonomies/taxonomy translate="0|1", admin-texts /key name for options, shortcode-list (CSV) vs shortcodes (rich), built-with-page-builder, and gutenberg-blocks. Explains file discovery (plugin root, theme root, the wpml_config_array filter), the exact 0/1 boolean and action-enum values, that a typo'd action silently means "ignore", that the XSD is NOT enforced during normal parsing, and that admin-texts needs the String Translation add-on while gutenberg-blocks is handled by WPML's bundled page-builders add-on. Use when adding, auditing, or debugging a wpml-config.xml.

SKILL.md

12.3 KB, as published. Nobody here has run it

WPML: the wpml-config.xml compatibility file

wpml-config.xml is the declarative way to tell WPML what in your plugin/theme is translatable — custom fields, custom post types, taxonomies, options, and shortcodes. It needs zero runtime code: WPML reads it and configures itself. This is the first (and often only) compatibility step for most plugins. For runtime language logic see wpml-language-api; for dynamic strings see wpml-string-translation.

Where the file goes and when it's read

  • Plugin: wp-content/plugins/<your-plugin>/wpml-config.xml (plugin root). Verified discovery at class-wpml-config.php:152,169.
  • Theme: child then parent theme root (class-wpml-config.php:262,268).
  • WPML re-reads config files in admin only, on a whitelist of pages (plugins.php, themes.php, WPML's own pages, string-translation.php when ST is active), filterable via wpml_config_white_list_pages (class-wpml-config.php:16-41). So after editing the file, visit Plugins or a WPML settings page to make WPML re-parse it — it is not re-read on every front-end request.

Skeleton (illustrative — plugin-specific keys)

<wpml-config>
    <custom-fields>
        <custom-field action="translate">subtitle</custom-field>
        <custom-field action="copy">_my_related_ids</custom-field>
        <custom-field action="copy-once">_my_layout</custom-field>
        <custom-field action="ignore">_my_cache</custom-field>
        <custom-field action="translate" encoding="json">footnotes</custom-field>
    </custom-fields>

    <custom-types>
        <custom-type translate="1">my_book</custom-type>
        <custom-type translate="0">my_log</custom-type>
    </custom-types>

    <taxonomies>
        <taxonomy translate="1">my_genre</taxonomy>
        <taxonomy translate="0">my_internal_tax</taxonomy>
    </taxonomies>

    <admin-texts>
        <key name="my_plugin_options">
            <key name="welcome_message" />
            <key name="footer_note" />
        </key>
    </admin-texts>

    <shortcode-list>my_cta,my_button</shortcode-list>
</wpml-config>

The sections you'll actually use

<custom-fields> — post meta (base plugin)

Each <custom-field action="...">meta_key</custom-field> sets how a meta key behaves across translations. The four action values are the enum honored by the parser (class-wpml-custom-field-xml-settings-import.php:78-96):

actionBehaviour
translateField is offered for translation; each language has its own value.
copyValue is copied from original to every translation and kept in sync.
copy-onceCopied when the translation is first created; editable independently after.
ignoreNot touched — translations keep whatever they have (default for anything).

Add encoding="json" for meta whose value is JSON (e.g. footnotes in WPML's own config, wpml-config.xml:24). Term meta uses the identical <custom-term-fields>/<custom-term-field action="..."> section.

Gotcha — a typo'd action silently becomes "ignore". The parser's switch has no validation branch; translate/copy/copy-once hit their cases and everything else falls to default → do nothing (:93-95). action="translated" or action="Translate" therefore silently leaves the field untranslated. There is no error — see "XSD not enforced" below.

<custom-fields-texts> — sub-keys inside a serialized/JSON meta

When a single meta key holds an array/JSON of many strings, declare exactly which inner keys are translatable with a nested <key name="..."> tree (name="*" = any key):

<custom-fields-texts>
    <key name="footnotes">
        <key name="*"><key name="content" label="Footnote" /></key>
    </key>
</custom-fields-texts>

Verified shape at wpml-config.xml:26-32, parsed by class-wpml-custom-field-xml-settings-import.php:112-156.

<custom-types> / <taxonomies> — make CPTs & taxonomies translatable

<custom-type translate="1">slug</custom-type> and <taxonomy translate="1">slug</taxonomy>. translate is required and accepts only 0 or 1 (the wpml-integer-boolean type — not yes/no/true). Read as (int) $c['attr']['translate'] (class-wpml-tm-settings-update.php:60).

Two optional attributes on both:

<admin-texts> — plugin options (needs String Translation)

Declares option names (and nested keys for serialized/array options) as translatable:

<admin-texts>
    <key name="my_plugin_options">
        <key name="welcome_message" />
    </key>
    <key type="post-ids" sub-type="attachment" name="my_logo_id" />
</admin-texts>

name is the wp_options name; nested <key> are keys inside a serialized/array option. type="post-ids" sub-type="attachment" marks a value as an object ID to convert to the translation rather than a string to translate.

Source-verified caveat: the base plugin declares admin-texts in its XSD but does not consume it — option translation is registered by WPML String Translation (which hooks wpml_config_array). On a base-only install this section does nothing. Confirmed: class-wpml-config.php initialises 'admin-texts' => array() but merge_with() never dispatches it, and no consumer exists in the base plugin. Gate any expectation on defined('WPML_ST_VERSION').

Shortcodes — two mechanisms

  • <shortcode-list>tag1,tag2</shortcode-list> (base) — a comma-separated list of shortcode tags whose content WPML registers for translation. Exploded on commas at class-wpml-config.php:432-434, stored via WPML_Config_Shortcode_List.
  • <shortcodes><shortcode><tag>…</tag><attributes><attribute>…</attribute></attributes></shortcode></shortcodes> (rich) — per-tag control over content and translatable attributes; consumed by the bundled page-builders add-on, not core. Use <shortcode-list> for the simple "translate this shortcode's inner text" case.

<built-with-page-builder><![CDATA[/<!-- wp:/]]></built-with-page-builder> marks builder-generated content via a regex; <gutenberg-blocks> declares per-block translatable parts — its config is parsed by WPML's bundled page-builders add-on (loaded unconditionally at sitepress.php:512, so it works on a base install), though translating the block content additionally needs String Translation. Full section reference in reference.md.

Programmatic config — the wpml_config_array filter

To add/modify config without a file (or for dynamically-registered post types), hook the main extension point (class-wpml-config.php:345):

add_filter( 'wpml_config_array', function ( $config ) {
    $config['wpml-config']['custom-types']['custom-type'][] = [
        'value' => 'my_dynamic_cpt',
        'attr'  => [ 'translate' => 1 ],
    ];
    return $config;
} );

Every parsed element has the [ 'value' => ..., 'attr' => [...] ] shape; a single entry is that array, multiple entries are a list of them.

Critical rules

  • translate / display-as-translated / automatic are 0 or 1 — never yes/no/true/false.
  • action is exactly translate / copy / copy-once / ignore. Anything else silently means "ignore" (no error).
  • The XSD is NOT enforced during normal file parsing (class-wpml-config.php:324 — validated with no XSD). Malformed elements, typo'd attributes, and wrong nesting are silently skipped, not reported. Validate your file against res/xsd/wpml-config.xsd yourself before shipping.
  • admin-texts requires String Translation — declaring options does nothing without ST active. gutenberg-blocks is handled by WPML's bundled page-builders add-on (parsed on a base install); only translating the block content additionally needs ST.
  • Re-parse is admin-and-whitelisted-page only — edit the file, then load Plugins/Themes/a WPML settings page to apply it; don't expect front-end reloads.
  • Place the file in the plugin/theme ROOT. Subfolders are not scanned.
  • Ship the file; don't rely on WPML.org's remote config for your own plugin — remote config is a fallback for plugins that don't ship one.

Common mistakes

<!-- WRONG — boolean/action values WPML doesn't recognise (silently ignored) -->
<custom-type translate="yes">my_book</custom-type>
<custom-field action="translated">subtitle</custom-field>

<!-- RIGHT -->
<custom-type translate="1">my_book</custom-type>
<custom-field action="translate">subtitle</custom-field>
<!-- WRONG — expecting <admin-texts> to translate options on base WPML -->
<admin-texts><key name="my_option"/></admin-texts>
<!-- ...with no String Translation active → nothing happens. Gate on WPML_ST_VERSION. -->

Cross-references

  • wpml-string-translation — for options/dynamic strings when admin-texts isn't enough, and the ST dependency.
  • wpml-language-api — runtime behaviour once your content is translatable.
  • wpml-overview — the base-vs-add-on split and decision matrix.
  • See reference.md for the complete honored-section table + the sections WPML does NOT support.

What this skill does NOT cover

  • <gutenberg-blocks> / page-builder widget sections in depth — declared in base XSD but consumed by ST / the page-builders add-on; see reference.md for the shape.
  • Options/string translation runtimewpml-string-translation.
  • Sections WPML does NOT honor (gettext-domains, custom-css, pages, post-types, custom-c2c-relationships) — listed in reference.md so you don't invent them.

References

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.