Skip to content

Hooks & filters

Every hook below is what LocaleReady’s own WooCommerce, Gravity Forms, and page-builder support is built from — reading integrations alongside this page is the worked example. Nothing here reaches into a private class; each is a plain add_filter() or add_action() call in your own plugin or theme’s functions.php.

Whether the current request is translated at all, decided before anything is segmented.

apply_filters( 'localeeasy_should_translate_request', bool $should, Request_Context $context );

Whether one specific piece of discovered text should be translated.

apply_filters( 'localeeasy_should_translate_segment', bool $should, Segment $segment );

Which HTML attributes are read for translatable text on a given element — alt, title, placeholder, and a handful of others by default.

apply_filters( 'localeeasy_translatable_attributes', string[] $attributes, string $tag );

CSS classes that exclude an element’s whole subtree from translation — WooCommerce adds its price and counter classes here.

apply_filters( 'localeeasy_exclude_classes', string[] $excluded );

The same idea, by element id instead of class.

apply_filters( 'localeeasy_exclude_ids', string[] $excluded );

Whether one inline script data object — a block’s attached JSON, a wp_localize_script() payload — is translated at all, for a payload a script parses in a way LocaleReady’s own walker cannot see into safely.

apply_filters( 'localeeasy_translate_localized_script', bool $translate, string $name, string $handle );

What happens to the string under one key of a JSON payload: skip, text, html, or url. The path is the full chain of keys from the root, so a rule can be scoped to one place in a payload rather than every key of that name anywhere.

apply_filters( 'localeeasy_json_key_rule', string $rule, string $key, string[] $path );

One effective translation, immediately before it replaces the source text on the page.

apply_filters( 'localeeasy_translation', string $translation, string $source, string $locale );

The whole response’s HTML, after the document and Interactivity translation passes have both run — the last point at which the full page is available as one string.

apply_filters( 'localeeasy_translated_html', string $html, string $locale );

Terms that must survive every provider verbatim — brand and product names, by default the list saved on the Translation settings tab.

apply_filters( 'localeeasy_protected_terms', string[] $terms, string $target_locale );

The regular expression used to find monetary amounts, so they are withheld from every provider before the request is sent.

apply_filters( 'localeeasy_currency_pattern', string $pattern );

Literal tokens a script substitutes at runtime — a cart button’s ### is the canonical example — isolated from a segment before translation and put back afterward.

apply_filters( 'localeeasy_interpolation_tokens', string[] $tokens );

The registered machine-translation providers, consulted in array order under Automatic selection. Register a third provider by appending your own Machine_Translation_Provider implementation.

apply_filters( 'localeeasy_machine_translation_providers', Machine_Translation_Provider[] $providers );

Whether a provider may be called in the current environment at all — production is always allowed; anywhere else needs this, the setting, or a constant to say so.

apply_filters( 'localeeasy_allow_provider', bool $allowed, string $environment );

The environment type LocaleReady’s spend guard reads, for a host that reports it incorrectly through wp_get_environment_type().

apply_filters( 'localeeasy_environment_type', string $type );

The monthly character ceiling, normally the value saved on the Usage & limits tab.

apply_filters( 'localeeasy_monthly_character_limit', int $limit );

Source term → required translation pairs supplied to the optional AI refinement pass.

apply_filters( 'localeeasy_glossary', array $glossary, string $source_locale, string $target_locale );

Content loaded after the page (AJAX & REST)

Section titled “Content loaded after the page (AJAX & REST)”

Whether one REST response is translated at all.

apply_filters( 'localeeasy_translate_rest_response', bool $translate, string $route, ?WP_REST_Request $request );

Whether a non-GET request’s reply may be translated. false by default, because a write usually echoes back what an author just saved — WooCommerce’s Store API opts its own cart and checkout writes back in here, since those replies answer a shopper, not an author.

apply_filters( 'localeeasy_translate_rest_write', bool $allowed, string $route, ?WP_REST_Request $request );

Whether an admin-ajax.php response is translated.

apply_filters( 'localeeasy_translate_ajax_response', bool $translate, string $action );

