terça-feira, 6 de junho de 2017

Personalizando o Idioma da Interface Gráfica do Zabbix

Introdução

Demonstrarei nesse post como realizar a alteração do idioma do Zabbix. Pode-se alterar apenas alguns termos ou todos os termos.

Objetivo

O objetivo desse post é ser uma Prova de Conceito, é fazer com que as pessoas pensem fora da caixa. O Zabbix é uma ferramenta fantástica, que permite coletar dados, exibi-los em forma de gráficos e mapas, reagir às métricas coletadas, seja alterando um ícone no gráfico, enviando uma notificação, executando um comando, etc.

O problema é que as pessoas pensam no Zabbix apenas para redes Ethernet e Aplicações! Há algum tempo vemos algumas iniciativas, como do Luciano Alves (Unirede) expandindo isso para uma visão de negócios, o Norberto Rozas (Syspro) que propôs a ideia de usar o Zabbix como supervisório de redes industriais, O Luiz Sales com seus monitoramentos nada convencionais, etc.

No começo do ano eu iniciei o mestrado em Engenharia Elétrica, trabalhando com Redes de Sensores Sem Fio (RSSF), e claro minha proposta foi a de utilizar o Zabbix como ferramenta para o gerenciamento dessas redes, mas conforme as ideias foram surgindo, fui lendo os artigos, conversando com meu orientador, eu fui percebendo um imenso aumento do uso de conceitos como IoT, Smart Cities, Smart Campus, etc. E com isso novos interesses foram sendo despertados.

O Zabbix pode ser usado como Interface para os usuários finais, independente da área de atuação, porém será preciso fazer algumas modificações, pois cada área possui seu conjunto de jargões, sua definição de ícones, de interface, etc. Personalizar o Zabbix para que o usuário tenha uma visão que lhe seja familiar, é essencial. O que estou propondo é utilizar o que o Zabbix tem de melhor, e adaptar o que for necessário para que o usuário se sinta motivado a utilizá-lo.

O que essa solução é

Um Hack: Tenha isso em mente, o que estou fazendo não servirá para qualquer um, em qualquer ambiente, não é suportado pela Zabbix SIA e pode nem ser interessante no seu ponto de vista.
Uma Prova de Conceito: Esse post está longe de ser a palavra final sobre o assunto, eu tinha uma necessidade, achei uma maneira de executá-la e estou compartilhando com vocês.

O que essa solução não é

Prática: A cada nova versão da ferramenta, será preciso reaplicar o hack.
Universal: Veja que essa solução é ideal para ambientes, onde um ou dois idiomas são utilizados, mas não atende uma empresa global, também não atende dezenas de segmentos ao mesmo tempo.

Entendendo como funcionam os idiomas no Zabbix

Consultando a documentação oficial descobrimos que eles utilizam o GNU/gettext e o conceito de locales, que envolve uma série de normas internacionais e vai muito além da simples tradução de textos. Por isso é muito provável que esse hack nunca seja absorvido oficialmente pela Zabbix SIA.

Entendendo os os arquivos que controlam o idioma que é exibido na Interface Gráfica

Vamos analizar o diretório com o idioma do Brasil (pt_BR):
# ls -l /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/
total 940
-rw-r--r-- 1 zabbix zabbix 309122 Mai 30 17:26 frontend.mo
-rw-r--r-- 1 zabbix zabbix 649043 Mai 30 17:20 frontend.po

