Skip to content

Todo para WordPress, el desarrollo web — y mucho más

🔄 Selector de idiomas WPML: solo códigos ISO, sin banderas ni nombres

🔄 Selector de idiomas WPML: solo códigos ISO, sin banderas ni nombres

Las banderas de países en el menú de un sitio son una elección cuestionable. La mitad de la audiencia ve la Union Jack como su propia bandera, mientras que la otra mitad no. ¿La bandera de EE. UU. representando al inglés? Eso deja completamente fuera a canadienses y australianos. Y los nombres completos de los idiomas ("Русский," "Українська," "English") ocupan la mitad del menú en una pantalla móvil.

Un formato compacto RU | UK | EN resuelve ambos problemas: se lee al instante, ocupa casi ningún espacio y no está ligado a la geografía. Son códigos ISO de idioma estándar de dos letras, comprensibles sin traducción en cualquier país.

A continuación se presentan dos formas de reemplazar el selector predeterminado de WPML por códigos ISO. La primera utiliza un filtro de elementos de menú (una simple inserción en functions.php). La segunda es un shortcode que muestra el selector en cualquier parte del sitio.

💡 Resumen rápido:

  • Método 1: reemplazo de los elementos del menú de navegación mediante el hook wp_nav_menu_items, para un selector integrado en el encabezado
  • Método 2: el shortcode [wpml_custom_lang_ISO], insertable en cualquier parte del tema (widget, pie de página, menú móvil)
  • CSS: estilizar el separador |, ocultar el idioma activo, diseño responsivo

Cómo se ve el resultado

Una vez añadido el código, el selector de idiomas se muestra en el formato RU | UK | EN, corto y limpio. El idioma activo se resalta u oculta (controlado mediante CSS), mientras que los idiomas restantes son clicables y llevan a la traducción correspondiente de la página.

Selector de idiomas WPML en formato ISO RU | EN

El código utiliza la función integrada de WPML icl_get_languages(), que devuelve un array con los idiomas activos del sitio junto con todos los datos relevantes: URL de traducción, código de idioma, estado activo. No hay dependencias de terceros, solo la API propia de WPML.

Método 1: reemplazar los elementos del menú mediante wp_nav_menu_items

Este método intercepta la salida del menú de navegación de WordPress y reemplaza los elementos de idioma predeterminados por códigos ISO compactos y un separador.

Dónde insertarlo: en el functions.php del tema hijo o mediante el plugin Code Snippets (más seguro, no se borrará al actualizar el tema).

Antes de añadir el código, realiza una copia de seguridad completa del sitio. El código no es destructivo y solo añade salida, pero hacer una copia de seguridad es una buena práctica siempre que edites functions.php.

1/**
2 * Reemplaza los elementos de idioma de WPML en el menú por códigos ISO.
3 * theme_location se configura según su menú.
4 */
5add_filter( 'wp_nav_menu_items', 'wpml_iso_menu_items', 10, 2 );
6
7function wpml_iso_menu_items( $items, $args ) {
8 // Comprobamos que la función WPML esté disponible
9 if ( ! function_exists( 'icl_get_languages' ) ) {
10 return $items;
11 }
12
13 $languages = icl_get_languages( 'skip_missing=0&orderby=code' );
14
15 // Indique aquí el theme_location de su menú (por ejemplo '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 // Eliminamos el último separador
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}

Qué ocurre aquí. El hook wp_nav_menu_items se dispara cuando se está construyendo cada menú del sitio. La condición $args->theme_location !== 'primary' restringe el reemplazo únicamente al menú que necesitas; reemplaza 'primary' por el theme_location de tu menú (revisa wp_nav_menu() en tu plantilla o, en el panel de administración, en Apariencia > Menús > Ubicaciones de visualización).

La función icl_get_languages('skip_missing=0') obtiene todos los idiomas publicados. skip_missing=0 significa "mostrar el idioma incluso si la página actual no tiene traducción", de modo que el usuario llega a la página de inicio de ese idioma en lugar de un 404.

strtoupper() convierte los códigos a mayúsculas: ruRU. Si necesitas minúsculas, elimina la llamada.

Método 2: el shortcode [wpml_custom_lang_ISO]

El shortcode es más versátil: inserta [wpml_custom_lang_ISO] en cualquier lugar, un widget, el cuerpo de una página o una plantilla PHP mediante do_shortcode(). Funciona bien para un menú móvil, un pie de página o un bloque debajo del encabezado.

Dónde insertarlo: en functions.php (el mismo archivo que en el Método 1). Puedes mantener ambos métodos activos al mismo tiempo; no entrarán en conflicto.

