AngularJS e i18n

Olá pessoal, na semana passada vi que alguns de vocês estão tendo problemas para implementar uma solução geral para i18n em AngularJS. Então, aqui estão meus 2 centavos sobre o assunto.

O problema:
precisávamos implementar uma solução i18n que incluísse suporte YAML e substituição de valor para que fosse geral e fácil de personalizar.

A solução:
precisamos de duas coisas para que isso aconteça corretamente, um serviço que pode analisar YAML e retornar um objeto JSON e um LanguageService que retornará a localidade do usuário (ou forçar uma localidade definida pelo usuário, para fins de alteração de idioma).
Então, escrevemos um serviço que carrega um arquivo YAML que é nomeado de acordo com a localidade do usuário (por exemplo en-us.i18n.yml )

Serviço i18n

angular.module('MyAppApp.services').service('i18nService', ['yamljs', 'LanguageService', function(yamljs, LanguageService) {
var errorString = "i18n error: ";
var self = this;
self.loaded = false;
self.isLoading = false;
self.yaml = {};

this.replaceValues = function(str, obj, dotnotation) {
if(obj) {
var regex;
for(i in obj) {
regex
= new RegExp("@" + i + "@", "g");
str
= str.replace(regex, obj[i]);
}
}
if(!str) return errorString + dotnotation;
return str;
}

this.recompose = function(obj, string) {

var parts = string.split('.');
var newObj = obj[parts[0]];
if(parts[1]) {
parts
.splice(0, 1);
var newString = parts.join('.');
return this.recompose(newObj, newString);
}
return newObj;
}


this.t = function(dotNotation, objectReplace) {
if(!self.isLoading) {
if(self.loaded) {
return self.replaceValues(self.recompose(self.yaml, dotNotation), objectReplace, dotNotation);
} else {
self.isLoading = true;
yamljs
.loadFromFile("yaml/" + LanguageService.getCurrentLanguage() + ".i18n.yml").then(function(o) {
self.yaml = o;
self.loaded = true;
self.isLoading = false;
return self.replaceValues(self.recompose(self.yaml, dotNotation), objectReplace, dotNotation);

}, function() {
console
.error("Error loading locale file. Trying default locale file.");
self.isLoading = true;
yamljs
.loadFromFile("yaml/en-us.i18n.yml").then(function(o) {
self.yaml = o;
self.loaded = true;
self.isLoading = false;
return self.replaceValues(self.recompose(self.yaml, dotNotation), objectReplace, dotNotation);

}, function() {
self.isLoading = false;
console
.error("Error loading default locale YAML file (en-us)");
});
});
}
}
};
}]);

YAML JS

angular.module('StoreApp.services').service('yamljs', ['$http', '$q', function($http, $q) {
var self = this;
// YAML - Core - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
// Modified by Filipe Melo <filipe.melo@centralway.com> as an AngularJS Service in 17.04.2013

// --- Helpers

/**
* Return 'near "context"' where context

* is replaced by a chunk of _str_.

*

*
@param {string} str
* @return {string}

* @api public

*/


var context = function(str) {
if(typeof str !== 'string') return ''
str
= str
.slice(0, 25)
.replace(/n/g, '\n')
.replace(/"/g, '\"')
return 'near ""' + str + '""'
}

// --- Lexer

/**
* YAML grammar tokens.

*/


var tokens = [
['comment'