WP Residence Help WP Residence Help

  • WpEstate
  • WPRESIDENCE
  • Video Tutorials
  • Client Support
  • API
Home / 30. WPResidence Translate Plugin / WPResidence Translate — Performance & Caching (Developer Reference)

WPResidence Translate — Performance & Caching (Developer Reference)

1 view 0

This article maps the cache layers inside the WPResidence Translate plugin (wpestate-translate, text domain wpr-translate) so you can reason about invalidation, extend it safely from a child theme or companion plugin, and keep a multi-language real estate website fast at scale.

Cache Layers Overview

Layer Scope API Where
Request-scoped static Single PHP request static $cache arrays in functions includes/translation-runtime.php
Object cache Persistent if drop-in installed wp_cache_get() / wp_cache_set() in group wpr_translate includes/custom-fields-sync.php
Transients (per language) Cross-request, expiring set_transient() / delete_transient(), names suffixed per language Theme search lists; includes/elementor-widget-compat.php; includes/admin/theme-transients.php
Theme cache-purge Whole-site admin-post.php?action=wpestate_purge_cache includes/admin/cache-purge.php

Screenshot: diagram showing the four cache layers stacked above the translations and strings tables

Per-Request Static Caches

Runtime string lookups are hot-path code — they run on every gettext filter for every translated string on every page. To keep the database touch low, translation-runtime.php memoizes results inside each request:

// includes/translation-runtime.php
function wpr_translate_domain_has_runtime_translations( $domain, $language_code ) {
    static $cache = array();
    $cache_key = strtolower( $domain ) . '|' . strtolower( $language_code );
    if ( array_key_exists( $cache_key, $cache ) ) {
        return (bool) $cache[ $cache_key ];
    }
    // ... wpdb query against wp_wpestate_translation_strings ...
    $cache[ $cache_key ] = $found;
    return $found;
}

function wpr_translate_lookup_runtime_translation( $domain, $original, $language_code ) {
    static $cache = array();
    $cache_key = strtolower( $domain ) . '|' . md5( $original ) . '|' . strtolower( $language_code );
    if ( array_key_exists( $cache_key, $cache ) ) {
        return $cache[ $cache_key ];
    }
    // ... wpdb query ...
    $cache[ $cache_key ] = $value;
    return $value;
}

Key design points:

  • Keys are lowercased and the original string is hashed with md5() so UTF-8 strings are safe in a static array.
  • Empty results are cached too — this matters: negative lookups dominate in the admin-only runtime override path.
  • There is no cross-request persistence here on purpose. Runtime string translation only applies in admin editor contexts (see wpr_translate_should_use_runtime_translations()), and each admin page load is short-lived.

If you add new lookup functions, follow the same pattern. Do not reach for wp_cache_set() here — these are request-scoped by design, and a persistent cache would make staleness harder to reason about.

Object Cache — Custom Field Preferences

The Custom Field Rules are loaded from a JSON configuration file and cached under the wpr_translate object cache group:

// includes/custom-fields-sync.php
$option_name = 'wpr_cf_preferences';
$cache_key   = 'wpr_cf_preferences';
$cache_group = 'wpr_translate';

wp_cache_set( $cache_key, $preferences, $cache_group );
$cached = wp_cache_get( $cache_key, $cache_group );

The priming flow (wpr_translate_prime_custom_fields_preferences_cache()) compares an md5 hash of the config file contents against the cached payload. If the file changed, the plugin re-reads the JSON, re-writes the wpr_cf_preferences option, and overwrites the cache entry.

Extending: If you ship a child plugin that writes to the same rules config, either call wpr_translate_sync_custom_fields_preferences() after your write, or invalidate directly with wp_cache_delete( 'wpr_cf_preferences', 'wpr_translate' ).

Per-Language Transients — Theme Search Lists

The WPResidence theme caches its large taxonomy lookup lists as transients. On a multilingual site each language has its own set. The helper wpestate_set_transient_name_multilang() (theme side) appends the active language to the transient name so callers never juggle suffixes manually.

The canonical cached keys (base names before language suffix):

wpestate_get_action_select_list
wpestate_get_category_select_list
wpestate_get_city_select_list
wpestate_get_area_select_list
wpestate_get_county_state_select_list
wpestate_get_status_select_list
wpestate_get_features_select_list

Invalidation is centralized in includes/admin/theme-transients.php:

