WP Residence Help WP Residence Help

  • WpEstate
  • WPRESIDENCE
  • Video Tutorials
  • Client Support
  • API
Home / 30. WPResidence Translate Plugin / Taxonomy Translation — Developer Guide

Taxonomy Translation — Developer Guide

1 view 0

This article maps the taxonomy translation subsystem in the wpresidence-translate plugin (text domain wpr-translate). It covers the settings storage, the term duplication pipeline, the hierarchy synchronizer, admin list-table filters, and the adv6 search compatibility shim. For the broader plugin architecture underpinning a multi-language real estate website, see the plugin overview.

Files In Scope

File Role
includes/translation-taxonomies.php Runtime: mode resolution, term duplication, hierarchy sync, term-list filters.
includes/admin/taxonomy-translation.php Admin UI helpers: columns, language filter views, add-translation request handler, edit-term panel.
includes/admin/taxonomy-metabox-filters.php Post-editor metabox filters (get_terms_args, terms_clauses, get_terms, get_the_terms).
includes/admin/views/settings-taxonomy.php Settings screen view (posted to options.php, group wpr_translate_settings).
includes/adv6-terms-compat.php Maps wp_estate_adv6_taxonomy_terms term IDs to the active language.

Settings Storage

Everything lives under the single plugin option wpr_translate_settings:

array(
    'taxonomy_modes'          => array( $taxonomy_slug => 'translate' | 'not_translatable' ),
    'taxonomy_auto_duplicate' => array( $taxonomy_slug => bool ),
    ...
)

Readers:

  • wpr_translation_get_taxonomy_modes_settings()
  • wpr_translation_get_taxonomy_mode( $taxonomy ) — default translate.
  • wpr_translation_is_taxonomy_translatable( $taxonomy ) — main gate used everywhere.
  • wpr_translation_get_taxonomy_auto_duplicate_settings()
  • wpr_translation_is_taxonomy_auto_duplicate_enabled( $taxonomy )

The settings view at includes/admin/views/settings-taxonomy.php renders a row per public taxonomy and preserves hidden values for taxonomies not in the current form (so a temporarily-hidden CPT does not lose its preference).

Element Type & Translation Groups

Each taxonomy maps to a translation element type via wpr_translation_get_taxonomy_element_type( $taxonomy ). Translation groups are stored in {$wpdb->prefix}wpestate_translation_translations with columns including element_id, element_type, trid, language_code, source_language_code, original, and needs_update.

Lookup helpers (defined elsewhere in the plugin but called here):

  • wpr_translation_get_translation_group( $term_id, $element_type ) — returns { trid, translations[code => id], source_language }.
  • wpr_translate_resolve_original_term_id( $term_id, $taxonomy ) — canonical anchor via term meta.
  • wpr_translate_lookup_translated_term_id_strict( $canonical_id, $taxonomy, $language ) — strict mapping with no fallback.
  • wpr_translate_link_term_translation_meta( $source, $target, $language, $taxonomy ) — writes meta linkage (wpr_original_term_id and language code).

Term Duplication Pipeline

wpr_translation_duplicate_term_for_language( $source_term_id, $taxonomy, $target_language, $args ) is the entry point. It:

  1. Validates inputs and rejects non-translatable taxonomies.
  2. Resolves the canonical source via wpr_translate_resolve_original_term_id().
  3. Short-circuits if a translation already exists (meta-first lookup, then translation group).
  4. Resolves the translated parent term id for hierarchical taxonomies.
  5. Generates a unique slug with wp_unique_term_slug().
  6. Sets the global guard $GLOBALS['wpr_translation_creating_term_translation'] to suppress recursive created_term handling.
  7. Calls wp_insert_term(). On term_exists error it reuses the existing ID.
  8. Copies term meta via wpr_translation_duplicate_term_meta() and the legacy taxonomy_{term_id} option (resetting category_tagline).
  9. Links meta and writes a row to the translation table via wpr_translation_insert_translation_record().

Created / Edited / Deleted Term Hooks

Action Callback What it does
created_term (pri 20) wpr_translation_handle_created_term Generates a new trid, inserts the source record, and fans out duplication to all other languages when auto-duplicate is enabled.
edited_term (pri 20) wpr_translation_handle_edited_term Reads wpr_translation_term_language and wpr_translation_term_source from POST (with nonce wpr_translation_term_language_{term_id}), updates the group, and syncs hierarchy.
delete_term (pri 20) wpr_translation_handle_deleted_term Removes the translation row; if the deleted term was the original, promotes another translation to original via translation_id update.

