Post

Como suportar múltiplos idiomas em um blog Jekyll com Polyglot (1) - Aplicando o plugin Polyglot e implementando tags hreflang alt, sitemap e botão de seleção de idioma

Apresenta o processo de implementação de suporte multilíngue em um blog Jekyll baseado no tema 'jekyll-theme-chirpy' usando o plugin Polyglot. Este post é o primeiro da série, cobrindo a aplicação do plugin Polyglot e a modificação do cabeçalho HTML e sitemap.

Como suportar múltiplos idiomas em um blog Jekyll com Polyglot (1) - Aplicando o plugin Polyglot e implementando tags hreflang alt, sitemap e botão de seleção de idioma

Visão geral

Cerca de 4 meses atrás, no início de julho de 2024, adicionei suporte multilíngue a este blog baseado em Jekyll e hospedado via GitHub Pages, aplicando o plugin Polyglot. Esta série compartilha os bugs encontrados durante o processo de aplicação do plugin Polyglot ao tema Chirpy, suas soluções, e métodos para escrever cabeçalhos HTML e sitemap.xml considerando SEO. A série consiste em dois posts, e este é o primeiro deles.

Requisitos

  • Deve ser capaz de fornecer o resultado da compilação (páginas web) separado por caminhos de idioma (ex. /posts/pt-BR/, /posts/ja/).
  • Para minimizar o tempo e esforço adicionais necessários para o suporte multilíngue, deve ser capaz de reconhecer automaticamente o idioma com base no caminho local onde o arquivo markdown original está localizado (ex. /_posts/pt-BR/, /_posts/ja/) durante a compilação, sem a necessidade de especificar manualmente as tags ‘lang’ e ‘permalink’ no YAML front matter de cada arquivo markdown escrito.
  • A parte do cabeçalho de cada página do site deve incluir meta tags Content-Language apropriadas e tags alternativas hreflang para atender às diretrizes de SEO para busca multilíngue do Google.
  • Deve ser capaz de fornecer links para todas as páginas que suportam cada idioma no site, sem omissões, no sitemap.xml, e o próprio sitemap.xml deve existir apenas uma vez no caminho raiz, sem duplicações.
  • Todas as funcionalidades fornecidas pelo tema Chirpy devem funcionar normalmente em cada página de idioma, e se não funcionarem, devem ser modificadas para funcionar corretamente.
    • Funcionamento normal das funcionalidades ‘Recently Updated’ e ‘Trending Tags’
    • Sem erros no processo de compilação usando GitHub Actions
    • Funcionamento normal da função de busca de posts no canto superior direito do blog

Aplicando o plugin Polyglot

Como o Jekyll não suporta nativamente blogs multilíngues, é necessário usar um plugin externo para implementar um blog multilíngue que atenda aos requisitos acima. Após pesquisar, descobri que o Polyglot é amplamente usado para implementação de sites multilíngues e pode satisfazer a maioria dos requisitos acima, então adotei este plugin.

Instalação do plugin

Como estou usando o Bundler, adicionei o seguinte conteúdo ao Gemfile:

1
2
3
group :jekyll_plugins do
   gem "jekyll-polyglot"
end

Depois, executar bundle update no terminal completa automaticamente a instalação.

Se você não estiver usando o Bundler, pode instalar a gem diretamente com o comando gem install jekyll-polyglot no terminal e então adicionar o plugin ao _config.yml da seguinte forma:

1
2
plugins:
  - jekyll-polyglot

Configuração

Em seguida, abra o arquivo _config.yml e adicione o seguinte conteúdo:

1
2
3
4
5
6
# Polyglot Settings
languages: ["en", "ko", "es", "pt-BR", "ja", "fr", "de"]
default_lang: "en"
exclude_from_localization: ["javascript", "images", "css", "public", "assets", "sitemap"]
parallel_localization: false
lang_from_path: true
  • languages: Lista de idiomas que você deseja suportar
  • default_lang: Idioma padrão de fallback
  • exclude_from_localization: Especifica expressões regulares de strings de caminho de arquivos/pastas raiz a serem excluídos da localização
  • parallel_localization: Valor booleano que especifica se o processamento multilíngue deve ser paralelizado durante a compilação
  • lang_from_path: Valor booleano, quando definido como ‘true’, reconhece e usa automaticamente o código de idioma se a string do caminho do arquivo markdown contiver um código de idioma, mesmo que a propriedade ‘lang’ não seja especificada explicitamente no YAML front matter dentro do arquivo markdown do post

