Skip to content

Tudo para WordPress, desenvolvimento web — e não só

🔄 Seletor de idiomas WPML: apenas códigos ISO, sem bandeiras nem nomes

🔄 Seletor de idiomas WPML: apenas códigos ISO, sem bandeiras nem nomes

As bandeiras de países num menu de site são uma escolha questionável. Metade da audiência vê a Union Jack como a sua própria bandeira, enquanto a outra metade não. A bandeira dos EUA a representar o inglês? Isso ignora completamente canadianos e australianos. E os nomes completos dos idiomas ("Русский," "Українська," "English") ocupam metade do menu num ecrã móvel.

Um formato compacto RU | UK | EN resolve ambos os problemas: lê-se instantaneamente, ocupa quase nenhum espaço e não está associado a geografia. São códigos ISO de idioma padrão de duas letras, compreendidos sem tradução em qualquer país.

Abaixo estão duas formas de substituir o seletor padrão do WPML por códigos ISO. A primeira utiliza um filtro de itens de menu (uma simples inserção no functions.php). A segunda é um shortcode que apresenta o seletor em qualquer parte do site.

💡 Visão geral rápida:

  • Método 1: substituição dos itens do menu de navegação através do hook wp_nav_menu_items, para um seletor incorporado no cabeçalho
  • Método 2: o shortcode [wpml_custom_lang_ISO], que pode ser inserido em qualquer parte do tema (widget, rodapé, menu mobile)
  • CSS: estilização do separador |, ocultação do idioma ativo, design responsivo

Como fica o resultado

Depois de o código ser adicionado, o seletor de idiomas é apresentado no formato RU | UK | EN, curto e limpo. O idioma ativo é destacado ou ocultado (controlado via CSS), enquanto os restantes idiomas são clicáveis e levam à respetiva tradução da página.

Seletor de idiomas WPML em formato ISO RU | EN

O código utiliza a função integrada do WPML icl_get_languages(), que devolve um array com os idiomas ativos do site e todos os dados relevantes: URL de tradução, código de idioma, estado ativo. Não existem dependências de terceiros, apenas a própria API do WPML.

Método 1: substituir itens do menu através de wp_nav_menu_items

Este método intercepta a saída do menu de navegação do WordPress e substitui os itens de idioma padrão por códigos ISO compactos e um separador.

Onde inserir: no functions.php do tema-filho (child theme) ou através do plugin Code Snippets (mais seguro, não é apagado quando o tema é atualizado).

Antes de adicionar o código, faça uma cópia de segurança do site completa. O código não é destrutivo e apenas adiciona saída, mas fazer uma cópia de segurança é uma boa prática sempre que se edita o functions.php.

