A floating, mobile-first language switcher widget for Polylang-powered WordPress sites.
This plugin renders a fixed-position button in the corner of the screen. Tapping it opens a dropdown listing every language configured in Polylang, with flags and language names. It's designed primarily for mobile visitors, though desktop visibility can be turned on in settings.
Everything the widget needs — markup, styles, and behaviour — is self-contained under a single element, #wdd-lang-switcher, so it can be dropped into any theme without affecting existing layouts or styles.
/wp-content/plugins/, or install the zip via Plugins → Add New → Upload Plugin.The widget renders automatically on the front end once Polylang is detected — no shortcode or template tag is needed.
All settings live under Settings → Lang Switcher in wp-admin.
| Setting | Default | Description |
|---|---|---|
| Position | right | Which corner the widget anchors to — left or right. |
| Bottom offset | 24px | Distance from the bottom edge of the screen. |
| Side offset | 20px | Distance from the chosen side edge. |
| Background color | #1a1a1a | Toggle button background. |
| Text color | #ffffff | Toggle button text and icon color. |
| Breakpoint | 767px | The dividing line between "mobile" and "desktop" for the two visibility toggles below. |
| Show on mobile | On | Display the widget at or below the breakpoint. |
| Show on desktop | Off | Display the widget above the breakpoint. |
| Show flags | On | Show flag images next to each language in the dropdown. |
| Show names | On | Show full language names instead of just the slug. |
| Show globe icon | On | Show a globe icon on the toggle button. |
| Button label | Empty | Custom text for the button. Leave empty to show the current language slug (e.g. EN). |
| Hide current language | Off | Remove the active language from the dropdown list, since it's already shown on the button. |
| Border radius | 50px | Roundness of the toggle button. 50 gives a pill shape, 0 gives square corners. |
Mobile and desktop visibility are independent — both, either, or neither can be enabled at once.
The widget HTML is printed in wp_footer. It pulls the active language list directly from Polylang's pll_the_languages() function — there's no caching layer of its own, so changes made in Polylang's language settings appear immediately.
Static, unchanging styles (layout, animation, hover states) live in a regular stylesheet. Settings that the admin can change — colors, position, offsets, border radius — are compiled into a small inline <style> block and printed in wp_footer as well, just before the widget markup. Printing styles in the footer, after every other stylesheet on the page, is what lets the widget's own design settings consistently take priority over page builder and theme styles without needing a long list of overrides.
A small vanilla JavaScript file (no jQuery) handles opening and closing the dropdown: click the button to toggle it, click outside or press Esc to close it, and clicking any language link closes it before navigating.
Both the CSS and JS ship in two versions — a readable source file and a minified one. The minified versions load by default. Add this to wp-config.php to load the readable source files instead, useful when debugging:
define( 'SCRIPT_DEBUG', true );
Every CSS rule the plugin outputs is scoped under the widget's wrapper element, #wdd-lang-switcher, so it cannot affect any other element on the page — and nothing on the page can leak in and affect the widget either, beyond what's noted below.
Specifically tested against:
Also expected to work cleanly with Astra, Divi, GeneratePress, OceanWP, and Avada, since the same scoping approach applies regardless of theme.
wdd-pls-script) from delay execution, either through WP Rocket's exclusion field in Settings → WP Rocket → File Optimization, or by disabling Delay JS Execution for this page if site-wide exclusion isn't an option.
wdd-pls-script.min.js — clear the site cache after any plugin update.No — the plugin checks for Polylang on every load and renders nothing if it isn't active.
Yes, enable both toggles in settings. They're independent of each other.
No — this widget doesn't replace or hook into any existing switcher; it simply adds its own floating element to the page. If you have another switcher already, you may want to disable one to avoid showing the same control twice.