A documentação oficial do protocolo Sitemap afirma o seguinte:

“A localização de um arquivo Sitemap determina o conjunto de URLs que podem ser incluídos nesse Sitemap. Um arquivo Sitemap localizado em http://example.com/catalog/sitemap.xml pode incluir quaisquer URLs começando com http://example.com/catalog/ mas não pode incluir URLs começando com http://example.com/images/.”

“É fortemente recomendado que você coloque seu Sitemap no diretório raiz do seu servidor web.”

Para cumprir isso, deve-se adicionar ‘sitemap’ à lista ‘exclude_from_localization’ para garantir que apenas um arquivo sitemap.xml exista no diretório raiz, em vez de criar arquivos sitemap.xml com o mesmo conteúdo para cada idioma, como no exemplo incorreto abaixo.

Exemplo incorreto (o conteúdo de cada arquivo é idêntico, não diferindo por idioma):

  • /sitemap.xml
  • /pt-BR/sitemap.xml
  • /es/sitemap.xml
  • /ko/sitemap.xml
  • /ja/sitemap.xml
  • /fr/sitemap.xml
  • /de/sitemap.xml

Definir ‘parallel_localization’ como ‘true’ pode reduzir significativamente o tempo de compilação, mas em julho de 2024, havia um bug onde os títulos dos links nas seções ‘Recently Updated’ e ‘Trending Tags’ na barra lateral direita da página não eram processados corretamente e se misturavam com outros idiomas quando esta função era ativada para este blog. Parece que ainda não está totalmente estabilizado, então é necessário testar previamente se funciona normalmente antes de aplicar ao site. Além disso, essa função não é suportada ao usar Windows, então deve ser desativada.

Além disso, no Jekyll 4.0, é necessário desativar a geração de sourcemaps CSS da seguinte forma:

1
2
sass:
  sourcemap: never # No Jekyll 4.0, os mapas de origem SCSS serão gerados incorretamente devido à forma como o Polyglot opera

Pontos a considerar ao escrever posts

Ao escrever posts multilíngues, deve-se considerar o seguinte:

  • Especificação apropriada do código de idioma: Deve-se especificar o código de idioma ISO apropriado usando o caminho do arquivo (ex. /_posts/pt-BR/example-post.md) ou a propriedade ‘lang’ no YAML front matter (ex. lang: pt-BR). Consulte os exemplos na documentação do desenvolvedor do Chrome.

No entanto, embora a documentação do desenvolvedor do Chrome use o formato ‘pt_BR’ para códigos regionais, na prática, deve-se usar ‘pt-BR’ com um hífen (-) em vez de um sublinhado (_) para que funcione corretamente ao adicionar tags alternativas hreflang ao cabeçalho HTML posteriormente.

  • O caminho e o nome do arquivo devem ser consistentes.

Para mais detalhes, consulte o README do repositório GitHub untra/polyglot.

Modificando o cabeçalho HTML e o sitemap

Agora, para SEO, precisamos inserir meta tags Content-Language e tags alternativas hreflang no cabeçalho HTML de cada página do blog.

Cabeçalho HTML

Na versão 1.8.1, a mais recente em novembro de 2024, o Polyglot tem uma função que realiza automaticamente as tarefas acima quando a tag Liquid {% I18n_Headers %} é chamada na parte do cabeçalho da página. No entanto, isso assume que a tag de atributo ‘permalink’ foi especificada explicitamente naquela página, e não funcionará corretamente se não for o caso.

Portanto, eu peguei o head.html do tema Chirpy e adicionei diretamente o seguinte conteúdo. Trabalhei com referência à página SEO Recipes do blog oficial do Polyglot, mas modifiquei para usar o atributo page.url em vez de page.permalink quando este último não estiver disponível. Além disso, referindo-me à documentação oficial do Google Search Central, especifiquei x-default em vez de site.default_lang como o valor do atributo hreflang para a página de idioma padrão do site, para que o link dessa página seja reconhecido como fallback quando o idioma preferido do visitante não estiver na lista de idiomas suportados pelo site ou quando o idioma preferido do visitante não puder ser reconhecido.

