Skip to content

Все для WordPress, веб-розробки — і не тільки

🔄 Перемикач мов WPML: лише ISO-коди замість прапорів і назв

🔄 Перемикач мов WPML: лише ISO-коди замість прапорів і назв

Прапори країн у меню сайту, сумнівне рішення. На прапорі Великої Британії половина країни впізнає свій, а друга половина, ні. Прапор США замість англійської? Для канадців і австралійців мимо. А назви мов повністю, «Русский», «Українська», «English», займають пів меню на мобільному екрані.

Компактний формат RU | UK | EN розв'язує обидві проблеми: читається миттєво, місця майже не займає і не прив'язаний до географії. Це стандартні ISO-коди мов, дволітерні, зрозумілі без перекладу в будь-якій країні.

Нижче, два способи замінити стандартний перемикач WPML на ISO-коди. Перший, через фільтр пунктів меню (простий врізкою у functions.php). Другий, шорткод, який виводить перемикач у будь-якому місці сайту.

💡 Швидкий огляд:

  • Спосіб 1: заміна пунктів навігаційного меню через хук wp_nav_menu_items, для вбудованого перемикача в шапці
  • Спосіб 2: шорткод [wpml_custom_lang_ISO], вставка в будь-яке місце теми (віджет, футер, мобільне меню)
  • CSS: стилізація роздільника |, приховування активної мови, адаптивність

Який вигляд має результат

Після додавання коду перемикач мов відображається у форматі RU | UK | EN, коротко й акуратно. Активна мова виділяється або приховується (задається через CSS), інші мови клікабельні й ведуть на відповідну версію сторінки.

Перемикач мов WPML у ISO-форматі RU | EN

Код використовує штатну функцію WPML icl_get_languages(), вона повертає масив активних мов сайту з усіма даними: URL перекладу, код мови, ознака активності. Жодних сторонніх залежностей, лише API самого WPML.

Спосіб 1: заміна пунктів меню через wp_nav_menu_items

Цей метод перехоплює вивід навігаційного меню WordPress і замінює стандартні пункти-мови на компактні ISO-коди з роздільником.

Куди вставляти: functions.php дочірньої теми або через плагін Code Snippets (безпечніше, не зітреться при оновленні теми).

Перед додаванням зробіть повний бекап сайту. Код не деструктивний і лише додає вивід, але бекап, правило доброго тону за будь-якої правки functions.php.

1/**
2 * Замінює пункти мов WPML у меню на ISO-коди.
3 * theme_location задається під ваше меню.
4 */
5add_filter( 'wp_nav_menu_items', 'wpml_iso_menu_items', 10, 2 );
6
7function wpml_iso_menu_items( $items, $args ) {
8 // Перевіряємо, що функція WPML доступна
9 if ( ! function_exists( 'icl_get_languages' ) ) {
10 return $items;
11 }
12
13 $languages = icl_get_languages( 'skip_missing=0&orderby=code' );
14
15 // Вкажіть тут theme_location вашого меню (наприклад 'primary', 'top')
16 if ( empty( $languages ) || $args->theme_location !== 'primary' ) {
17 return $items;
18 }
19
20 $lang_links = '';
21
22 foreach ( $languages as $lang ) {
23 $code = strtoupper( $lang['language_code'] );
24
25 if ( $lang['active'] ) {
26 $lang_links .= '<span class="wpml-lang-item active">' . $code . '</span>';
27 } else {
28 $lang_links .= '<a href="' . esc_url( $lang['url'] ) . '" class="wpml-lang-item">' . $code . '</a>';
29 }
30
31 $lang_links .= '<span class="wpml-lang-sep">|</span>';
32 }
33
34 // Прибираємо останній розділювач
35 $lang_links = rtrim( $lang_links, '<span class="wpml-lang-sep">|</span>' );
36
37 return $items . '<li class="menu-item wpml-iso-switcher">' . $lang_links . '</li>';
38}

Що тут відбувається. Хук wp_nav_menu_items спрацьовує під час формування кожного меню на сайті. Умова $args->theme_location !== 'primary' обмежує заміну лише потрібним меню, замініть 'primary' на theme_location вашого меню (дивіться у wp_nav_menu() у шаблоні або в адмінці: Зовнішній вигляд → Меню → місця розміщення).

