Reconstruindo a torre de Babel

com RequireJS

e outras bibliotecas legais

Criado por Leo Moura / @lfsmoura

##Pedra de Rosetta ![Pedra de Rosetta](assets/rosetta.png)

i18n


"i" + "nternationalizatio".length + "n"
// > "i18n"
  • l10n - localization
  • g11n - globalization
  • NLS - native language support
* Linguistas estimam que o número de línguas existentes seja em torno de **6000** * \> 70% da Internet não fala inglês * Localizar para 8 línguas significa atingir 80% da população mundial
Internacionalização - dificuldades
Greece, Iran, Lebanon, Syria, Palestine, Turkey, Macedonia, Bulgaria, Albania, and Sicily
##Internacionalização é muito mais que traduzir strings * People have exactly one canonical full name. * People have exactly N names, for any value of N. * People’s names fit within a certain defined amount of space. * People’s names are written in ASCII. * People’s names are written in any single character set. * People’s names are all mapped in Unicode code points. * People’s names are case sensitive. * People’s names are case insensitive. * People’s names do not contain numbers.
##Internacionalização é muito mais que traduzir strings
##Como as linguas podem variar * direção (esquerda para direita, direita para a esquerda) * formato de data e hora * formato dos números * plurais * símbolos e pontuação * unidades de medida * tamanhos de folhas de impressão * atalhos e teclas * questões culturais
* Estou ausente fui "almoçar" * Estou ausente fui „almoçar“ * Estou ausente fui ”almoçar” * Estou ausente fui «almoçar» * Estou ausente fui 「almoçar」
##Microsoft Checklist - Look for geo-political sensitivity issues (e.g., borders may be disputed between neighboring countries) - Run with Complex scripts and Right to Left (RTL) support - Verify all controls function correctly with the East Asian (IME) - Verify switching the keyboard to a different mapping works correctly - **Verify ANSI, double-byte, and Unicode text are handled correctly for display, input, and elsewhere (e.g., double-byte characters will be split if treated as ANSI)** - Verify any language-dependant features work correctly
![JS poo](assets/poop.png) * [Javascript has a Unicode problem](https://mathiasbynens.be/notes/javascript-unicode)
##Microsoft Checklist - Verify extended and non-standard characters are displayed and handled correctly - Verify controls in dialogs and elsewhere are aligned and sized correctly (e.g., text is not truncated) - Verify any functionality affected by the localization process works correctly - Verify data is ordered correctly - Verify tab order is correct - Verify no unlocalized strings remain - Verify hot keys are [sic] localzied

Show me the code

  1. RequireJS + plugin i18n
  2. RequireJS + plugin Handlebars + FormatJS

Detectando a língua no servidor


var app = require('express')();
var appLocales = ['de', 'en', 'fr'];

app.get('/', function (req, res) {
	var locale = req.acceptsLanguages(appLocales) || 'en';
	// ...customize the response to locale
});
	
[BCP47](http://tools.ietf.org/html/bcp47) * en - inglês * mas - Maasai * pt-BR - Português do Brasil * es-419 - Espanhol da América Latina * zn-Hans - Chinês com caracteres simplificados
Usando o plugin `i18n` ![Estrutura do programa](assets/requirejs.png)
Usando o plugin `i18n` ![Estrutura do programa](assets/structure.png)

Usando o plugin i18n


// js/nls/main.js
define({
	root: true,
	"pt-br": true
});
// js/nls/root/main.js
define({
	greetings: "hello world",
	home: "Home",
	about: "About"
});
// js/nls/pt-br/main.js
define({
	greetings: "Olá mundo",
	home: "Home",
	about: "Sobre"
});
					
Usando o plugin i18n

requirejs(['i18n!nls/main'], function(lang) {
	console.log(lang);
});
					
![chat](assets/chat.png)
Configurando manualmente a língua

require.config({
    config: {
        i18n: {
            locale: 'pt-br'
        }
    }
});
							
Para formatar datas ![Moment.js](assets/moment.png)
## Usando handlebars e FormatJS ![Moment.js](assets/handlebars.png)

Handlebars


{{title}}

{{body}}
    {{#each items}}
  • {{agree_button}}
  • {{/each}}

var context = {
	items: [
	    {name: "Handlebars", emotion: "love"},
	    {name: "Mustache", emotion: "enjoy"},
	    {name: "Ember", emotion: "want to learn"}
	  ]
};
Handlebars.registerHelper('agree_button', function() {
  var emotion = Handlebars.escapeExpression(this.emotion),
      name = Handlebars.escapeExpression(this.name);
  return new Handlebars.SafeString(
    ""
  );
});

var source   = $("#entry-template").html();
var template = Handlebars.compile(source);
					

require.config({
	paths: {
		hbs: 'lib/require-handlebars-plugin/hbs'
	},
	hbs: {
		helpers: false
	}
});

require(['hbs!templates/main'], function(tplMain) {
	var text = tplMain();
}
					

	
	
{{formatMessage (intlGet "messages.welcome")}} {{name}}

{{formatDate date day="numeric" month="long" year="numeric"}}


// js/nls/pt-br.js
define({
  locales: 'pt-BR',
  messages: {
    welcome: "Bem-vindo!"
  }
});
					

requirejs(['hbs/handlebars', 'handlebars-intl',
	'hbs!templates/main',
	'nls/pt-BR'],
	function(Handlebars, HandlebarsIntl, mainTpl, intlData) {
  HandlebarsIntl.registerWith(Handlebars);
  var context = {
    name: 'Leo',
    price: 1000,
    date: new Date()
  };
  var text = mainTpl(context, {
    data: {intl: intlData}
  });
  document.body.innerHTML = text;
});
					
Bem-vindo! Leo

24 de setembro de 2015


  • {{formatNumber num}}
  • {{formatNumber completed style="percent"}}
  • {{formatNumber price style="currency" currency="USD"}}
fr
    42 000
    90 %
    100,95 $US
pt-BR
    42.000
    90%
    US$100,95

{{formatDate date day="numeric" month="long" year="numeric"}}

en-US
September 24, 2015
pt-BR
24 de setembro de 2015

{{formatRelative postDate}} {{formatRelative postDate units="minute"}}

yesterday
1,320 minutes ago

{{formatMessage (intlGet "messages.coffee_drinking") name=name numCups=numCups}}

{ coffee_drinking: "Usuário {name} {numCups, plural, \ =0 {não} \ other {} } tomou {numCups, plural,\ =0 {nenhuma xícara}\ =1 {uma xícara}\ other {# xícaras}} de café" }
Usuário Leo não tomou nenhuma xícara de café
* [ECMA-402 JavaScript internalization specification](http://www.ecma-international.org/ecma-402/1.0/index.html#sec-4.1) * [Microsoft test checklist](http://www.thebraidytester.com/downloads/YouAreNotDoneYet.pdf)
##Muchas Gracias! [@lfsmoura](http://twitter.com/lfsmoura)