Polylang > Blog > Polylang 3.9 & Polylang Pro 3.9 – New Language Switcher customizations in pll_the_languages()

Polylang 3.9 & Polylang Pro 3.9 – New Language Switcher customizations in pll_the_languages()

Grégory

Polylang

18 September 2026

Polylang 3.9 improves its language switcher with new customization options, and those new possibilities are available in the API function pll_the_languages().

API & Parameter changes

Deprecated parameters

New options mean new parameters, but they also mean deprecated parameters. The function will throw a “Deprecated argument” notice if any of the following parameters is used: 'dropdown', 'show_names', 'display_names_as', 'item_spacing'. Those parameters have been renamed or replaced. However, backward compatibility is ensured, so your custom switchers won’t break if you still use them.

Let’s take a closer look at the deprecated parameters:

  1. 'dropdown': it was used to display the switcher as a <select> element ('dropdown' => 1), or a list of <li> elements ('dropdown' => 0). This is replaced by 'layout', which accepts 4 possible values:
    • 'horizontal',
    • 'vertical' (similar to 'dropdown' => 0),
    • 'dropdown',
    • 'select' (similar to 'dropdown' => 1).
  2. 'show_names' and 'display_names_as': 'show_names' was used to display or hide the labels, and 'display_names_as' was used to display the labels as language names or language codes. They have been merged into a single parameter 'show_labels' that accepts 3 possible values:
    • 'names' (similar to 'show_names' => 1 + 'display_names_as' => 'name'),
    • 'codes' (similar to 'show_names' => 1 + 'display_names_as' => 'code'),
    • an empty string (similar to 'show_names' => 0).
  3. 'item_spacing': it was used to preserve or discard whitespace between list items. It is renamed to 'preserve_spacing' and is now a boolean.

Type changes

The following parameters are preserved, but they are now boolean instead of 0/1: 'hide_if_empty', 'show_flags', 'force_home', 'hide_if_no_translation', 'hide_current', 'echo', and 'raw'. They won’t trigger any notice if they receive 0 or 1.

Summary

Old parameterOld valueNew parameterNew valueDeprecation notice
'dropdown'0, 1'layout''horizontal', 'vertical', 'dropdown', 'select'Yes
'show_names'0, 1'show_labels''names', 'codes', ''Yes
'display_names_as''name', 'code'
'item_spacing''preserve', 'discard''preserve_spacing'false, trueYes
'hide_if_empty'0, 1No changefalse, trueNo
'show_flags'
'force_home'
'hide_if_no_translation'
'hide_current'
'echo'
'raw'

Markup & Layouts

Among all the changes, this new switcher can display a new HTML element (<nav> or <div>, depending on HTML5 support) wrapping the list of languages.
The previous behavior is kept by default for now, but this will change; we want 'show_wrapper' => true to be the default value in the future. So, in some cases, a “Doing it wrong” notice will be thrown (for example when calling pll_the_languages() without arguments). To prevent this notice, specify 'show_wrapper' => false if you still want to build your own wrapper.

Example for the horizontal and vertical layouts

<nav id="pll-switcher-1" class="pll-switcher ..." aria-label="Choose a language">
  <ul>
    <li class="lang-item ...">
      <a lang="en-US" hreflang="en-US" href="..." aria-current="true">
        <span class="pll-switcher-flag" style="..."><img src="..." alt="" width="18" height="12" style="..."></span>
        <span class="pll-switcher-label" style="...">English</span>
      </a>
    </li>
    ...
  </ul>
</nav>

The difference between horizontal and vertical is only a CSS class.

Example with the dropdown layout

<nav id="pll-switcher-1" class="pll-switcher ..." aria-label="Choose a language">
  <div class="pll-switcher-inner">
    <a lang="en-US" hreflang="en-US" href="..." aria-current="true"><span class="pll-switcher-label">Français</span></a>
    <button aria-label="Open/Close languages submenu" class="pll-submenu-toggle"><svg ...></svg></button>
    <ul>
      <li class="lang-item ...">
        <a lang="en-US" hreflang="en-US" href="..." aria-current="true">
          <span class="pll-switcher-label">English</span>
        </a>
      </li>
      ...
    </ul>
  </div>
</nav>

Example with the select layout

<div class="pll-switcher ...">
  <label class="screen-reader-text" for="pll-switcher-1">Choose a language</label>
  <select class="pll-switcher-select" id="pll-switcher-1">
    <option lang="en-US" value="..." selected="selected" class="lang-item ...">English</option>
    ...
  </select>
</div>

Raw data changes

The data returned when using 'raw' => true is still available: it contains the previous fields along with several new ones. Some are duplicated: for example, 'is_rtl' is still there, but its value is also in 'direction', which can contain 'ltr' or 'rtl'. And some are new: for example, 'link_classes', which contains CSS classes to apply to the <a> elements.

Assets (CSS & JS)

This new switcher comes with some minimal inline style for the flags and labels (see the 'horizontal'/'vertical' layouts example above).
When used in our block or widget, a stylesheet is also enqueued to style alignment etc, but pll_the_languages() doesn’t enqueue it, you must create your own styles, like the old switcher.

The 'dropdown' and 'select' layouts require some JavaScript, which is enqueued automatically, but it will still need your own styling. Previously the JavaScript for the 'select' layout was inlined under the switcher.

Author

Grégory

Developer. If you manage to find me at a WordCamp, you’ll be able to tell your grandchildren all about this feat.