// includes/admin/theme-transients.php
function wpr_translate_admin_clear_theme_search_transients( $context ) {
    // Only act for the theme admin-strings domain (or the legacy 'wpresidence_admin').
    // Build the list of language IDs (slug + code) from wpr_translate_get_active_languages().
    foreach ( $keys as $key ) {
        delete_transient( $key );                         // base, no language
        foreach ( $language_ids as $language_id ) {
            delete_transient( $key . '_' . $language_id ); // per-language variants
        }
    }
}

This runs whenever admin-facing theme strings change, so translated dropdown labels stay in sync without manual purges. The function also honors ICL_LANGUAGE_CODE to cover sites migrating from WPML compatibility shims.

Elementor taxonomy widgets prime their own transients via the same multilang helper — see includes/elementor-widget-compat.php:

// includes/elementor-widget-compat.php
$primed_transient_key = 'wpestate_elementor_tax_';
if ( function_exists( 'wpestate_set_transient_name_multilang' ) ) {
    $primed_transient_key = (string) wpestate_set_transient_name_multilang( $primed_transient_key );
}
set_transient( $primed_transient_key, $primed_terms, 60 * 60 * 6 );

TTL is 6 hours. Invalidation is lazy — on the next language switcher render after expiry, the cache refills from the terms table.

Theme-Wide Cache Purge Endpoint

includes/admin/cache-purge.php exposes an AJAX bridge that triggers the WPResidence theme’s own purge action:

// includes/admin/cache-purge.php
function wpr_translate_purge_wpestate_cache() {
    $purge_url = admin_url( 'admin-post.php' );
    $nonce     = wp_create_nonce( 'wpestate_purge_cache' );
    // ... copies cookies for auth, POSTs to admin-post.php ...
    wp_remote_post( $purge_url, array(
        'body' => array(
            'action'   => 'wpestate_purge_cache',
            '_wpnonce' => $nonce,
        ),
        // ...
    ) );
}
add_action( 'wp_ajax_wpr_translate_purge_cache', 'wpr_translate_ajax_purge_cache' );

Called by the bulk auto-translate screen when a batch finishes. Gated by manage_options and a dedicated nonce (wpr_translate_purge_cache). Re-use this endpoint from your own admin flows after operations that touch many posts.

Query Filter & Cache Interaction

includes/query-filter.php applies the active language to WP_Query via pre_get_posts and the_posts. A few caching considerations follow from that:

  • Cached query results must be language-scoped. Anything you cache that wraps a WP_Query should include the active language code (or slug) in the cache key. Use the wpestate_set_transient_name_multilang() helper, or derive the code via wpr_translate_get_current_language().
  • suppress_filters bypasses language filtering. Callers that intentionally want cross-language results should set 'suppress_filters' => true or opt out via the plugin’s documented query vars. Never do this silently from inside a cached helper.
  • Avoid meta_key at WP_Query top level when not needed — it forces an INNER JOIN that silently drops posts without that key. Not a cache rule per se, but combined with caching it can freeze bad results.

Settings-Errors Transients

Admin screens use short-lived (30-second) settings_errors transients to carry notices across a redirect:

// includes/admin/menu.php, includes/admin/string-actions.php, includes/admin/reset-settings.php
set_transient( 'settings_errors', get_settings_errors(), 30 );

These are unrelated to content caching — they are the standard WordPress pattern for post-submit notice survival. No invalidation needed; they self-expire.

Screenshot: stack trace showing request flow from gettext filter through static cache to wp_wpestate_translation_strings

Extension Points & Recipes

  • Adding a cached helper that depends on active language — key with wpestate_set_transient_name_multilang( 'your_base_key' ) so the plugin’s existing invalidators (see theme-transients.php) cover you when you pick compatible base names.
  • Bypassing cache for diagnostics — clear the static caches by forcing a fresh PHP process (new request); they have no public reset. For the object cache, use wp_cache_delete( 'wpr_cf_preferences', 'wpr_translate' ).
  • Clearing transients after bulk operations — call wpr_translate_admin_clear_theme_search_transients( 'wpresidence_admin' ). Pass the theme admin strings context to match the guard clause.
  • Flushing the whole theme cache — fire the AJAX endpoint wp_ajax_wpr_translate_purge_cache with the wpr_translate_purge_cache nonce, or call wpr_translate_purge_wpestate_cache() directly from PHP with an authenticated admin context.

Non-Latin Safety