Enquanto o arquivo frontend.mo é um arquivo com uma codificação especial, descrita na documentação como uma "foto". E repleto de caracteres especiais:
# head -3 /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.mo
▒gGl▒▒▒/▒▒9▒5F [|▒▒▒!▒▒▒▒▒%▒,
3>Z
cn


O arquivo frontend.po é descrito na documentação como um arquivo texto, editável e utilizado para a tradução.
# head -3 /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.po
msgid ""
msgstr ""
"Project-Id-Version: Zabbix 3.2\n"


Observe esse trecho do arquivo frontend.po:
   4592 #: include/actions.inc.php:660 include/actions.inc.php:1061
   4593 msgid "Disable host"
   4594 msgstr "Desativar host"
   4595
   4596 #: include/views/configuration.host.list.php:116
   4597 msgid "Disable host?"
   4598 msgstr "Desabilitar host?"
   4599
   4600 #: app/views/administration.proxy.list.php:154
   4601 #: include/views/configuration.hostgroups.list.php:150
   4602 msgid "Disable hosts"
   4603 msgstr "Desativar hosts"
   4604
   4605 #: include/views/configuration.hostgroups.list.php:151
   4606 msgid "Disable hosts in the selected host groups?"
   4607 msgstr "Desabilitar os hosts nos grupos selecionados?"


Ele contém as strings que desejamos alterar, o problema é que alterar esse arquivo não surte efeito algum na interface gráfica. Pois se observarmos o arquivo que é chamado na linha 4596, por exemplo:
# vi /var/www/html/zabbix/include/views/configuration.host.list.php +116
                $confirm_message = _('Disable host?');


Verificamos que ele busca como referência a frase original, e, então aplica a tradução.

Observe esse trecho "^@Desabilitar host^@D" da linha 523 do arquivo /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.mo

Veja o que acontece se eu troco a frase por outra com o mesmo número de caracteres:
"^@Desabilitar sens^@D"

E reinicio o apache:
# systemctl restart httpd
Hack 01 no arquivo frontend.mo
Agora veja o que acontece e eu troco a frase por outra com um número diferente de caracteres:
"^@Desabilitar sensor^@D"

E reinicio o apache:
# systemctl restart httpd

Hack 02 no arquivo frontend.mo
Lembra que a documentação diz que o arquivo .mo é como uma foto? É nesse sentido. A mensagem aparece correta, mas todo o resto da formatação da interface gráfica se perdeu.

Basta voltar o arquivo ao normal e reiniciar o apache, que a interface gráfica também volta ao normal.
Interface Gráfica intacta após a remoção do Hack

Conclusões Iniciais

Devemos utilizar o arquivo frontend.po para gerar um arquivo frontend.mo atualizado. Mas como?

Observando o diretório /var/www/html/zabbix/locale temos um README e três scripts:
# ls -l *.sh README
-rwxr-xr-x 1 zabbix zabbix  385 Dez 21 05:08 add_new_language.sh
-rwxr-xr-x 1 zabbix zabbix  164 Mai 30 17:29 make_mo.sh
-rw-r--r-- 1 zabbix zabbix  957 Dez 21 05:08 README
-rwxr-xr-x 1 zabbix zabbix 1434 Dez 21 05:08 update_po.sh


No arquivo README encontramos a seguinte instrução:
If you want to update po files with new strings in the sourcefile, run update_po.sh . It will gather translatable strings from all files that end with ".php"

Maravilha é exatamente o que pretendemos fazer!

Vou mover o arquivo frontend.mo para o /root:
# mv /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.mo /root

E editar o arquivo frontend.po:
# vi /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.po
Alteramos as linhas 4592 até 4607, alterando as ocorrências de "host" para "sensor" e  de "hosts" para "sensores", e executamos o script:
# sh update_po.sh
Generating translation template...
Merging new strings in po files...
.
.
.
pt_BR
............................................................................................................................................................................................................................................................................................................................................. feito.
.
.
.
pt_BR/LC_MESSAGES/frontend.po   3316 mensagens traduzidas, 5 mensagens não traduzidas.
.
.
.


Mas... Não gerou um novo arquivo .mo:
# ls -l  /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.*
-rw-r--r-- 1 zabbix zabbix 649043 Mai 31 09:59 /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.po


Sem ele, mesmo com o idioma setado para Português (pt_BR)
Idioma setado como pt_BR
A interface gráfica fica em Inglês.
Interface Gráfica em Inglês

Basta trazer o arquivo de volta e reiniciar o apache:
# mv /root/frontend.mo /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/
# systemctl restart httpd


Que a interface gráfica volta ao normal.
Intreface Gráfica em pt_BR

Teste 02: Vamos rodar o update_po.sh e ver se ele atualiza o arquivo frontend.mo

# ls -l /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.mo
-rw-r--r-- 1 zabbix zabbix 309122 Mai 31 09:53 /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.mo
 

# sh update_po.sh
 

# ls -l /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.mo
-rw-r--r-- 1 zabbix zabbix 309122 Mai 31 09:53 /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.mo


E nada :-(

Teste 03: Vamos ver o que esse script faz ;-)

E na última instrução temos:
        # setting output file to /dev/null so that unneeded messages.mo file
        # is not created
        msgfmt --use-fuzzy -c --statistics -o /dev/null $translation

Achei!!! Esse script realmente não cria os arquivos.mo. Agora eu vou alterar ele para gerar os arquivos:
        #msgfmt --use-fuzzy -c --statistics -o /dev/null $translation
        msgfmt --use-fuzzy -c --statistics -o /root/$translation/frontend.mo $translation


Eu fiz a menor alteração possível, apenas substituindo "/dev/null" por "/root/$translation/frontend.mo". Isso poderia ficar bem mais elegante, mas preferi ser didático.

Vou criar apenas o diretório pt_BR, que será utilizado pela variável "$translation", os outros idiomas vão dar erro, mas nesse momento não tem problema:
# mkdir -p /root/pt_BR/LC_MESSAGES/frontend.po/

Vou guardar o antigo frontend.mo no /root
# mv /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/frontend.mo /root/

E rodar o script de update novamente:
# sh update_po.sh
Generating translation template...
Merging new strings in po files...
.
.
.
pt_BR
............................................................................................................................................................................................................................................................................................................................................. feito.
.
.
.
bg/LC_MESSAGES/frontend.po      msgfmt: erro ao abrir o arquivo "/root/bg/LC_MESSAGES/frontend.po/frontend.mo" para gravação: Arquivo ou diretório não encontrado
2052 mensagens traduzidas, 56 traduções aproximadas (fuzzy), 1213 mensagens não traduzidas.
.
.
.
pt_BR/LC_MESSAGES/frontend.po   3316 mensagens traduzidas, 5 mensagens não traduzidas.
.
.
.


E agora vamos colocar o novo frontend.mo na interface gráfica do Zabbix:
# cp /root/pt_BR/LC_MESSAGES/frontend.po/frontend.mo /var/www/html/zabbix/locale/pt_BR/LC_MESSAGES/

Reiniciar o apache
# systemctl restart httpd

E Voilà:

Interface Gráfica com a mensagem alterada
Volte o arquivo que você salvou no /root e reinicie o apache. Pois agora vamos fazer o trabalho, de verdade, vamos ter o Zabbix em Português com a interface intacta, e mais 3 variações do Português aplicado à nichos específicos.

Primeiro vamos criar a estrutura de diretórios para os idiomas Italiano (it), Francês (fr) e Russo (ru):
# mkdir -p /root/{it,fr,ru}/LC_MESSAGES/frontend.po/

Abaixo uma pequena cola, das alterações que vamos fazer:
pt_br - Hosts / Itens - Administrador da Rede Ethernet
it - Sensores / Métricas - Administrador da Rede de Sensores
fr - Plantas / Características - Usuário da Rede de Sensores - Ramo Agrícola
ru - Pacientes / Sinais Vitais - Usuário da Rede de Sensores - Ramo Medicina

Vamos copiar o arquivo frontend.po de pt_BR para os idiomas que vamos alterar:
# cd /var/www/html/zabbix/locale

# cp pt_BR/LC_MESSAGES/frontend.po it/LC_MESSAGES/frontend.po
cp: sobrescrever “it/LC_MESSAGES/frontend.po”? y

# cp pt_BR/LC_MESSAGES/frontend.po fr/LC_MESSAGES/frontend.po
cp: sobrescrever “fr/LC_MESSAGES/frontend.po”? y

# cp pt_BR/LC_MESSAGES/frontend.po ru/LC_MESSAGES/frontend.po
cp: sobrescrever “ru/LC_MESSAGES/frontend.po”? y


Primeiro vamos trabalhar no idioma Italiano e trocar todas as ocorrências de hosts por sensores e depois de host por sensor:
# sed -i -e ':g;/^msgstr/s/hosts/sensores/g' /var/www/html/zabbix/locale/it/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/host/sensor/g' /var/www/html/zabbix/locale/it/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Hosts/Sensores/g' /var/www/html/zabbix/locale/it/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Host/Sensor/g' /var/www/html/zabbix/locale/it/LC_MESSAGES/frontend.po


Agora vamos trocar todas as ocorrências de itens por métricas e depois de item por métrica:
# sed -i -e ':g;/^msgstr/s/itens/métricas/g' /var/www/html/zabbix/locale/it/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/item/métrica/g' /var/www/html/zabbix/locale/it/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Itens/Métricas/g' /var/www/html/zabbix/locale/it/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Item/Métrica/g' /var/www/html/zabbix/locale/it/LC_MESSAGES/frontend.po


Agora vamos ao idioma Francês, vamos trocar todas as ocorrências de hosts por plantas e depois de host por planta:
# sed -i -e ':g;/^msgstr/s/hosts/plantas/g' /var/www/html/zabbix/locale/fr/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/host/planta/g' /var/www/html/zabbix/locale/fr/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Hosts/Plantas/g' /var/www/html/zabbix/locale/fr/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Host/Planta/g' /var/www/html/zabbix/locale/fr/LC_MESSAGES/frontend.po


Agora vamos trocar todas as ocorrências de itens por características e depois de item por característica:
# sed -i -e ':g;/^msgstr/s/itens/características/g' /var/www/html/zabbix/locale/fr/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/item/característica/g'  /var/www/html/zabbix/locale/fr/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Itens/Características/g' /var/www/html/zabbix/locale/fr/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Item/Característica/g' /var/www/html/zabbix/locale/fr/LC_MESSAGES/frontend.po


E finalmente vamos ao idioma Russo, vamos trocar todas as ocorrências de hosts por pacientes e depois de host por paciente:
# sed -i -e ':g;/^msgstr/s/hosts/pacientes/g' /var/www/html/zabbix/locale/ru/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/host/paciente/g' /var/www/html/zabbix/locale/ru/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Hosts/Pacientes/g' /var/www/html/zabbix/locale/ru/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Host/Paciente/g' /var/www/html/zabbix/locale/ru/LC_MESSAGES/frontend.po


Agora vamos trocar todas as ocorrências de itens por sinais vitais e depois de item por sinal vital:
# sed -i -e ':g;/^msgstr/s/itens/sinais vitais/g' /var/www/html/zabbix/locale/ru/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/item/sinal vital/g' /var/www/html/zabbix/locale/ru/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Itens/Sinais Vitais/g' /var/www/html/zabbix/locale/ru/LC_MESSAGES/frontend.po

# sed -i -e ':g;/^msgstr/s/Item/Sinal Vital/g' /var/www/html/zabbix/locale/ru/LC_MESSAGES/frontend.po


Eentão gerar os nossos arquivos frontend.mo atualizados:
# sh update_po.sh

E coloca-los na interface gráfica do Zabbix:
# cp /root/fr/LC_MESSAGES/frontend.po/frontend.mo /var/www/html/zabbix/locale/fr/LC_MESSAGES/frontend.mo
cp: sobrescrever “/var/www/html/zabbix/locale/fr/LC_MESSAGES/frontend.mo”? y

# cp /root/it/LC_MESSAGES/frontend.po/frontend.mo /var/www/html/zabbix/locale/it/LC_MESSAGES/frontend.mo
cp: sobrescrever “/var/www/html/zabbix/locale/it/LC_MESSAGES/frontend.mo”? y

# cp /root/ru/LC_MESSAGES/frontend.po/frontend.mo /var/www/html/zabbix/locale/ru/LC_MESSAGES/frontend.mo
cp: sobrescrever “/var/www/html/zabbix/locale/ru/LC_MESSAGES/frontend.mo”? y


Reiniciar o Apache
# systemctl restart httpd

E pronto:
Interface Gráfica com o Hack Aplicado

Conclusão:

Esse é apenas um pequeno exemplo de que com um pouco de criatividade e algum esforço, podemos levar o Zabbix a outros nichos e ampliar a nossa área de atuação, seja ela pessoal, acadêmica ou profissional.