agentsclimarketplace

Wpml language api

Skill Lonsdale201/wp-agent-skills/wpml/wpml-language-api

Use WPML's runtime language hook API from plugin/theme code — read the current/active/default language, resolve the translated ID of a post/term, switch language around a query, and build language-aware URLs. Covers apply_filters('wpml_current_language','') and the ICL_LANGUAGE_CODE constant, apply_filters('wpml_active_languages', null, $args), apply_filters('wpml_default_language', null), apply_filters('wpml_object_id', $id, $type, $return_original_if_missing, $lang), do_action('wpml_switch_language', $lang) with restore via null, apply_filters('wpml_permalink', $url, $lang), apply_filters('wpml_home_url',''), apply_filters('wpml_post_language_details', null, $post_id), and apply_filters('wpml_element_language_details', null, $args). All are registered in SitePress::api_hooks(); the legacy icl_* functions (icl_object_id, icl_get_current_language) are deprecated since 3.2. Use when code must behave per-language, show the right translation, run a query in a specific language, or link across translations.From its SKILL.md

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

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

10.6 KB, ~2.4k tokens by cl100k_base, as published. Nobody here has run it

WPML: the runtime language API

For plugin/theme code that must behave per language — know the current language, show the correct translation of a post/term, query in a specific language, or build language-aware URLs. WPML exposes this as a set of wpml_* hooks (not global functions), all registered in SitePress::api_hooks() (sitepress.class.php:316-407). The legacy icl_* global functions still exist but are deprecated since 3.2 in favour of these hooks.

Why hooks, not function calls

WPML deliberately exposes its API as filters/actions so your code works whether or not WPML is active: apply_filters('wpml_current_language','') returns your passed default ('') when WPML is absent, instead of a fatal undefined function. Always call through the hook, and treat the WPML-absent return as the graceful fallback.

Current / active / default language

// Current language code (2-letter). Pass '' — it's the ignored default.
$current = apply_filters( 'wpml_current_language', '' );          // e.g. 'hu'

// Or the constant (defined once per request at sitepress.class.php:485-487):
$current = defined( 'ICL_LANGUAGE_CODE' ) ? ICL_LANGUAGE_CODE : '';

// Default (site) language:
$default = apply_filters( 'wpml_default_language', null );        // e.g. 'en'

// All active languages, keyed by code:
$langs = apply_filters( 'wpml_active_languages', null, [ 'skip_missing' => 0, 'orderby' => 'code' ] );
// $langs['hu'] => [ 'code','native_name','translated_name','url','flag','active', ... ]

Verified registrations: wpml_current_language sitepress.class.php:341, wpml_default_language :380, wpml_active_languages :374 (callback wpml_get_active_languages_filter, inc/template-functions.php:124).

wpml_object_id — resolve the translation of a post/term

The workhorse. Given an ID in one language, return its counterpart in another (default: current) language. Use it whenever you have a hardcoded/stored ID and must show the right translation.

$translated_id = apply_filters(
    'wpml_object_id',
    $element_id,                 // post_id or term_id
    'post',                      // 'post' | 'page' | CPT slug | 'category' | 'post_tag' | taxonomy | 'nav_menu' | 'any'
    true,                        // $return_original_if_missing: true → original id when no translation; false → null
    null                         // target language (null = current)
);

Verified at sitepress.class.php:378 (callback wpml_object_id_filter, inc/template-functions.php:381; underlying SitePress::get_object_id() sitepress.class.php:4644). Legacy icl_object_id() (template-functions.php:353) is deprecated 3.2 and just wraps this filter.

Rule: pass $return_original_if_missing = true for display (so you never render a blank when a translation is missing), false when you specifically need "is there a translation?".

wpml_switch_language — run code in a specific language

To query or render as another language, switch, do the work, then restore by passing null:

do_action( 'wpml_switch_language', 'de' );   // switch to German

$posts = get_posts( [ 'post_type' => 'product', 'numberposts' => 5 ] ); // now returns German posts

do_action( 'wpml_switch_language', null );   // ALWAYS restore