The action name LocaleReady uses to identify an AJAX request, for a plugin like WooCommerce that names its action in ?wc-ajax= rather than in the action parameter every other filter here sees.

apply_filters( 'localeeasy_ajax_action', string $action );

Whether a partly translated response may go out rather than falling back to source text as a whole — a cart whose product names are already known should not go back entirely untranslated over one unfamiliar label.

apply_filters( 'localeeasy_dynamic_partial_response', bool $partial, string $route );

Whether a dynamic response may wait synchronously for a translation provider rather than serving source text on a memory miss. false by default; think twice before enabling it for a route an anonymous visitor can POST to.

apply_filters( 'localeeasy_dynamic_translate_immediately', bool $immediate, string $locale, string $route );

Text domains read from a script’s own translated string catalog — WooCommerce’s React cart and checkout add their woocommerce domain here.

apply_filters( 'localeeasy_js_i18n_domains', string[] $domains );

Whether one outgoing message is translated at all — a cheap way to hold back a specific email whose wording is a legal matter.

apply_filters( 'localeeasy_translate_email', bool $translate, array $wp_mail_args );

The language one message is sent in. Return an empty string to send it in the site’s own language.

apply_filters( 'localeeasy_email_locale', string $locale, array $wp_mail_args );

The language remembered for whatever the email is about — an order, a form entry, a booking — written down while the visitor was still on the site. WooCommerce and Gravity Forms both answer this filter.

apply_filters( 'localeeasy_email_visitor_locale', string $locale, array $wp_mail_args );

Whether an address is one of the site’s own — an internal recipient never gets a visitor’s inferred language.

apply_filters( 'localeeasy_email_recipient_is_internal', bool $internal, string $address, array $wp_mail_args );

The language links a switcher is about to show, for every placement (block, shortcode, menu item, template tag) at once.

apply_filters( 'localeeasy_switcher_links', array $links, string $label_style );

The resolved options for one switcher, after the placement’s own settings and the site defaults have both been applied.

apply_filters( 'localeeasy_switcher_options', array $values, string $placement, array $overrides );

Return anything other than null to replace a switcher’s markup outright — including its stylesheet, since markup of your own wants styles of your own.

apply_filters( 'localeeasy_switcher_render', ?string $replacement, array $links, Switcher_Options $options );

The finished switcher markup, for a smaller change than replacing it entirely.

apply_filters( 'localeeasy_switcher_output', string $markup, array $links, Switcher_Options $options );

The og:locale value used for a language, in language_TERRITORY form.

apply_filters( 'localeeasy_og_locale', string $og_locale, string $locale );

The language a first-time visitor is about to be redirected to based on their browser. Return an empty string to leave them where they are.

apply_filters( 'localeeasy_redirect_locale', string $preferred, string[] $enabled );

Whether the page’s schema.org JSON-LD graph — printed by Yoast SEO or RankMath — is translated and its URLs rewritten.

apply_filters( 'localeeasy_translate_json_ld', bool $enabled, string $locale );

Post types checked, on save, for a locked or manual translation whose source sentence just disappeared. page and post by default.

apply_filters( 'localeeasy_stale_check_post_types', string[] $post_types );

Post types eligible for background translation on save, when that setting is turned on. page and post by default.

apply_filters( 'localeeasy_warmup_post_types', string[] $post_types );

Events, for logging, cache purging, or syncing to another system — none of these change any behavior by being hooked.

Fires once per provider that translated something on a request — the same event the Usage & limits table is built from.

do_action( 'localeeasy_provider_usage', array{ provider: string, segments: int, characters: int, requests: int } $usage );

Fires after a batch of automatic translations has been written for one locale.

do_action( 'localeeasy_translations_stored', string $locale, string[] $hashes );

Fires when a translation is changed from the Translations screen.

do_action( 'localeeasy_translation_updated', int $id, string $locale );

Fires when a translation is deleted from the Translations screen.

do_action( 'localeeasy_translation_deleted', int $id, string $locale );

Fires when translated output for an object or an entire locale becomes stale. A page cache or CDN in front of WordPress can hook this to purge its own copy rather than waiting for a TTL.

do_action( 'localeeasy_cache_invalidate', int $object_id, string $locale );