Hierarchy Sync

wpr_translation_sync_term_translation_hierarchy( $term_id, $taxonomy ) loads the parent’s translation group, finds the per-language translated parent ID, and calls wp_update_term() on each sibling with the correct parent. The recursion guard $GLOBALS['wpr_translation_syncing_term_parents'] prevents re-entry through edited_term while the sync is running.

Front-End Term Filtering

wpr_translation_filter_terms_for_hidden_modes() hooks get_terms at priority 20. It:

  • Skips admin, REST (wpr_translate_language_router_is_rest_request()), and non-translatable taxonomies.
  • Resolves the current language via wpr_translate_get_current_language(), falls back to wpestate_get_current_language().
  • For each term: resolves canonical id, then looks up the language-specific id (wpr_translate_lookup_translated_term_id_strict). For the default language, canonical is always used.
  • For modes where untranslated terms should not be hidden (wpr_translation_should_hide_untranslated_terms()), falls back to canonical so output does not disappear.
  • Rebuilds the result respecting $args['fields'] — supports all, ids, tt_ids, names, id=>parent, id=>name, id=>slug.
  • Deduplicates by taxonomy|parent|lowercase(name) to avoid duplicate labels.

wpr_translation_force_terms_filters_args() hooks get_terms_args and forces suppress_filters = false when any queried taxonomy is translatable, so the filter above can actually run.

Admin List Table & Edit Screen

Registered in wpr_translation_bootstrap_taxonomy_admin():

add_action( 'admin_init',      'wpr_translation_setup_taxonomy_columns' );
add_action( 'admin_init',      'wpr_translation_handle_add_term_translation_request' );
add_action( 'current_screen',  'wpr_translation_register_taxonomy_language_filter_hooks' );
add_action( 'edit_term_form',  'wpr_translation_render_term_language_panel', 10, 2 );

The language filter injects per-language views into views_{screen_id} with a wpr_term_language query var. The add-translation handler nonces requests using wpr_translation_get_term_translation_nonce_action( $term_id, $taxonomy, $language ).

Screenshot: The term edit screen showing the language panel with language picker and source-term selector

Post Editor Metabox Filters

includes/admin/taxonomy-metabox-filters.php registers filters on current_screen and uses the four-filter pattern documented at the top of the file:

get_terms_args   -> high-level arg adjustments
terms_clauses    -> SQL JOIN/WHERE for language
get_terms        -> post-query list filtering
get_the_terms    -> per-post term list filtering

Advanced Search (adv6) Compatibility

wpr_translate_filter_adv6_terms_in_theme_options() in adv6-terms-compat.php hooks the WPResidence theme options and rewrites wp_estate_adv6_taxonomy_terms so that term IDs configured by admins for the advanced search tab are mapped to their current-language equivalents. This keeps “For Sale / For Rent” and similar action filters pointing at the right terms in every language, using the same wpr_translate_resolve_original_term_id and wpr_translate_lookup_translated_term_id_strict pair as the main filter.

Screenshot: The WPResidence advanced search tab configuration showing mapped term IDs

Extension Points

  • Add or remove translatable taxonomies by writing directly to wpr_translate_settings['taxonomy_modes'] in a migration.
  • Skip a specific taxonomy from auto-duplication by setting its taxonomy_auto_duplicate entry to false.
  • Use suppress_filters = true on get_terms / WP_Term_Query when you explicitly need the raw cross-language term list (e.g. admin exports).
  • Override wpr_translate_lookup_translated_term_id_strict via a plugin if you need a custom resolver — it is called everywhere through function_exists() checks.

Gotchas

  • The delete_term handler promotes a replacement only when the deleted term was the group’s original — non-original deletions simply drop the mapping row.
  • Non-Latin slugs: wp_unique_term_slug() uses sanitize_title(), which transliterates. If you need to preserve the original script, pre-set a slug before calling wp_insert_term().
  • The hierarchy sync only runs for taxonomies marked hierarchical in register_taxonomy().
  • REST requests are intentionally skipped by the term filter — term assignment UIs must see the full cross-language term pool.

Related Reading

  • Translation Linking (trid system) — the shared TRID mechanism used for both posts and terms.
  • WP_Query Language Filtering — the sibling subsystem for posts.
  • Database Schema — structure of the translations table.

Product context: multi-language real estate website.

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