1/**
2 * El shortcode [wpml_custom_lang_ISO] muestra el selector de idiomas en formato ISO.
3 * Inserción: [wpml_custom_lang_ISO] en el texto o <?php echo do_shortcode('[wpml_custom_lang_ISO]'); ?> en la plantilla.
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 // Eliminamos el último separador
32 $output = rtrim( $output, '<span class="wpml-lang-sep">|</span>' );
33
34 return '<div class="wpml-iso-lang-switcher">' . $output . '</div>';
35}

La diferencia con el Método 1: el shortcode devuelve una cadena HTML en lugar de añadir elementos a un menú. Esto significa que puedes colocarlo en cualquier lugar, sin depender de theme_location. El parámetro order=desc invierte el orden de los idiomas (opcional; elimínalo si no lo necesitas).

Cómo encontrar el theme_location de tu menú

Si estás usando el Método 1, debes especificar el argumento theme_location con exactitud. Abre el archivo de plantilla donde se llama al menú (normalmente header.php) y busca una línea como esta:

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

El valor entre comillas simples, por ejemplo 'primary', es tu theme_location. Los nombres comunes son primary para el menú principal y top para la barra superior. Sustituye el tuyo en la condición $args->theme_location !== 'primary' del código anterior.

Otra forma: en el panel de administración, ve a Apariencia > Menús > la pestaña "Gestionar ubicaciones", que enumera todos los valores theme_location registrados para tu tema.

Estilos CSS para el selector

Un conjunto mínimo de estilos para que el selector se vea limpio. Añádelos en Apariencia > Personalizar > CSS adicional o en el archivo style.css del tema hijo.

1/* Contenedor del selector */
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/* Enlaces e idioma activo */
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/* Separador */
31.wpml-lang-sep {
32 margin: 0 6px;
33 color: #ccc;
34 font-weight: 400;
35}
36
37/* Ocultar el idioma activo y el separador que le sigue */
38.wpml-lang-item.active,
39.wpml-lang-item.active + .wpml-lang-sep {
40 display: none;
41}
42
43/* Adaptación móvil */
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}

El truco clave aquí: el selector .wpml-lang-item.active + .wpml-lang-sep oculta el separador inmediatamente después del idioma activo. Si el idioma activo está oculto, el separador junto a él también desaparece, de modo que no queda ningún | colgando al principio o al final de la fila.

La fuente Oswald se usa como ejemplo. Reemplázala por la fuente de tu tema o elimina por completo la línea font-family para heredarla del tema. Después de añadir el CSS, prueba el selector en resoluciones móviles usando las herramientas de desarrollador (F12 > Alternar barra de dispositivo).

⁉️🤔 Preguntas frecuentes

¿Puedo mostrar nombres de idiomas en lugar de códigos ISO?

> Sí, reemplaza $lang['language_code'] por $lang['native_name'] en ambas variantes de código. Obtendrás "Русский | English | Українська." Alternativamente, $lang['translated_name'] genera los nombres en el idioma de la página actual: si el visitante está en la versión en inglés, verá "Russian | English | Ukrainian." Todas las claves disponibles del array aparecen en la documentación oficial de WPML para la función icl_get_languages().

¿Cómo elimino un idioma que no tiene traducción para la página actual?

Cambia el parámetro skip_missing=0 a skip_missing=1 en la llamada a icl_get_languages(). Los idiomas sin traducción simplemente desaparecerán del selector, y no quedará ningún enlace roto en su lugar. Esto resulta cómodo para sitios donde no todas las páginas están traducidas: el menú se mantiene limpio, sin enlaces que lleven a la página de inicio o a un 404.

El selector no aparece. ¿Qué está mal?

Comprueba tres cosas. Primero, ¿está activo el plugin WPML y hay idiomas añadidos en WPML > Idiomas? Segundo, ¿coincide el theme_location del código con el menú real (Método 1)? Tercero, ¿se llama al shortcode mediante do_shortcode() si lo estás usando en una plantilla PHP en lugar de en el contenido de la página (Método 2)? Si todo es correcto pero el selector sigue sin mostrarse, activa WP_DEBUG en wp-config.php y revisa error.log; puede haber un error de sintaxis en functions.php.

¿Cómo añado banderas junto a los códigos, por ejemplo 🇬🇧 + EN?

Añade un emoji de bandera antes de $code con una condición: if ($lang['language_code'] === 'en') $code = '🇬🇧 ' . $code;. Ten en cuenta, sin embargo, que los emojis de bandera pueden no renderizarse en Windows. Un enfoque más fiable es usar banderas CSS mediante ::before con background-image, o las banderas integradas de WPML.

¿Funcionará este código con Polylang o TranslatePress?

No: icl_get_languages() es específicamente una API de WPML. Para Polylang, la función equivalente es pll_the_languages(), y TranslatePress tiene su propio conjunto de hooks. La lógica es la misma, pero los nombres de las funciones difieren.

Conclusiones: menú o shortcode

El método del filtro de menú es para quienes necesitan el selector estrictamente en la navegación y conocen con certeza su theme_location. Esfuerzo mínimo: inserta el código, reemplaza el nombre de la ubicación, listo. La desventaja: está ligado a un único menú; para un segundo necesitarías duplicar el hook con un theme_location diferente.

El shortcode es el camino a seguir si el selector necesita estar en un lugar no estándar: un panel móvil, un pie de página o una barra lateral. Añade el shortcode a un widget "HTML" o a una plantilla y controla su posición mediante las herramientas estándar de WordPress. La ventaja: puedes insertarlo en varios lugares sin duplicar código.

En la práctica, ambos métodos conviven sin problemas en un mismo functions.php. Configura el filtro para el menú principal y el shortcode para la versión móvil, y obtendrás un limpio RU | UK | EN en todos los dispositivos. Y si necesitas el selector una tercera vez (por ejemplo, en el pie de página), simplemente añade otro do_shortcode('[wpml_custom_lang_ISO]') a la plantilla correspondiente.

¿Qué formato de selector usas tú: banderas, nombres o códigos ISO? Comparte tu experiencia configurando sitios multilingües en los comentarios; sería interesante comparar enfoques.