Функція icl_get_languages('skip_missing=0') отримує всі опубліковані мови. skip_missing=0 означає «показати мову, навіть якщо у поточної сторінки немає перекладу», користувач потрапить на головну цієї мови замість 404.

strtoupper() приводить коди до верхнього регістру: ruRU. Якщо потрібні малі, приберіть виклик.

Спосіб 2: шорткод [wpml_custom_lang_ISO]

Шорткод універсальніший: вставляйте [wpml_custom_lang_ISO] в будь-яке місце, віджет, текст сторінки, PHP-шаблон через do_shortcode(). Підходить для мобільного меню, футера або блока під шапкою.

Куди вставляти: functions.php (той самий файл, що й для способу 1). Можна тримати обидва способи одночасно, конфлікту не буде.

1/**
2 * Шорткод [wpml_custom_lang_ISO] — виводить перемикач мов у ISO-форматі.
3 * Вставка: [wpml_custom_lang_ISO] у тексті або <?php echo do_shortcode('[wpml_custom_lang_ISO]'); ?> у шаблоні.
4 */
5add_shortcode( 'wpml_custom_lang_ISO', 'wpml_shortcode_lang_iso' );
6
7function wpml_shortcode_lang_iso() {
8 if ( ! function_exists( 'icl_get_languages' ) ) {
9 return '';
10 }
11
12 $languages = icl_get_languages( 'skip_missing=0&orderby=code&order=desc' );
13 $output = '';
14
15 if ( empty( $languages ) ) {
16 return '';
17 }
18
19 foreach ( $languages as $lang ) {
20 $code = strtoupper( $lang['language_code'] );
21
22 if ( $lang['active'] ) {
23 $output .= '<span class="wpml-lang-item active">' . $code . '</span>';
24 } else {
25 $output .= '<a href="' . esc_url( $lang['url'] ) . '" class="wpml-lang-item">' . $code . '</a>';
26 }
27
28 $output .= '<span class="wpml-lang-sep">|</span>';
29 }
30
31 // Прибираємо останній розділювач
32 $output = rtrim( $output, '<span class="wpml-lang-sep">|</span>' );
33
34 return '<div class="wpml-iso-lang-switcher">' . $output . '</div>';
35}

Різниця зі способом 1: шорткод повертає HTML-рядок, а не доповнює пункти меню. Тому його можна розмістити будь-де, не прив'язаний до theme_location. Параметр order=desc змінює порядок мов на зворотний (опційно, приберіть якщо не потрібен).

Як знайти theme_location вашого меню

Якщо ви використовуєте Спосіб 1, потрібно точно вказати аргумент theme_location. Відкрийте файл шаблону, де викликається меню (зазвичай header.php), і знайдіть рядок виду:

1wp_nav_menu( array( 'theme_location' => 'primary', 'menu_id' => 'primary-menu' ) );

Значення в одинарних лапках, наприклад 'primary', і є ваш theme_location. Ходові назви: primary для основного меню, top для верхньої панелі. Підставте своє в умову $args->theme_location !== 'primary' з коду вище.

Інший спосіб: в адмінці відкрийте Зовнішній вигляд → Меню → вкладка «Місця розміщення», там перелічені всі зареєстровані theme_location теми.

CSS-стилі для перемикача

Мінімальний набір стилів, щоб перемикач мав акуратний вигляд. Додайте в Зовнішній вигляд → Налаштувати → Додаткові CSS або у файл style.css дочірньої теми.

1/* Контейнер перемикача */
2.wpml-iso-lang-switcher,
3.wpml-iso-switcher {
4 display: flex;
5 align-items: center;
6 gap: 0;
7 font-family: 'Oswald', sans-serif;
8 font-size: 16px;
9 font-weight: 600;
10 text-transform: uppercase;
11}
12
13/* Посилання та активна мова */
14.wpml-lang-item {
15 color: #33445d;
16 text-decoration: none;
17 padding: 4px 2px;
18 transition: color 0.2s;
19}
20
21a.wpml-lang-item:hover {
22 color: #0073aa;
23}
24
25.wpml-lang-item.active {
26 color: #999;
27 cursor: default;
28}
29
30/* Розділювач */
31.wpml-lang-sep {
32 margin: 0 6px;
33 color: #ccc;
34 font-weight: 400;
35}
36
37/* Приховати активну мову та наступний за нею розділювач */
38.wpml-lang-item.active,
39.wpml-lang-item.active + .wpml-lang-sep {
40 display: none;
41}
42
43/* Мобільна адаптація */
44@media screen and (max-width: 768px) {
45 .wpml-iso-lang-switcher,
46 .wpml-iso-switcher {
47 font-size: 18px;
48 padding: 8px 0;
49 }
50}

