Documentação Universally

Guias passo a passo, dicas de SEO multilíngue e melhores práticas para ajudar você a traduzir e escalar seu site WordPress.

Crie um seletor de idioma personalizado no WordPress

Universally vem com um seletor integrado em dropdown que você pode adicionar via auto-placement, o shortcode [universally_switcher], ou a função PHP universally_switcher(). Isso cobre a maioria dos casos.

Mas se você quiser controle total sobre a aparência e o comportamento do seletor: uma linha de abas inline, botões apenas com bandeiras, uma lista vertical na barra lateral, um seletor suspenso personalizado que combine com seu sistema de design, qualquer coisa. Você pode criar o seu próprio em PHP usando os mesmos dados que o plugin usa internamente.

Este guia mostra a você:

  1. A base: a única função auxiliar que você precisa, os dados que ela retorna e um seletor mínimo de “Olá, Mundo” no qual você pode se basear.
  2. Um exemplo completo e funcional: abas inline (bandeiras + nomes nativos) com opções de alinhamento, alternâncias e estilos, que você pode usar como está ou adaptar.

A base

Universally expõe uma única função auxiliar PHP que retorna tudo o que você precisa para renderizar um seletor:

universally_get_switcher_urls();

Ele retorna um array de entradas de idioma. Cada entrada contém:

Campo Tipo Descrição
nome string Nome de exibição em inglês, com a região ou variante entre colchetes (por exemplo, Espanhol (México), Inglês (Britânico)).
originalName string Apenas o nome nativo, sem região (por exemplo, Deutsch, English, Français).
flagUrl string URL do ícone da bandeira, ou uma string vazia quando nenhuma bandeira é mapeada para a região. Sempre presente, independentemente do que a configuração de Bandeiras de País diga.
urlPrefix string Prefixo de URL para o idioma (por exemplo, de, fr, mx). Vazio para o idioma de origem.
idioma string Código de idioma base (por exemplo, es, en).
variant string Variante de tradução, em minúsculas (por exemplo, es-419, en-gb). Vazio para o idioma de origem.
region string Código de região completo, em minúsculas (por exemplo, es-mx, de-de). Não é um código de país base.
isSource bool true para o idioma de origem.
desabilitado bool true quando o idioma é adicionado, mas desativado. Apenas para idiomas de destino.
url string URL completo para a página atual neste idioma.
isCurrent bool true para o idioma que o visitante está visualizando no momento.

Pular idiomas desativados. Um idioma desativado ainda aparece nesta matriz, mas seu URL não é mais servido como uma tradução, então um link para ele é um beco sem saída. O seletor integrado os filtra e o seu também deve filtrar: essa é a verificação isDisabled nos exemplos abaixo.

Use region quando precisar de um valor de localidade para um atributo lang ou um hreflang, pois é o código completo em vez de uma abreviação de país.

Uma vez que você tenha essa matriz, o resto depende de você: em qual HTML você a envolve, qual CSS você aplica, qual comportamento você adiciona. Universally não se importa.

Exemplo de base mínima

O menor seletor personalizado possível: percorra os idiomas, gere um link para cada um, exponha-o como um shortcode. Sem estilos, sem opções, sem marcação além do necessário.

<?php
function custom_language_switcher() {
    if (!function_exists('universally_get_switcher_urls')) return '';
    $langs = universally_get_switcher_urls();
    if (empty($langs)) return '';

    $out = '<ul class="custom-language-switcher">';
    foreach ($langs as $lang) {
        if (empty($lang['url'])) continue;
        if (!empty($lang['isDisabled'])) continue;

        $label = esc_html($lang['originalName'] ?? '');
        $url   = esc_url($lang['url']);
        $flag  = !empty($lang['flagUrl'])
            ? '<img src="' . esc_url($lang['flagUrl']) . '" alt="">'
            : '';

        $out .= '<li><a href="' . $url . '">' . $flag . $label . '</a></li>';
    }
    $out .= '</ul>';

    return $out;
}
add_shortcode('custom_language_switcher', 'custom_language_switcher');

Cole isso no functions.php do seu tema filho (ou em um plugin de snippets de código como WPCode) e use-o em qualquer lugar onde shortcodes são aceitos:

[custom_language_switcher]

...ou chame-o do PHP (por exemplo, em um arquivo de template de tema):

<?php if (function_exists('custom_language_switcher')) echo custom_language_switcher(); ?>

Essa é a base. A partir daqui você pode:

  • Adicionar CSS para organizá-lo como quiser (linha de abas, menu vertical, grade…).
  • Adicionar atributos de shortcode para torná-lo configurável.
  • Destacar o idioma atual usando $lang['isCurrent'].
  • Ocultar o idioma de origem, mostrar apenas idiomas específicos, agrupá-los, etc.

O exemplo prático abaixo mostra como isso pode parecer na prática.


Exemplo funcional: abas de idioma inline

