Árvore de páginas

Utilização

Para internacionalização (tradução e localização) é recomendado a adição de um AngularJS Filter registrado com o nome de i18n. Este filter deverá ser uma função que irá receber uma literal ou uma chave para tradução. Após a definição do mecanismo de internacionalização sua utilização se resume a:

Exemplo
{{ 'label-to-translate' | i18n }}

<label>{{ 'label-to-translate' | i18n }}</label>
<p>{{ 'label-to-translate' | i18n }}</p>

Caso não seja preciso realizar a tradução para a label, basta inseri-la normalmente no HTML e/ou não informar o filtro de internacionalização:

Exemplo
{{ 'Olá !!' }}

<label>Olá !!</label>
<p>Olá !!</p>

Quando necessário utilizar o filtro programaticamente, é recomendado que este seja linkado ao $rootScope do AngularJS para que seja acessível de qualquer ponto do aplicativo. Utilizando como base a implementação da aplicação de referencia, basta no index.js ao fazer o bootstrap da aplicação, após já ter realizado o registro do filtro de internacionalização, adicionar a referencia ao $rootScopt conforme exemplo:

Exemplo
app.run(['$rootScope', '$filter', function ($rootScope, $filter) {
    // Adiciona o filtro de i18n, caso exista, ao $rootScope para facilitar o acesso
    // ao mesmo programaticamente.
    if ($filter('i18n')) {
    	$rootScope.i18n = $filter('i18n');
	}
}]);

Tendo adicionado o link do filtro ao $rootScope atraves do alias 'i18n', basta injetar o $rootScope ao AngularJS Controller ou AngularJS Service e acessar a função da seguinte maneira:

Exemplo
sampleService.$inject = ['$rootScope'];
function sampleService($rootScope) {
	this.label = $rootScope.i18n('label-to-translate');
}

Definição

Cada produto é livre para definir a forma como irá gerenciar suas traduções. No entanto, o TOTVS | HTML Framework confia que o AngularJS Filter seja registrado com o alias de i18n e que receba como parâmetro a palavra ou código a ser traduzido.

Utilizando como base a implementação da aplicação de referencia temos um filtro de internacionalização definido no arquivo filter-i18n.js. Este filtro considera o arquivo de tradução por contexto de aplicação; no caso temos um arquivo de tradução para a aplicação centralizadora (html-app) e um para a aplicação convencional (html-sample). Ambas as aplicações seguem a mesma infraestrutura para que as traduções possam ser carregadas de acordo com a aplicação que está sendo acessada.

Neste model cada arquivo de tradução está disponível através da seguinte estrutura:

  • <contexto da aplicação>/<contexto da view>/i18n/translations.js

Usando o cadastro de clientes como exemplo teríamos o arquivo de tradução na seguinte estrutura:

  • /dts/crm/i18n/translations.js

Para o carregamento dinâmico das traduções foi desenvolvida uma função para carregar o arquivo de tradução de acordo com o contexto da aplicação e view. O carregamento do arquivo é realizado através do RequireJS e armazenado na sessão para evitar de recarregar o arquivo para cada solicitação de tradução.

No caso da aplicação de referencia o filtro foi concebido para inicialmente buscar a tradução no contexto que está sendo acessado. Caso não encontre recorre ao arquivo de tradução da aplicação centralizadora. Desta forma, podemos evitar de replicar traduções comuns como 'sim', 'atenção', 'não' entre outros.

É possível definir um contexto diferente do contexto atual ou da aplicação centralizadora. Veja mais abaixo.

Cada arquivo de tradução se resume a um arquivo JSON com o nome de translations.js, este por sua vez deve seguir a estrutura padrão de um arquivo do JSON no qual temos a seguinte formatação:

Exemplo
[{
    "sample" : {
        "pt":"Sample",
        "en":"Sample",
        "es":"Sample"
    },
    "label-to-translate" : {
        "pt":"Palavra ou sentença a ser internacionalizada !",
        "en":"Word or sentence to be internationalized !",
        "es":"Palabra o frase que se internacionalizaron !"
    }
}]

Por termos o produto normalmente traduzido para 3 idiomas (Português, Inglês e Espanhol) foi adotada a estrutura de que cada palavra ou sentença irá conter as 3 traduções para que seja possível alterar o idioma do sistema em runtime.

Na aplicação de referencia ao carregar as informações do usuário logado para a sessão é carregado também a preferência de idioma do usuário. Sendo assim, no filtro é realizado o tratamento para retornar preferencialmente a tradução correspondente ao idioma do usuário logado. Entretanto, caso o usuário não possua um idioma associado ao seu login, o filtro se responsabiliza por buscar o idioma utilizado no navegador do usuário. Caso seja diferente dos idiomas padrões do produto este então considera o idioma inglês para realização das traduções.

No caso de não encontrar uma tradução para a palavra ou sentença a retorna entre colchetes para que fique visível que está pendente de tradução.

Caso o filtro encontre a literal, mas não encontre a tradução requisitada, não será disparado nenhum erro, apenas será retornado o próprio nome da literal.

Literais com parâmetros

É possível passar parâmetros juntos com as literais para a internacionalização, para usar esse recurso inclua marcadores dentro da literal usando "{" e "}" junto com seu índice.
translation.js
[{
    "salutation" : {
        "pt":"Olá {0}, {1}",
        "en":"Hi {0}, {1}"
    }
}]

Para passar os parâmetros para o filtro, passe um array como segundo parâmetro.

Exemplo
{{ 'salutation' | i18n: ['José', 'Bom dia'] }}

<label>{{ 'salutation' | i18n: ['José', 'Bom dia'] }}</label>
<p>{{ 'salutation' | i18n: ['José', 'Bom dia'] }}</p>

Especificando um Contexto para tradução

Durante o desenvolvimento de alguns módulos foi levantada a necessidade de especificar o módulo que contenha a tradução correta ou contextualizada para a sentença a ser traduzida. Desta forma foi adicionado um parâmetro ao filtro de i18n que permite que seja informado de qual contexto a sentença deve buscar sua tradução. Exemplo:

Exemplo
{{ 'label-to-translate' | i18n: []: 'linha/meu-modulo' }}

<label>{{ 'label-to-translate' | i18n: []: 'linha/meu-modulo' }}</label>
<p>{{ 'label-to-translate' | i18n: []: 'linha/meu-modulo' }}</p>

Ao especificar o terceiro parâmetro como 'meu-modulo' o filtro de i18n vai desconsiderar o contexto atual e para essa sentença em especial vai buscar no arquivo de tradução do 'meu-modulo'.

  • Sem rótulos