agentsclimarketplace

Wpml config

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

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.From its SKILL.md

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.

SKILL.md

12.3 KB, ~2.8k tokens by cl100k_base, 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

What ships with it: 1 file

5.9 KB alongside SKILL.md

Keep looking

Skills are one crate of 325,949. 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.