1
2
3
4
5
6
  <meta http-equiv="Content-Language" content="{{site.active_lang}}">

  {% if site.default_lang %}<link rel="alternate" hreflang="x-default" href="{{site.url}}{{page.url}}" />{% endif %}
  {% for lang in site.languages %}{% if lang == site.default_lang %}{% continue %}{% endif %}
  <link rel="alternate" hreflang="{{lang}}" href="{{site.url}}/{{lang}}{{page.url}}" />
  {% endfor %}

Sitemap

Como o sitemap gerado automaticamente pelo Jekyll durante a compilação não suporta corretamente páginas multilíngues, crie um arquivo sitemap.xml no diretório raiz e insira o seguinte conteúdo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
---
layout: content
---
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">
{% for lang in site.languages %}

    {% for node in site.pages %}
        {% comment %}<!-- verificação muito preguiçosa para ver se a página está na lista de exclusão - isso significa que as páginas excluídas não estarão no sitemap de forma alguma, escreva exceções conforme necessário -->{% endcomment %}
        {% unless site.exclude_from_localization contains node.path %}
            {% comment %}<!-- assumindo que se não houver layout atribuído, então não inclua a página no sitemap, você pode querer mudar isso -->{% endcomment %}
            {% if node.layout %}
                <url>
                    <loc>{% if lang == site.default_lang %}{{ node.url | absolute_url }}{% else %}{{ node.url | prepend: lang | prepend: '/' | absolute_url }}{% endif %}</loc>
                    {% if node.last_modified_at and node.last_modified_at != node.date %}<lastmod>{{ node.last_modified_at | date: '%Y-%m-%dT%H:%M:%S%:z' }}</lastmod>{% elsif node.date %}<lastmod>{{ node.date | date: '%Y-%m-%dT%H:%M:%S%:z' }}</lastmod>{% endif %}
                </url>
            {% endif %}
        {% endunless %}
    {% endfor %}

    {% comment %}<!-- Isso percorre todas as coleções do site, incluindo posts -->{% endcomment %}
    {% for collection in site.collections %}
        {% for node in site[collection.label] %}
            <url>
                <loc>{% if lang == site.default_lang %}{{ node.url | absolute_url }}{% else %}{{ node.url | prepend: lang | prepend: '/' | absolute_url }}{% endif %}</loc>
                {% if node.last_modified_at and node.last_modified_at != node.date %}<lastmod>{{ node.last_modified_at | date: '%Y-%m-%dT%H:%M:%S%:z' }}</lastmod>{% elsif node.date %}<lastmod>{{ node.date | date: '%Y-%m-%dT%H:%M:%S%:z' }}</lastmod>{% endif %}
            </url>
        {% endfor %}
    {% endfor %}

{% endfor %}
</urlset>

Adicionando botão de seleção de idioma à barra lateral

Criei o arquivo _includes/lang-selector.html e inseri o seguinte conteúdo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<p>
{%- for lang in site.languages -%}
  {%- if lang == site.default_lang -%}
<a ferh="{{ page.url }}" style="display:inline-block; white-space:nowrap;">
    {%- if lang == site.active_lang -%}
      <b>{{ lang }}</b>
    {%- else -%}
      {{ lang }}
    {%- endif -%}
</a>
  {%- else -%}
<a href="/{{ lang }}{{ page.url }}" style="display:inline-block; white-space:nowrap;">
  {%- if lang == site.active_lang -%}
      <b>{{ lang }}</b>
    {%- else -%}
      {{ lang }}
    {%- endif -%}
</a>
  {%- endif -%}
{%- endfor -%}
</p>

Em seguida, adicionei as seguintes três linhas à parte da classe “sidebar-bottom” do _includes/sidebar.html do tema Chirpy para que o Jekyll carregue o conteúdo do _includes/lang-selector.html criado anteriormente durante a compilação da página:

1
2
3
    <div class="lang-selector">
      {%- include lang-selector.html -%}
    </div>

Leitura Adicional

Continuado na Parte 2

This post is licensed under CC BY-NC 4.0 by the author.