1/**
2 * Substitui os itens de idiomas do WPML no menu por códigos ISO.
3 * theme_location é definido conforme o seu menu.
4 */
5add_filter( 'wp_nav_menu_items', 'wpml_iso_menu_items', 10, 2 );
6
7function wpml_iso_menu_items( $items, $args ) {
8 // Verifica se a função WPML está disponível
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 aqui o theme_location do seu menu (por exemplo '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 // Remove o ú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}

O que acontece aqui. O hook wp_nav_menu_items é acionado sempre que cada menu do site está a ser construído. A condição $args->theme_location !== 'primary' restringe a substituição apenas ao menu que precisa; substitua 'primary' pelo theme_location do seu menu (verifique wp_nav_menu() no seu template ou no painel de administração em Aparência > Menus > Locais de exibição).

A função icl_get_languages('skip_missing=0') obtém todos os idiomas publicados. skip_missing=0 significa "mostrar o idioma mesmo que a página atual não tenha tradução", pelo que o utilizador é direcionado para a página inicial desse idioma em vez de um erro 404.

strtoupper() converte os códigos para maiúsculas: ruRU. Se precisar de minúsculas, remova a chamada.

Método 2: o shortcode [wpml_custom_lang_ISO]

O shortcode é mais versátil: insira [wpml_custom_lang_ISO] em qualquer lugar — um widget, o corpo de uma página ou um template PHP através de do_shortcode(). Funciona bem num menu mobile, rodapé ou num bloco abaixo do cabeçalho.

Onde inserir: no functions.php (o mesmo ficheiro do Método 1). Pode manter ambos os métodos ativos em simultâneo; não entram em conflito.

1/**
2 * Shortcode [wpml_custom_lang_ISO] — apresenta o seletor de idiomas em formato ISO.
3 * Inserção: [wpml_custom_lang_ISO] no texto ou <?php echo do_shortcode('[wpml_custom_lang_ISO]'); ?> no template.
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 // Remove o último separador
32 $output = rtrim( $output, '<span class="wpml-lang-sep">|</span>' );
33
34 return '<div class="wpml-iso-lang-switcher">' . $output . '</div>';
35}

A diferença em relação ao Método 1: o shortcode devolve uma string HTML em vez de acrescentar itens a um menu. Isto significa que pode colocá-lo em qualquer lugar, sem depender do theme_location. O parâmetro order=desc inverte a ordem dos idiomas (opcional; remova-o se não precisar dele).

Como encontrar o theme_location do seu menu

Se estiver a usar o Método 1, precisa de especificar exatamente o argumento theme_location. Abra o ficheiro de template onde o menu é chamado (normalmente header.php) e procure uma linha como:

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

O valor entre aspas simples, por exemplo 'primary', é o seu theme_location. Nomes comuns são primary para o menu principal e top para a barra superior. Substitua pelo seu na condição $args->theme_location !== 'primary' no código acima.

Outra forma: no painel de administração, vá a Aparência > Menus > separador "Gerir Locais", que lista todos os valores de theme_location registados para o seu tema.

Estilos CSS para o seletor

Um conjunto mínimo de estilos para manter o seletor com um aspeto limpo. Adicione-os em Aparência > Personalizar > CSS Adicional ou no ficheiro style.css do tema-filho.

1/* Contentor do seletor */
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/* Ligações e idioma ativo */
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 o idioma ativo e o separador seguinte */
38.wpml-lang-item.active,
39.wpml-lang-item.active + .wpml-lang-sep {
40 display: none;
41}
42
43/* Adaptação para dispositivos móveis */
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}

O truque principal aqui: o seletor .wpml-lang-item.active + .wpml-lang-sep oculta o separador imediatamente a seguir ao idioma ativo. Se o idioma ativo estiver oculto, o separador ao lado dele também desaparece, pelo que não fica um | solto no início ou no fim da linha.

A fonte Oswald é usada como exemplo. Substitua-a pela fonte do seu tema ou remova completamente a linha font-family para herdar do tema. Depois de adicionar o CSS, teste o seletor em resoluções móveis usando as ferramentas de programador (F12 > Toggle device toolbar).

⁉️🤔 Perguntas frequentes

Posso mostrar nomes de idiomas em vez de códigos ISO?

> Sim, substitua $lang['language_code'] por $lang['native_name'] em ambas as variantes de código. Vai obter "Русский | English | Українська." Em alternativa, $lang['translated_name'] apresenta os nomes no idioma da página atual: se o visitante estiver na versão em inglês, verá "Russian | English | Ukrainian." Todas as chaves de array disponíveis estão listadas na documentação oficial do WPML para a função icl_get_languages().

Como removo um idioma que não tem tradução para a página atual?

Altere o parâmetro skip_missing=0 para skip_missing=1 na chamada a icl_get_languages(). Os idiomas sem tradução simplesmente desaparecem do seletor, sem deixar um link quebrado no seu lugar. Isto é útil para sites onde nem todas as páginas estão traduzidas: o menu mantém-se limpo, sem links que levem à página inicial ou a um erro 404.

O seletor não aparece. O que está errado?

Verifique três coisas. Primeiro, o plugin WPML está ativo e os idiomas foram adicionados em WPML > Languages? Segundo, o theme_location no código corresponde ao menu real (Método 1)? Terceiro, o shortcode está a ser chamado via do_shortcode() se o estiver a usar num template PHP em vez de no conteúdo da página (Método 2)? Se tudo estiver correto e o seletor continuar sem aparecer, ative o WP_DEBUG no wp-config.php e verifique o error.log; pode haver um erro de sintaxe no functions.php.

Como adiciono bandeiras junto aos códigos, por exemplo 🇬🇧 + EN?

Adicione um emoji de bandeira antes de $code com uma condição: if ($lang['language_code'] === 'en') $code = '🇬🇧 ' . $code;. Tenha em conta, no entanto, que os emojis de bandeiras podem não ser apresentados no Windows. Uma abordagem mais fiável é usar bandeiras em CSS através de ::before com background-image, ou as bandeiras integradas do WPML.

Este código funciona com o Polylang ou o TranslatePress?

Não: icl_get_languages() é especificamente uma API do WPML. Para o Polylang, a função equivalente é pll_the_languages(), e o TranslatePress tem o seu próprio conjunto de hooks. A lógica é a mesma, mas os nomes das funções são diferentes.

Conclusões: menu ou shortcode

O método do filtro de menu é para quem precisa do seletor estritamente na navegação e conhece com certeza o seu theme_location. Esforço mínimo: insira o código, substitua o nome do local, e está feito. A desvantagem: está associado a um único menu; para um segundo seria necessário duplicar o hook com um theme_location diferente.

O shortcode é o caminho a seguir se o seletor precisar de estar num local não convencional: um painel mobile, rodapé ou barra lateral. Adicione o shortcode a um widget "HTML" ou a um template e controle a sua posição através das ferramentas padrão do WordPress. A vantagem: pode inseri-lo em vários locais sem duplicar código.

Na prática, ambos os métodos coexistem pacificamente num único functions.php. Configure o filtro para o menu principal e o shortcode para a versão mobile, e obtém um RU | UK | EN limpo em todos os dispositivos. E se precisar do seletor uma terceira vez (por exemplo, no rodapé), basta adicionar outro do_shortcode('[wpml_custom_lang_ISO]') ao template apropriado.

Que formato de seletor utiliza: bandeiras, nomes ou códigos ISO? Partilhe a sua experiência a configurar sites multilingues nos comentários; seria interessante comparar abordagens.