WP Provider Translate filters and actions reference
WP Provider Translate has a small set of WordPress filters and actions, all starting with wppt_, that let a theme or plugin tell the translation what it cannot work out on its own: which texts are content, which pages hold one visitor’s data, which requests are a page builder’s editor, and more. You add them with add_filter() and add_action() as usual, for example in a small must-use plugin or your theme’s functions.php.
Most sites never need them. The plugin already handles WooCommerce, Elementor and the page builders listed under Page builders by itself. For the commands you can run on the server, see WP-CLI commands.
Before you start
- Translated pages are cached. Filters that change a translated page run when the page is built, not on every visit. Return the same result for the same page and language, and never anything personal to one visitor.
- Load your code early. Add filters on
plugins_loadedor earlier (a must-use plugin is simplest), so they are in place before WP Provider Translate reads them. - Language codes are short codes such as
de,esorfr, the same ones you see in the language addresses.
wppt_output (filter)
What it is for. A last pass over a translated page, for things the plugin cannot know, such as a link or text inside a script your theme prints.
Signature.
apply_filters( 'wppt_output', string $output, string $lang ): string$output: the full HTML of the translated page.$lang: the language code of the page.- Return the (changed) HTML.
Example. Point a link in an inline script to the language version of the contact page.
add_filter( 'wppt_output', function ( $output, $lang ) { if ( 'de' === $lang ) { $output = str_replace( '"contactUrl":"\/contact\/"', '"contactUrl":"\/de\/kontakt\/"', $output ); } return $output;}, 10, 2 );When it runs. On the front end, each time a page in a target language is built, after all texts, links and images have been put in the language and before the page is stored in the plugin’s cache. It does not run for pages in your site’s own language.
wppt_may_extract (filter)
What it is for. Tell the plugin that a page shows one visitor’s data, so none of its text is ever sent for translation. The page is still shown in the language with the translations the site already has.
Signature.
apply_filters( 'wppt_may_extract', bool $may_extract ): bool$may_extract:trueby default.- Return
falsefor pages that show a visitor’s own data.
Example. A booking plugin shows the booking details on /booking/confirmation/.
add_filter( 'wppt_may_extract', function ( $may_extract ) { if ( is_page( 'booking-confirmation' ) ) { return false; } return $may_extract;} );When it runs. While a translated page is built for a visitor who is not logged in, on a GET or HEAD request. Text is never sent from logged-in views, previews or form posts anyway, so the filter is not asked there. WooCommerce order pages (order received, view order, order pay) already return false.
wppt_rest_routes (filter)
What it is for. Name REST routes whose responses carry page content, such as product lists a script loads. Responses from these routes, requested from a translated page, get their content translated by key (see wppt_json_keys) and their links in the language.
Signature.
apply_filters( 'wppt_rest_routes', string[] $routes ): string[]$routes: route prefixes, such as/wc/store/. Empty by default; WooCommerce adds/wc/store/itself.- Return the list with your prefixes added. Values that are not strings are ignored.
Example.
add_filter( 'wppt_rest_routes', function ( $routes ) { $routes[] = '/my-catalog/v1/products'; return $routes;} );When it runs. When a REST response is sent for a request made from a translated page, and when a translated page is built (to translate REST data that is preloaded into the page). A route matches when it starts with one of the prefixes.
wppt_json_keys (filter)
What it is for. The JSON keys whose string values are content to translate. They are used in JSON and JSON-LD script blocks in a page and in responses from the routes in wppt_rest_routes.
Signature.
apply_filters( 'wppt_json_keys', string[] $keys ): string[]$keys: by defaultname,description,short_description,headlineandcaption.- Return the list of keys.
Example. Your catalog route returns a tagline and a badge_text per product.
add_filter( 'wppt_json_keys', function ( $keys ) { return array_merge( $keys, array( 'tagline', 'badge_text' ) );} );When it runs. The first time JSON is translated during a request; the result is kept for the rest of that request. Address and customer data in a response are always left as they are.
wppt_json_attributes (filter)
What it is for. Some builders and blocks keep visible text as JSON inside an HTML attribute and show it with a script. This filter tells the plugin which attributes hold such text and which values in them are text.
Signature.
apply_filters( 'wppt_json_attributes', array $rules ): array$rules: attribute name => regular expression. Divi’sdata-et-multi-viewand WordPress’sdata-wp-contextare included by default.- The expression is matched against the dotted path of each string value in the JSON, such as
slides.title. Items of a list keep their parent’s path: every title in{"slides":[{"title":"…"}]}has the pathslides.title. - Write the attribute name in lowercase.
- Return the rules.
Example. A slider keeps its captions in data-slider-config.
add_filter( 'wppt_json_attributes', function ( $rules ) { $rules['data-slider-config'] = '#^slides\.(title|caption)$#'; return $rules;} );When it runs. The first time a page’s JSON attributes are read during a request, both when texts are collected and when a translated page is built. Attributes inside script, style, code, pre and similar elements are not read.
wppt_page_texts (filter)
What it is for. Texts a page shows only after the visitor does something, such as a form’s “Thank you” message, that your plugin knows on the server. Texts added here are translated together with the page, so they are ready before anyone sends the form. Elementor Pro form messages are added this way already.
Signature.
apply_filters( 'wppt_page_texts', string[] $texts, string $page, string $lang ): string[]$texts: texts added so far. Empty by default.$page: the address of the page in your site’s own language.$lang: the language code the page is being built in.- Return the list of texts, in your site’s own language. Simple HTML is allowed. Empty values are skipped.
Example.
add_filter( 'wppt_page_texts', function ( $texts, $page, $lang ) { if ( str_contains( $page, '/contact/' ) ) { $texts[] = get_option( 'my_form_success_message', 'Thank you, we will reply within two working days.' ); $texts[] = 'Please fill in your email address.'; } return $texts;}, 10, 3 );When it runs. Each time a page in a target language is built, while its texts are collected. Your filter must have run for the page by then, so register the texts from code that runs before the page is output (for example on init or wp), not from the form’s own submit handler.
wppt_visitor_values (filter)
What it is for. Values that belong to one visitor, such as an order number or a name. Before a text is sent for translation, each value is replaced by a placeholder, so the sentence is translated once for everybody and the value itself never leaves your site. The value is put back into the translation.
Signature.
apply_filters( 'wppt_visitor_values', string[] $values, string $url ): string[]$values: values the plugin found in the address’s query string: search terms, and values of 3 characters or more that contain a digit or an@.$url: the address of the page in your site’s own language, with its query string. For a script’s request (AJAX or REST), it is the address of the page the request came from, as the browser reports it.- Return the list. Values shorter than 3 characters are dropped.
Example. A membership plugin greets the member by name on the account page.
add_filter( 'wppt_visitor_values', function ( $values, $url ) { $user = wp_get_current_user(); if ( $user->exists() ) { $values[] = $user->display_name; } return $values;}, 10, 2 );When it runs. When a translated page is built, and when a script’s request from a translated page is answered with translated text.
wppt_is_editor_request (filter)
What it is for. Mark a request as a front-end page builder’s editor. Editors are never translated or cached, and an editor opened on a language address moves to the address in your site’s own language, where the page is edited. Elementor, Divi, Beaver Builder, Bricks, Oxygen, Breakdance, Brizy, Thrive Architect, Avada and WPBakery are recognised already.
Signature.
apply_filters( 'wppt_is_editor_request', bool $is_editor, array $query ): bool$is_editor: whether the plugin recognised a known editor.$query: the request’s query parameters ($_GET, unslashed).- Return
truefor your builder’s editor.
Example. Your builder opens its editor with ?my_builder=edit.
add_filter( 'wppt_is_editor_request', function ( $is_editor, $query ) { return $is_editor || ( isset( $query['my_builder'] ) && 'edit' === $query['my_builder'] );}, 10, 2 );When it runs. Early in every front-end request, before the language address is handled, and again before a page is translated.
wppt_text_groups (filter)
What it is for. Texts that are not on a page, such as WooCommerce emails and payment texts, are listed as named groups on the Translations screen. This filter holds those groups, their names and, optionally, a preview that shows the texts as the reader sees them.
Signature.
apply_filters( 'wppt_text_groups', array $groups ): array$groups: group id => settings. Each group has alabel(string), and may have apreviewwith two callables:options(returns choice id => label, for example one entry per email) andrender(receives the choice id and a locale, and returns an array withhtmland optionallysubject, ornull).- Return the groups.
Texts only appear in a group when the plugin records them under that group’s id. The built-in groups are woocommerce-email-templates and woocommerce-settings.
Example. Give the WooCommerce groups names your shop team uses.
add_filter( 'wppt_text_groups', function ( $groups ) { if ( isset( $groups['woocommerce-email-templates'] ) ) { $groups['woocommerce-email-templates']['label'] = 'Order emails'; } return $groups;}, 20 );Use a priority above 10 so your change runs after the plugin has added its groups.
When it runs. In wp-admin, when the Translations screen and its previews are shown.
wppt_flag (filter)
What it is for. Choose the flag the language switcher shows for a language. For your site’s own language the plugin uses the country of your WordPress locale (for example be for nl_BE); for the other languages a default country.
Signature.
apply_filters( 'wppt_flag', string $flag, string $code ): string$flag: two-letter country code of the flag, such asus.$code: the language code, such asen.- Return a country code. The plugin ships its flags as SVG files named by country code, so return a country it has a flag for.
Example. Show the British flag for English.
add_filter( 'wppt_flag', function ( $flag, $code ) { return 'en' === $code ? 'gb' : $flag;}, 10, 2 );When it runs. Each time a language switcher shows a flag. See Language switcher options for where flags are turned on.
wppt_cross_domain_cookies (filter)
What it is for. When a language has its own domain, a visitor who switches language moves to another domain, and cookies do not travel by themselves. This filter lists the cookies, by name prefix, that the plugin carries along. WooCommerce’s session and cart cookies are included already, so the cart follows the visitor.
Signature.
apply_filters( 'wppt_cross_domain_cookies', string[] $prefixes ): string[]$prefixes: cookie name prefixes. Empty by default; WooCommerce adds its own.- Return the list. Empty values are dropped.
Example. Keep a wishlist plugin’s cookie.
add_filter( 'wppt_cross_domain_cookies', function ( $prefixes ) { $prefixes[] = 'my_wishlist_'; return $prefixes;} );When it runs. When a visitor follows a link to a language on another domain. Only relevant when you use a domain per language.
wppt_carry_login (filter)
What it is for. A logged-in user who switches to a language on another domain stays logged in. Return false to stop that, for everyone or for some users.
Signature.
apply_filters( 'wppt_carry_login', bool $carry, WP_User $user ): bool$carry:trueby default.$user: the logged-in user.- Return
falseto not carry the login.
Example. Administrators log in again on each domain.
add_filter( 'wppt_carry_login', function ( $carry, $user ) { return in_array( 'administrator', (array) $user->roles, true ) ? false : $carry;}, 10, 2 );When it runs. When a logged-in user follows a link to a language on another domain, and only over HTTPS. Without HTTPS the login is never carried.
wppt_crawl_extra (action)
What it is for. Near the end of the site crawl, the plugin renders pages that need something extra, such as the cart and checkout with a product in the cart, and repeats requests that scripts made on your pages before. Hook in here to render your own pages that a plain visit does not show, so their text is translated before the first visitor sees them.
Signature.
do_action( 'wppt_crawl_extra' )No parameters.
Example. Open a page in each language with the query string that shows its extra step. A page in a target language that is opened by a visitor who is not logged in queues its new text, so a plain request is enough.
add_action( 'wppt_crawl_extra', function () { foreach ( array( '/de/configurator/', '/fr/configurateur/' ) as $path ) { wp_remote_get( add_query_arg( 'step', 'summary', home_url( $path ) ), array( 'timeout' => 30 ) ); }} );Leave visitor data out of these requests: do not log in, and do not add an email address or personal code to the address.
When it runs. Once per crawl, after all pages have been rendered, just before wppt_stored_texts. The crawl runs in the background after you choose languages, and with wp wpprovider-translate crawl.
wppt_crawl_pages (filter)
What it is for. The crawl follows lists that continue on more pages (blog, categories, shop, query loops, “load more” buttons), so text only a later page shows, such as excerpts, is translated before the first visitor opens it. This filter sets how far it follows each list.
Signature.
apply_filters( 'wppt_crawl_pages', int $pages ): int$pages: the highest page number of one list the crawl renders. 20 by default.- Return a number.
1turns following lists off.
Example. A large shop with long category pages.
add_filter( 'wppt_crawl_pages', function () { return 50;} );When it runs. During the crawl, each time a page has been rendered and its links to next pages are read.
wppt_stored_texts (action)
What it is for. The moment the plugin queues texts that are saved in settings and that no page shows, such as WooCommerce email subjects, headings, footers and payment method texts. The built-in WooCommerce support hooks in here.
Signature.
do_action( 'wppt_stored_texts' )No parameters.
The plugin does not offer a public function to queue your own texts from this action. To get a text translated that only appears after an action on a page, use wppt_page_texts instead. You can use this action to run your own code at the same moment, for example to log it.
Example.
add_action( 'wppt_stored_texts', function () { error_log( 'WP Provider Translate is queueing texts from settings.' );} );When it runs. At the end of every crawl, after wppt_crawl_extra, and each time you run wp wpprovider-translate texts.
wppt_purge_urls (action)
What it is for. Tells a page cache which language pages to drop, so visitors get the new translation instead of an old cached copy. LiteSpeed Cache, WP Rocket, W3 Total Cache, WP Super Cache and SiteGround Speed Optimizer are purged by the plugin itself; use this action for any other page cache or a CDN. See Caching plugins.
Signature.
do_action( 'wppt_purge_urls', string[] $urls )$urls: full addresses of the language pages to drop from the cache.
Example. Purge the addresses on a reverse proxy that accepts PURGE requests.
add_action( 'wppt_purge_urls', function ( $urls ) { foreach ( $urls as $url ) { wp_remote_request( $url, array( 'method' => 'PURGE', 'blocking' => false ) ); }} );When it runs.
- When new translations arrive for texts on those pages.
- When someone edits a translation in WordPress.
- When a published post is saved: its language pages are dropped before they are built again.
It does not run when the list is empty.
Troubleshooting
- My filter has no effect. Check that it is added before the page is built, ideally in a must-use plugin or on
plugins_loaded. Then make the page build again: a translated page is kept in the plugin’s cache until the page in your own language changes or a translation in that language is edited. Change the page, then open it in the language as a visitor who is not logged in. - A text I added with
wppt_page_textsstays in the original language. New texts are translated in the background. Runwp wpprovider-translate syncor wait a few minutes, then load the page again. See How translation runs. - A JSON text is still not translated. Check the path in your
wppt_json_attributespattern: list items have no number in their path, and the attribute name must be in lowercase.