WP Residence Help WP Residence Help

  • WpEstate
  • WPRESIDENCE
  • Video Tutorials
  • Client Support
  • API
Home / 30. WPResidence Translate Plugin / Language Switcher Widget — Developer Reference

Language Switcher Widget — Developer Reference

1 view 0

This article documents the frontend language switcher widget shipped with wpresidence-translate. It covers registration, option storage, render pipeline, translation-target resolution, and the inline script that handles cookie persistence and navigation. The user-facing sibling explains the site-owner workflow; for the product overview see the multi-language real estate website guide.

Source Files

File Role
includes/widgets/language-switcher.php Widget bootstrap — registers the sidebar widget and control via wp_register_sidebar_widget() / wp_register_widget_control().
includes/widgets/language-switcher-options.php Instance storage helpers (wpr_translate_language_switcher_get_options(), _save_options(), _next_number()).
includes/widgets/language-switcher-display.php Frontend render — wpr_translate_language_switcher_widget_display() and wpr_translate_render_language_switcher_dropdown().
includes/widgets/language-switcher-control.php Admin form renderer at Appearance > Widgets — single Title field.

Registration

The widget uses the legacy wp_register_sidebar_widget() API rather than WP_Widget because the plugin intentionally keeps multiple instances behind a single option. wpr_translate_register_language_switcher_widget() loops saved instances and registers each, plus a catch-all id for the widgets screen.

$widget_ops = array(
    'classname'   => 'wpr-language-switcher-widget',
    'description' => __( '...', 'wpr-translate' ),
);
$control_ops = array( 'id_base' => 'wpr_translate_language_switcher' );

Instance numbers start at 1 and increment via wpr_translate_language_switcher_next_number(). Registered IDs follow the pattern wpr_translate_language_switcher-{N}.

Option Storage

All instances live under a single option:

Option key Shape
wpr_translate_language_switcher (constant WPR_TRANSLATE_LANGUAGE_SWITCHER_OPTION) array( int $number => array( 'title' => string ) )

Helpers sort the array by numeric key, sanitize titles through sanitize_text_field(), and delete the option when no instances remain.

Screenshot: wp_options row for wpr_translate_language_switcher with serialized instance map

Render Pipeline

wpr_translate_language_switcher_widget_display( $args, $widget_args ) is the display callback. In order it:

  1. Loads saved options and resolves the instance title by $widget_args['number'].
  2. Calls wpr_translate_get_active_languages() and bails when fewer than 2 languages exist.
  3. Detects the current context — is_singular(), get_queried_object() for WP_Term, global $post fallback.
  4. Resolves the current language via wpr_translate_get_context_language( $current_post_id ); for term archives it overrides with wpr_translate_get_element_language( $term_id, 'tax_{taxonomy}' ).
  5. Builds a $translation_map — language code to target post/term ID — using wpr_translation_get_translation_group() for posts and wpr_translate_lookup_translated_term_id_strict() for terms.
  6. Computes a fallback post URL via wpr_translation_get_post_language_permalink(), falling back to get_permalink().
  7. Iterates languages, builds per-language payload (code, label, flag URL, target URL, router URL, fallback URL, cookie flag), and emits <li> items.
  8. Delegates to wpr_translate_render_language_switcher_dropdown() for the Bootstrap dropdown shell.
  9. Emits a small inline script that wires clicks, updates the button label/flag, stores the cookie preference, and navigates.

Output Shape

<div id="wpr-language-switcher-{widget_id}" class="dropdown wpr-language-switcher"
     data-current-post-id="…" data-current-language-code="…"
     data-flag-alt-template="%s flag">
  <button class="btn dropdown-toggle wpr-language-switcher-toggle"
          data-bs-toggle="dropdown" aria-expanded="false">…</button>
  <ul class="dropdown-menu wpr-language-switcher-menu">
    <li role="presentation">
      <button class="dropdown-item wpr-language-switcher-item"
              data-language-code="fr" data-translation-id="123"
              data-target-url="…" data-router-url="…"
              data-fallback-url="…" data-can-set-cookie="1"
              data-flag-url="…" data-label="Français">…</button>
    </li>
  </ul>
</div>

When the widget is injected into a WPRentals header menu, the helper wpr_translate_is_wprentals_theme_active() adds sub-menu, menu-item, and menu-item-link classes plus Bootstrap-3 data-toggle="dropdown" for compatibility.

Target URL Resolution

For each language the widget picks the best URL in this priority:

  1. Direct translation — wpr_translation_get_post_language_permalink() for posts or get_term_link() for terms.
  2. Front-page root — when the current post is the front page (or one of its translations), the language root URL from wpr_translate_language_router_get_switch_url().
  3. Fallback post/term URL — the default-language permalink of the current post or term, if any.
  4. Router URL — wpr_translate_language_router_get_switch_url( $language ) for archives, search, 404s.

The data-can-set-cookie attribute is 0 when the URL is a fallback (no real translation) so the cookie is not stuck on a language the visitor did not intentionally pick.

Cookie Persistence

On click, the inline script POSTs to admin-ajax.php with action=wpr_translate_set_language_cookie, the selected language code, a wp_create_nonce('wpr_translate_language_cookie'), and current_post_id. The transport preference order is navigator.sendBeacon, fetch with keepalive: true, and finally XMLHttpRequest so navigation is not delayed.

The server stores the choice under the cookie wpestate_translation_lang_pref, which wpr_translate_resolve_preferred_language() reads on subsequent requests.

Screenshot: Browser DevTools Application tab showing the wpestate_translation_lang_pref cookie

Flags

Flag URLs are constructed with WPR_TRANSLATE_URL . 'assets/img/flags/4x3/{code}.svg'. The widget uses the language’s explicit flag field first and falls back to the language code if no flag is set. Missing flags render an <img> with no src and the hidden-state class wpr-language-switcher-flag--hidden so the layout stays intact.

Menu Injection

$args['wpr_translate_menu_injected'] tells the display callback it is rendering inside a WordPress nav menu rather than a standalone widget area. Combined with wpr_translate_is_wprentals_theme_active(), this toggles WPRentals-compatible markup. Menu injection itself is handled by nav-menu-locations-frontend.php — outside the scope of this article.

Elementor Widget

There is no dedicated Elementor language switcher widget in either the plugin or residence-elementor at this time. For Elementor layouts, drop a standard WordPress widget area or use a shortcode/widget via the Sidebar widget. The legacy WPResidence theme widget WP_Estate_Translation continues to work for older sites, but new integrations should use the widget documented here.

Extension Tips

  • Do not guard on $_SERVER['HTTP_ACCEPT_LANGUAGE']. The widget never renders different markup per visitor — language detection happens via cookie on click, not at render time.
  • Multiple instances: each instance is keyed by its number, and the wrapper ID is derived from $args['widget_id']. Two instances on the same page each get their own handlers.
  • Styling: hook your theme CSS on .wpr-language-switcher, .wpr-language-switcher-toggle, and .wpr-language-switcher-item. Avoid overriding the inline script.
  • Translation-group helpers: if you are building a custom switcher, reuse wpr_translation_get_translation_group() and wpr_translation_get_post_language_permalink() rather than reading the trid tables directly.

Related Articles

  • Managing Languages — upstream option the widget reads from.
  • Language Detection & Redirects — how the cookie is consumed on subsequent requests.
  • Admin Bar Language Switcher & Editor Header Selector — admin-side companion.

See the multi-language real estate website page for product context.

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