Um seletor personalizado completo construído sobre a base acima. Ele renderiza os idiomas como uma linha horizontal de abas com bandeiras e nomes nativos, útil para colocar em um cabeçalho, ao lado de uma barra de pesquisa, ou em qualquer outro lugar onde você queira um seletor que não seja suspenso.

Ele adiciona:

  • Três opções de alinhamento: left, right, center.
  • Alternâncias para bandeiras e nomes independentemente (por exemplo, apenas bandeiras).
  • CSS embutido para que ele tenha uma boa aparência sem que você precise escrever nenhum estilo.
  • Destaca o idioma atual com aria-current="page" e uma classe --current para estilização.
  • Classes com namespace (custom-uni-tabs*) para que não colidam com mais nada.

⚠️ Use este OU o snippet de base acima, não ambos ao mesmo tempo, pois eles definiriam um shortcode. (Você pode renomear um deles para usá-los lado a lado.)

Adicionar o snippet

Cole isso no functions.php do seu tema filho (ou WPCode):

<?php
function custom_uni_tabs($atts = []) {
    if (!function_exists('universally_get_switcher_urls')) return '';
    $langs = universally_get_switcher_urls();
    if (empty($langs)) return '';

    $atts = shortcode_atts([
        'align'      => 'center',
        'show_flags' => 'true',
        'show_names' => 'true',
    ], $atts);

    $align     = in_array($atts['align'], ['left', 'right', 'center'], true) ? $atts['align'] : 'center';
    $showFlags = filter_var($atts['show_flags'], FILTER_VALIDATE_BOOLEAN);
    $showNames = filter_var($atts['show_names'], FILTER_VALIDATE_BOOLEAN);

    if (!$showFlags && !$showNames) {
        $showNames = true; // never render an empty link
    }

    static $printed_styles = false;
    $styles = '';
    if (!$printed_styles) {
        $printed_styles = true;
        $styles = '<style>
            .custom-uni-tabs { display: flex; align-items: center; gap: 16px; list-style: none; margin: 0; padding: 0; }
            .custom-uni-tabs--left   { justify-content: flex-start; }
            .custom-uni-tabs--right  { justify-content: flex-end; }
            .custom-uni-tabs--center { justify-content: center; }
            .custom-uni-tabs__item { margin: 0; padding: 0; }
            .custom-uni-tabs__link { display: inline-block; margin: 0; padding: 0; text-decoration: none; line-height: 1; }
            .custom-uni-tabs__link--current { font-weight: 600; }
            .custom-uni-tabs__flag { width: 20px; height: auto; vertical-align: middle; }
            .custom-uni-tabs__flag--with-label { margin-right: 6px; }
            .custom-uni-tabs__label { vertical-align: middle; }
        </style>';
    }

    $out = $styles . '<ul class="custom-uni-tabs custom-uni-tabs--' . esc_attr($align) . '">';
    foreach ($langs as $lang) {
        if (empty($lang['url'])) continue;
        if (!empty($lang['isDisabled'])) continue;

        $label = esc_html($lang['originalName'] ?? '');
        $url   = esc_url($lang['url']);
        $isCur = !empty($lang['isCurrent']);

        $flag = '';
        if ($showFlags && !empty($lang['flagUrl'])) {
            $flagCls = 'custom-uni-tabs__flag' . ($showNames ? ' custom-uni-tabs__flag--with-label' : '');
            $alt     = $showNames ? '' : $label;
            $flag    = '<img class="' . $flagCls . '" src="' . esc_url($lang['flagUrl']) . '" alt="' . esc_attr($alt) . '">';
        }

        $linkCls = 'custom-uni-tabs__link' . ($isCur ? ' custom-uni-tabs__link--current' : '');
        $aria    = $isCur ? ' aria-current="page"' : '';

        $out .= '<li class="custom-uni-tabs__item">';
        $out .= '<a class="' . $linkCls . '" href="' . $url . '"' . $aria . '>';
        $out .= $flag;
        if ($showNames) {
            $out .= '<span class="custom-uni-tabs__label">' . $label . '</span>';
        }
        $out .= '</a></li>';
    }
    $out .= '</ul>';

    return $out;
}
add_shortcode('custom_uni_tabs', 'custom_uni_tabs');

Usar

Shortcode

[custom_uni_tabs]

Atributos:

Atributo Valores Padrão O que faz
alinhar esquerda, direita, centro centro Alinhamento horizontal da linha.
mostrar_bandeiras verdadeiro, falso verdadeiro Mostrar/ocultar ícones de bandeira.
mostrar_nomes verdadeiro, falso verdadeiro Mostrar/ocultar nomes nativos dos idiomas.

Exemplos:

[custom_uni_tabs]
[custom_uni_tabs align="right"]
[custom_uni_tabs show_names="false"]               (flags only) 
[custom_uni_tabs show_flags="false" align="left"]  (names only, left)

PHP

Para quando você quiser inseri-lo diretamente em um arquivo de template de tema (por exemplo, header.php), em um hook, ou em um widget PHP/código de construtor de páginas. Chame a função diretamente e passe quaisquer atributos como um array:

