Quando você precisa pensar em internacionalização de sua plataforma, é um sinal bom, vocês estão crescendo (ou já são grandes, ou só querem internacionalizar). E sabemos que este ponto é um pouco delicado e existem diversas libs por aí, e muitas delas são complexas para o que você precisa fazer (muitas vezes é apenas tradução de conteúdo, sem muitos formatos).

Recentemente conheci a lib polyglot.js, desenvolvida pela Airbnb. Trata-se de uma biblioteca js muito simples e objetiva, com apenas 2.8kb e que garanto que vai te ajudar muuuito.

Nosso cenário:
Ttemos um site mobile e um site web para nossa plataforma (não, não fizemos responsivo por questões de “não, não fizemos responsivo”).

  • O site mobile é apenas html/js/css, utilizando o generator-webapp
  • O site web possui alguns componentes em react, e os outros são server-rendering nodejs/jade template.

Agora imagina o trabalho que seria para desenvolver i18n destes dois lados, e a manutenção que teríamos. Se fosse apenas trabalhar no server-render, o package node-i18n já resolveria, inclusive nós estamos utilizando no server.

Não vou abordar essa parte de node-i18n, pois os docs deles são muito bons e também tem bastante conteúdo sobre como utilizar. Como não encontrei muita coisa sobre o polyglot.js, vou tratar dele hoje :)

Contexto no código do mobile
Precisamos tratar i18n nos arquivos javascript, visto que muito conteúdo é montado pelo js.
Precisamos tratar i18n nos arquivos .jade, visto que muito conteúdo é estático também.
Precisamos disponibilizar o polyglot pros arquivos .js
Precisamos disponibilizar o polyglot pros templates em .jade

Vamos lá
O objetivo aqui é termos 3 arquivos de tradução (pt-br, en, es), onde buscaremos o texto adequado pela key. Os arquivos serão em .json e quando o usuário indicar que quer uma tradução (vulgo clicar na bandeirinha), acionaremos a locale específica.

Como estou utilizando o generator do yeoman, temos um gulpfile onde chamamos a task views, que é a responsável por percorrer os arquivos em .jade e transformá-los para html.

No generator ela é assim:

gulpfile.babel.js
  • js
1
2
3
4
5
6
gulp.task('views', () => {
return gulp.src(['app/*.jade', 'app/**/*.jade'])
.pipe($.jade({pretty: true}))
.pipe(gulp.dest('.tmp'))
.pipe(reload({stream: true}));
});

E agora ficará assim:

gulpfile.babel.js
  • js
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
gulp.task('views', (cb) => {
let locales = {
'es': require('./locales/es.json'),
'en': require('./locales/en.json'),
'pt-br': require('./locales/pt-br.json')
}

_.each(locales, (value, key, list) => {
let polyglot = new Polyglot({phrases: value, locale: key})
let LOCALS = {
polyglot: polyglot
};
let _folder = process.env.NODE_ENV == 'production' ? `dist/${key}` : `.tmp/${key}`;

return gulp.src(['app/*.jade', 'app/**/*.jade', '!app/locales'])
.pipe($.jade({
locals: LOCALS,
pretty: true
}))
.pipe(gulp.dest(_folder))
.pipe(reload({stream: true}));
})

cb();
});

E vamos ao exemplo de um arquivo da view em jade:

about.jade
  • jade
1
2
3
4
5
6
7
8
9
10
11
12
13
14
extends layouts/default
block content
.container
.row.featured-banner
.col-md-12
img(src="images/internas/allinclusive.jpg", alt="All Inclusive")

p.search #{polyglot.t('Reserve agora')}

#fh5co-features(data-section='features')
.container
.row
.col-md-12.section-heading.text-center
h2.single-animate.animate-features-1 #{polyglot.t('Tratamento VIP a todo momento')}

Como nos 3 arquivos .json, utilizamos essa key Reserve agora, o arquivo jade será transformado para html com base no polyglot e fará a tradução de forma adequada, ficando assim:

about.html
  • ptbr
  • en
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div class="container">
<div id="pacotes-fixed" class="row featured-banner">
<div class="col-md-12"><img src="images/internas/allinclusive.jpg" alt="All Inclusive">
<p class="search">Reserve agora</p>
</div>
</div>
</div>
<div id="fh5co-features" data-section="features" class="topo-banner">
<div class="container">
<div class="row">
<div class="col-md-12 section-heading text-center">
<h2 class="single-animate animate-features-1">Tratamento VIP a todo momento</h2>
</div>
</div>
</div>
</div>

A ideia é que o site estático tenha 3 versões de idiomas (isso foi pré-definido), então o projeto na raíz é pt-br e possuirá duas pastas: /en e /es
Onde em cada pasta, teremos as views já em .html servindo para quando o user acionar as bandeiras do idioma.

Não sei se este post ficou bem explicativo e com apenas pouco código, mas tentei passar um approach que pode ser útilo quando forem pensar em internacionalização do seu site.

Caso haja muitas dúvidas, feel free to contact me @victorkurauchi

See ya.