Ключовий прийом: селектор .wpml-lang-item.active + .wpml-lang-sep приховує роздільник одразу за активною мовою. Якщо активна мова прихована, то й роздільник за нею зникає, не залишається висячої палиці | на початку або в кінці рядка.

Шрифт Oswald вказано для прикладу. Замініть на шрифт вашої теми або приберіть рядок font-family зовсім, щоб успадкувати від теми. Після додавання CSS перевірте перемикач на мобільній роздільності через інструменти розробника (F12 → Toggle device toolbar).

⁉️🤔 Часті запитання

Чи можна показувати назви мов замість ISO-кодів?

> Так, замініть $lang['language_code'] на $lang['native_name'] в обох варіантах коду. Отримаєте «Русский | English | Українська». Альтернативно, $lang['translated_name'] виводить назви мовою поточної сторінки: якщо відвідувач на англійській версії, він побачить «Russian | English | Ukrainian». Усі доступні ключі масиву перелічені в офіційній документації WPML щодо функції icl_get_languages().

Як прибрати мову, у якої немає перекладу поточної сторінки?

Поміняйте у виклику icl_get_languages() параметр skip_missing=0 на skip_missing=1. Мови без перекладу просто зникнуть з перемикача, замість них не буде битого посилання. Зручно для сайтів, де перекладені не всі сторінки: меню залишиться чистим, без посилань що ведуть на головну або 404.

Перемикач не з'являється, у чому річ?

Перевірте три моменти. Перше: чи активний плагін WPML і чи додані мови у WPML → Languages. Друге: чи збігається theme_location у коді з реальним меню (Спосіб 1). Третє: чи вставлено шорткод через do_shortcode() якщо використовуєте його в PHP-шаблоні, а не в тексті сторінки (Спосіб 2). Якщо все правильно, а перемикача немає, увімкніть WP_DEBUG у wp-config.php і перевірте error.log, можливо у functions.php синтаксична помилка.

Як зробити прапори разом з кодами, наприклад, прапор 🇬🇧 + EN?

Додайте перед $code емодзі прапора за умовою: if ($lang['language_code'] === 'en') $code = '🇬🇧 ' . $code;. Але пам'ятайте, емодзі прапорів можуть не відображатися на Windows. Надійніше використовувати CSS-прапори через ::before з background-image або вбудовані прапори WPML.

Чи підійде цей код для Polylang або TranslatePress?

Ні: icl_get_languages() це API саме WPML. Для Polylang аналогом буде функція pll_the_languages(), для TranslatePress свій набір хуків. Логіка та сама, але назви функцій різні.

Підсумки: меню чи шорткод

Спосіб з фільтром меню, для тих, кому потрібен перемикач строго в навігації і хто точно знає theme_location. Мінімум рухів: вставили код, замінили назву локації, готово. Недолік: прив'язаний до одного меню, для другого доведеться дублювати хук з іншим theme_location.

Шорткод, якщо перемикач має бути в нестандартному місці: мобільна панель, футер, сайдбар. Додали шорткод у віджет «HTML-код» або в шаблон, і керуєте позицією через стандартні засоби WordPress. Плюс: можна вставити в кількох місцях без дублювання коду.

На практиці обидва способи мирно живуть в одному functions.php. Поставте фільтр для основного меню і шорткод для мобільної версії, отримаєте акуратний RU | UK | EN на всіх пристроях. А якщо перемикач потрібен третій раз (наприклад у футері), просто додайте ще один do_shortcode('[wpml_custom_lang_ISO]') у потрібний шаблон.

Який формат перемикача використовуєте ви: прапори, назви чи ISO-коди? Діліться в коментарях своїм досвідом налаштування багатомовних сайтів, цікаво порівняти підходи.