All cache keys avoid sanitize_title() on user-supplied strings. Language codes go through sanitize_key(), translated values are hashed with md5() before being used as key fragments. Cyrillic, Arabic, and CJK language data caches identically to Latin data — there is no separate slow path.

Gotchas

  • Static caches do not clear on option save. If you write admin code that updates a translation mid-request and then reads it back, expect stale results in the same request. Re-query directly or reset the static in tests via a dedicated hook.
  • Transient TTLs are not adaptive. The 6-hour TTL on Elementor primed terms means a term renamed through WP admin might take up to 6 hours to reflect in some widgets, unless the plugin’s save hooks clear the specific key. Clear explicitly after bulk term updates.
  • The cache-purge endpoint is whole-site. Use it for post-batch jobs, not per-edit — you will hurt front-end performance if you call it on every save.
  • Reactivation does not clear transients. Activation runs flush_rewrite_rules() only. Stale caches survive deactivate/activate; delete them explicitly if you need a clean slate.

Further Reading

  • Database Schema — the tables the caches front.
  • Cache Purge & Reset Tools — the admin-side counterparts to this reference.
  • WP_Query Language Filtering — how pre_get_posts interacts with cached results.
  • Automatic Translation (OpenAI, Google, DeepL, Azure) — the flows that trigger wpr_translate_purge_wpestate_cache().

For broader context on running a multi-language real estate website on WPResidence, see the product page.

30. WPResidence Translate Plugin

Related Articles

  • String Scanner — Developer Guide
  • The String Scanner
  • Gettext Pipeline & MO Files — Developer Guide
  • Gettext & MO Files — Making Translations Appear on the Front End

WP Residence Documentation

  • 01. Getting Started
    • How to Get Support
    • Get your buyer license code.
    • Use SSL / https
    • Server / Theme Requirements
  • 02. Installation & Setup
  • 03. Installation FAQ
  • 06. Search & Filtering
    • Advanced Search Display Settings
    • Advanced Search Form
    • Geolocation Search for Half Map
    • Save Search Theme Options
    • Advanced Search Colors
  • 09. Agent, Agency & Developers
  • 08. Property Pages & Layouts
  • 07. Property Lists, Categories & Archive
  • 13. WPResidence Elementor Studio
  • 10. Blog Posts & Blog List
  • 11. Shortcodes
    • Contact Form
    • Featured Agency/Developer
    • Membership Packages
    • Testimonials
    • Google Map with Property Marker
    • Listings per Agent, Agency or Developer
    • Display Categories
    • Agent List
    • Recent Items Slider
    • Recent items
    • List Properties or Articles by ID
    • Featured Agent
    • Featured Article
    • Featured Property
    • Login & Register Form
    • Icon Content Box Shortcode
  • 12. Widgets
  • 04. Theme Options & Global Settings
    • General Settings
    • User Types Settings
    • Appearance
    • Logos & Favicon
    • Header
    • Footer Style and Colors
    • Price & Currency
    • Property Custom Fields
    • Features & Amenities
    • Listing Labels
    • Theme Slider
    • Permalinks
    • Splash Page
    • Social & Contact
    • Map Settings
    • Pin Management
    • How read from file works
    • General Design Settings
    • Custom Colors Settings
    • Header Design & Colors
    • Mobile Menu Colors
    • User Dashboard Colors
    • Print PDF Design
    • Property, Agent, Blog Lists Design Settings
    • Sidebar Widget Design
    • Font management
    • How to add custom CSS
    • Custom Property Card Unit – Beta version
    • Email Management
    • Import & Export theme options
    • reCaptcha settings
    • YELP API Integration
    • iHomefinder Optima Express IDX
    • MEMBERSHIP & PAYMENT Settings
    • Property Submission Page
    • PayPal Setup
    • Stripe Setup
    • Wire Transfer Payment Method
  • 20. Translations & Languages
  • 26. FAQ
  • 10. Pages
  • 11. Header
  • 12. Footer
  • 05. Maps & Location Settings
  • 18. Payments & Monetization
  • Plugins
    • 19. Included Plugins
    • 22. Third Party Plugins – IDX Compatibility
    • 21. Third-Party Plugins – Multi-Language
    • 23. Third party Plugins – Other
  • Technical
    • 24. Technical how to | Custom Code Required
    • 25. Technical: Child Theme

Join Us On

Powered by WP Estate - All Rights Reserved
  • WpEstate
  • WPRESIDENCE
  • Video Tutorials
  • Client Support
  • API