Verified at sitepress.class.php:406 → wpml_switch_language_action (template-functions.php:1380) → SitePress::switch_lang() (sitepress.class.php:1203); null restores the cached original_language (:1214-1219). Passing 'all' widens queries to every active language. WPML fires do_action('wpml_language_has_switched', $code, $cookie_lang, $original) after each switch (:1234) if you need to react.

Rule: every switch must be paired with a restore (null), even on early return / exception — otherwise the rest of the request runs in the wrong language.

Language-aware URLs

// Home URL in the current language:
$home = apply_filters( 'wpml_home_url', '' );

// Convert any URL to a target language (null = current):
$url = apply_filters( 'wpml_permalink', $url, $lang_code );
// 3rd arg $absolute_url = true resolves the object behind the URL and finds the
// matching translation's URL — heavier; use only when you don't already know the language.

// Ready-made <a> link to the translation of an element:
$link = apply_filters( 'wpml_element_link', $element_id, 'post' );

wpml_home_url sitepress.class.php:373; wpml_permalink is registered in a class action (classes/API/Hooks/class-wpml-api-hook-permalink.php:17,29) and runs the result through esc_url_raw(); wpml_element_link sitepress.class.php:377. WPML emits hreflang, canonical, and the switcher itself — you don't build those.

Language details of a post / element

// Post: array with language_code, locale, text_direction, display_name, native_name, different_language (or WP_Error)
$info = apply_filters( 'wpml_post_language_details', null, $post_id );

// Any element (post or term): object with trid, language_code, source_language_code
$details = apply_filters( 'wpml_element_language_details', null, [
    'element_id'   => $term_taxonomy_id,   // post_id for posts, term_taxonomy_id for terms
    'element_type' => 'post_product',      // WPML element type — see wpml_element_type
] );

// Translate a WP type to a WPML element type ('post_{cpt}' / 'tax_{taxonomy}'):
$wpml_type = apply_filters( 'wpml_element_type', 'product' );  // 'post_product'

wpml_post_language_details sitepress.class.php:381 (callback returns keys at template-functions.php:817-824); wpml_element_language_details :401; wpml_element_type :391.

Critical rules

  • Call through the hook, not the icl_* function. wpml_current_language / wpml_object_id / etc. are the supported API; icl_get_current_language / icl_object_id are @deprecated 3.2. The hooks also no-op safely when WPML is absent.
  • Never store or cache a cross-language ID / URL. They are per-language; resolve with wpml_object_id / wpml_permalink at the point of use.
  • Always restore after wpml_switch_language by calling it with null — wrap in try/finally if the work can throw.
  • wpml_object_id for display uses $return_original_if_missing = true so a missing translation falls back to the original instead of vanishing.
  • wpml_active_languages returns an array keyed by language code, not a list — iterate keys or array_keys().
  • Don't read ICL_LANGUAGE_CODE before WPML initialises it (sitepress.class.php:485, set during WPML init). In early hooks prefer apply_filters('wpml_current_language','').

Common mistakes

// WRONG — hardcoded ID renders the wrong language's object
echo get_the_title( 123 );

// RIGHT — resolve to the current language first
$id = apply_filters( 'wpml_object_id', 123, 'post', true );
echo get_the_title( $id );

// WRONG — switch without restore leaves the request in 'de'
do_action( 'wpml_switch_language', 'de' );
return $this->build_feed(); // rest of request now German

// RIGHT — restore, even on the early-return path
do_action( 'wpml_switch_language', 'de' );
try { return $this->build_feed(); }
finally { do_action( 'wpml_switch_language', null ); }

// WRONG — calling the deprecated function directly (fatals if WPML inactive)
$lang = icl_get_current_language();
// RIGHT
$lang = apply_filters( 'wpml_current_language', '' );

Cross-references

  • wpml-overview — the "WPML translates copies" model that makes wpml_object_id necessary.
  • wpml-config — declare which content types are translatable in the first place.
  • wpml-string-translation — translate dynamic strings (a different concern from resolving object IDs).

What this skill does NOT cover

  • String / option translation — wpml-string-translation.
  • Declaring translatable content — wpml-config.
  • Building language switchers / hreflang / sitemaps — WPML generates these; the SEO/URL internals are out of scope here.
  • The icl_translations table schema — interact via the hooks, not the tables.

References

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

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.