<?php
if (function_exists('custom_uni_tabs')) {
    echo custom_uni_tabs([
        'align'      => 'center',
        'show_flags' => 'true',
        'show_names' => 'false',
    ]);
}
?>

⚠️ Edite header.php (ou qualquer arquivo principal do tema) apenas dentro de um tema filho. Editar o tema pai diretamente significa que suas alterações serão perdidas na próxima vez que o tema for atualizado.

Substituições opcionais de CSS

O exemplo vem com padrões sensatos. Substitua-os a partir da sua folha de estilos do tema sempre que precisar:

/* Bigger flags, more spacing, and a colour for the active language */
.custom-uni-tabs            { gap: 24px; }
.custom-uni-tabs__flag      { width: 24px; }
.custom-uni-tabs__link      { font-size: 14px; color: #333; }
.custom-uni-tabs__link:hover            { color: #000; }
.custom-uni-tabs__link--current         { color: #c00; font-weight: 700; }

Referência de classe:

Classe Aplicado a
.custom-uni-tabs O <ul> externo.
.custom-uni-tabs--left/right/center Modificador de alinhamento no <ul>.
.custom-uni-tabs__item Cada <li>.
.custom-uni-tabs__link Cada <a> (inline-block, sem preenchimento).
.custom-uni-tabs__link--current O link do idioma ativo.
.custom-uni-tabs__flag A flag <img>.
.custom-uni-tabs__flag--with-label Bandeira quando exibida ao lado de um nome.
.custom-uni-tabs__label O nome nativo <span>.

Onde colocar o seletor

Depois que seu shortcode for registrado, você pode colocá-lo em qualquer lugar do seu site. As etapas exatas dependem do seu tema/construtor:

  • Temas de bloco (Twenty Twenty-Four, etc.): abra Aparência → Editor, encontre o modelo ou parte do modelo que deseja editar (por exemplo, Cabeçalho, Rodapé, uma página única), insira um bloco Shortcode e cole [custom_uni_tabs].
  • Construtores de página (Elementor / Divi / Beaver Builder / Bricks): adicione um widget Shortcode ou Código onde você quiser o seletor e cole [custom_uni_tabs].
  • Temas clássicos: cole [custom_uni_tabs] diretamente em uma postagem, página ou área de widget. Para colocá-lo dentro de um arquivo de modelo de tema (por exemplo, header.php, footer.php, sidebar.php), edite o arquivo em um tema filho e adicione:
<?php if (function_exists('custom_uni_tabs')) echo custom_uni_tabs(); ?>

Solução de Problemas

Nada aparece. Certifique-se de que o plugin Universally está ativo e que pelo menos um idioma de destino está habilitado em seu projeto. Os trechos não retornam nada quando universally_get_switcher_urls() está indisponível ou vazio.

A lista está vazia ou desatualizada. A lista de idiomas é armazenada em cache em seu site por 15 minutos. Adicionar ou remover um idioma normalmente a atualiza imediatamente, mas essa atualização não pode chegar a um site que o Universally não consegue alcançar: uma instalação local ou de staging, um host com firewall, um projeto sem domínio definido ou uma solicitação que expirou. Um site que acabou de ser conectado também pode ainda estar com uma lista vazia. Abrir Universally » Geral » Idiomas força uma atualização. Salvar as configurações do plugin não faz isso.

Nenhuma bandeira é exibida. A configuração de Bandeiras de País não afeta um seletor personalizado: aplica-se apenas ao integrado. Verifique se flagUrl está vazio para esse idioma, o que acontece quando nenhuma bandeira é mapeada para sua região. A configuração está em Universally » Seletor de Idiomas » Bandeiras de País se você também quiser alterar o seletor integrado.

Visitantes não conseguem retornar ao idioma de origem. Visualizar um URL traduzido armazena o idioma do visitante por 30 dias, e URLs sem prefixo redirecionam para ele. O seletor integrado contorna isso adicionando ?universally_switch=source ao link do idioma de origem, o que limpa a escolha armazenada. Reproduza isso em seu próprio seletor:

$url = $lang['url'];
if (!empty($lang['isSource'])) {
    $url .= (strpos($url, '?') === false ? '?' : '&') . 'universally_switch=source';
}

As abas não estão alinhadas como eu esperava. No exemplo funcional, o atributo align posiciona os itens dentro do <ul>, mas o próprio <ul> ocupa apenas a largura de seu contêiner pai. Se o pai não tiver largura total, as abas podem parecer descentralizadas ou deslocadas para um lado. Envolva o shortcode em um contêiner de largura total ou adicione:

.custom-uni-tabs { width: 100%; }

O seletor flutuante padrão ainda está sendo exibido. Vá para Universally → Seletor de Idiomas e alterne a implementação de Automático para Personalizado, caso contrário, ambos aparecerão.

Erro “Não é possível redeclarar a função”. Você colou dois trechos que definem o mesmo nome de função. Mantenha apenas um ou renomeie um deles.

Isso foi útil?