Estou enviando um ... (marque um com "x")
[x] feature request
Comportamento atual
https://github.com/angular/angular/issues/9104#issuecomment -244909246
Eu não acho que seja possível, como eu disse antes só funciona com texto estático, não vai analisar texto no código js, apenas templates
Comportamento esperado/desejado
Ser capaz de traduzir strings usadas em qualquer lugar do código, usando uma API.
Qual é o comportamento esperado?
Estou referenciando o uso de $translate.instant
para expor casos de uso reais:
if (data._current_results === data._total) {
content = this.$translate.instant('CLIPPINGS__LIST__SUMMARY_ALL', {'num': data._current_results});
} else {
if (undefined === data._total) {
data._total = '...';
}
content = this.$translate.instant('CLIPPINGS__LIST__SUMMARY', {
'num': data._current_results,
'total': data._total
});
}
// Put 'mentions' first
data = angular.merge({}, {
mentions: mentions
}, data);
_.each(data, (value:number, key:string):void => {
if (value) {
details += value + ' ' + this.$translate.instant('CLIPPINGS__LIST__SUMMARY_TYPE_' + key) + ', ';
}
});
if (details) {
details = '(' + _.trim(details, ', ') + ')';
}
content = content.replace(':details', details);
Mais exemplos:
getExportImageName(hideExtension:boolean):string {
let fileName:string;
fileName = this.$translate.instant('D_CHART_FACET_authors__EXPORT_FILENAME', {
'profileName': this.ExportService.GetProfileName(),
'period': this.ExportService.GetPeriodString(this.SearchFilter.GetPeriodFromInterval())
});
if (!Boolean(hideExtension)) {
fileName += '.png';
}
return fileName;
}
private _getTitle():string {
if (this.inShareColumn) {
return this.$translate.instant('COMPARISONS__SHARE_COLUMN_share_of_voice_TITLE');
} else if (this.inTotalsColumn) {
return this.$translate.instant('COMPARISONS__TOTAL_COLUMN_share_of_voice_TITLE');
} else {
return _.get<string>(this.group, 'profileName', '');
}
}
this.chart = new Highcharts.Chart(<any>{
title: {
text: this.$translate.instant('REPORTS_BLOG_MAPPING_CHART_TITLE_tone').toUpperCase(),
},
xAxis: {
title: {
text: this.$translate.instant('REPORTS_BLOG_MAPPING_CHART_TITLE_tone_xaxis')
}
},
yAxis: {
min: 0,
title: {
text: this.$translate.instant('REPORTS_BLOG_MAPPING_CHART_TITLE_tone_yaxis')
}
},
plotOptions: {
scatter: {
tooltip: {
headerFormat: '<b>{point.key}</b><br>',
pointFormat: '{point.y} ' + this.$translate.instant('REPORTS_BLOG_MAPPING_CHART_mentions')
}
}
}
});
this.config = {
requiredList: true,
bannedList: false,
allowSpaces: false,
allowComma: false,
colorsType: false,
defaultEnterAction: 'required',
requiredTooltip: this.$translate.instant('D_CLIPPING_TAGS__REQUIRED_TOOLTIP'),
bannedTooltip: this.$translate.instant('D_CLIPPING_TAGS__BANNED_TOOLTIP')
};
SetWindowTitle(title:string) {
if (!!title) {
this.$window.document.title = this.$translate.instant(title);
}
}
dateHuman(date:Date):string {
return date.getDate() + ' ' + this.$translate.instant('GLOBAL_CALENDAR_MONTH_' + date.getMonth())
+ ' ' + date.getFullYear();
}
// Sort types
tmpTypes = _.sortBy(tmpTypes, (type:string):string => {
// 'MISC' at the end
if ('MISC' === type) {
return 'zzzzz';
}
return this.$translate.instant('FACET_phrases2__TYPE_' + type);
});
GetSortedLanguages():IFacetLangDetectedCommonServiceLanguageObject[] {
// We have to sort by translated languages!
return _.sortBy(_.map(this.facetOptions, (item:string):any => {
return {
key: item,
label: this.$translate.instant('FACET_langDetected_' + item),
cssStyle: (_.includes(['english', 'catalan', 'spanish', 'french', 'italian'], item))
? {'font-weight': 'bold'} : null,
flag: _.get(this.lutFlags, item, null)
};
}), (item):string => {
return item.label.toLowerCase();
});
}
getDataExportStacked(inputData:any):any {
let exportData = angular.copy(inputData);
if (angular.isArray(exportData) && exportData.length) {
exportData[0].name = this.$translate.instant('CLIPPINGS__CHARTS_volume_TITLE');
exportData[0].data = _.map(exportData[0].data, (inputDataItem:any):any => {
return {
'label': inputDataItem.association.profileName,
'value': inputDataItem.value
};
});
}
return exportData;
}
UpdateCalendarStrings():void {
Highcharts.setOptions({
lang: {
months: [
this.$translate.instant('GLOBAL_CALENDAR_MONTH_January'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_February'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_March'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_April'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_May'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_June'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_July'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_August'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_September'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_October'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_November'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_December')
],
shortMonths: [
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Jan'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Feb'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Mar'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Apr'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_May'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Jun'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Jul'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Aug'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Sep'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Oct'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Nov'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Dec')
],
weekdays: [
this.$translate.instant('GLOBAL_CALENDAR_DAY_Sunday'),
this.$translate.instant('GLOBAL_CALENDAR_DAY_Monday'),
this.$translate.instant('GLOBAL_CALENDAR_DAY_Tuesday'),
this.$translate.instant('GLOBAL_CALENDAR_DAY_Wednesday'),
this.$translate.instant('GLOBAL_CALENDAR_DAY_Thursday'),
this.$translate.instant('GLOBAL_CALENDAR_DAY_Friday'),
this.$translate.instant('GLOBAL_CALENDAR_DAY_Saturday')
]
}
});
}
Qual é a motivação/caso de uso para mudar o comportamento?
Ser capaz de traduzir strings fora dos templates.
Por favor, conte-nos sobre o seu ambiente:
@vicb
Eu acho que isso é um verdadeiro showtopper, i18n não está pronto para uso até que isso seja implementado.
Por exemplo, não consigo definir mensagens de validação traduzidas no código
@ Mattes83 Você tentou dessa maneira?
<p [hidden]="!alertManagerRowForm.controls.sendTo.hasError('validateEmail')" class="help-error">
{{ 'ALERTMANAGER__FORM__FIELD__sendTo__ERROR__validateEmail' | translate }}
</p>
:confused: A documentação diz como é bom ter mensagens de erro no código e o suporte à tradução requer qualquer coisa no template. Parece que há mais necessidade de comunicação.
@marcalj Eu sei dessa maneira... mas preciso ter strings localizadas nos meus arquivos ts.
@manklu concordo plenamente
Eu acho que isso é um verdadeiro showtopper, i18n não está pronto para uso até que isso seja implementado.
Por exemplo, não consigo definir mensagens de validação traduzidas no código
Sim, o mesmo aqui, acabei de mudar de ng2-translate para Angular2 i18n, pois prefiro usar módulos OOTB e é muito mais fácil extrair traduções (ng2-translate é mais demorado IMO)
Nesta fase, não consigo traduzir as mensagens de erro levantadas pelos meus serviços. Nenhuma solução alternativa também.
Se alguém quiser iniciar uma especificação de design, seria útil (ou seja, no Google Docs).
Precisaria listar todos os casos. Pensando rapidamente sobre isso, vejo a necessidade de
_.('static text');
_.('with {{ parameter }}', {parameter: "parameter" });
_.plural(count, {'few': '...'});
_.select(on, {'value': '...'});
Olá pessoal, ótima solicitação de recurso :+1:
Existe alguma solução sugerida para traduzir textos *.ts?
@fbobbio O que tenho feito é criar elementos ocultos no template, ex.
<span class="translation" #trans-foo i18n>foo</span>
.
Vincule-os usando:
@ViewChild('trans-foo) transFoo : ElementRef;
.
Em seguida, recupere o valor traduzido
transFoo.nativeElement.textContent
.
Parece retardado, mas funciona para as minhas necessidades.
Como o ng-xi18n já processa todo o código TS, por que não implementar um decorador como @i18n()
para (string-)properties? Estes podem então ser preenchidos com o valor traduzido, como @Input()
é usado com vinculação de dados unidirecional.
Se o valor não traduzido não puder ser facilmente extraído do código, basta colocá-lo no argumento da seguinte forma:
@i18n( {
source : 'Untranslated value',
description: 'Some details for the translator'
} )
public set translatedProperty( value : string ) {
this._translatedProperty = value;
}
e alimente a origem na propriedade quando não houver destino de tradução.
Este é um item essencial em todo o ciclo de internacionalização, IMO.
Na minha loja, estamos acostumados a uma ferramenta "ng-xi18n - like" (uma extensão para xgettext) que rastreia todos os tipos de arquivos de origem procurando por texto marcado para colocar em arquivos de dicionário para os tradutores.
Adoro a marcação i18n limpa e fácil nos modelos HTML e esperava o mesmo para o código Typescript.
@vicb Além de seus casos de uso, estou pensando na possibilidade de oferecer suporte à localização de string interpolada no código TS. No entanto, é provável que seja necessário reescrever o código TS para dar suporte a esse cenário. Será uma abordagem válida?
Esse é o principal recurso que nos impede de usar a abordagem pronta para uso para a tradução que o Angular 2 oferece. Temos muitos componentes orientados a metadados cujas chaves vêm de alguns metadados não armazenados em HTML. Se pudéssemos traduzir via pipe ou programaticamente em relação às TRANSLATIONS disponíveis, poderíamos fazer com que esses componentes mostrassem as strings apropriadas.
Enquanto isso, estamos limitados a algo como ng-translate por causa dessa limitação.
A maneira como resolvi esse problema foi adicionando um objeto 'lang' vazio em um serviço usado em todo o meu aplicativo. Em seguida, aplico uma diretiva que lê todo o intervalo em uma div e armazeno o valor nesse objeto. Coloco toda a minha string em um modelo na parte inferior da página com uma propriedade oculta. A string é então acessível a partir do modelo ou do componente. É feio e você pode facilmente substituir uma entrada com o mesmo id. Mas é melhor que nada.
SERVIÇO
@Injectable()
export class AppService {
//Language string object.
private _lang:Object = new Object();
get lang():Object {
return this._lang;
}
}
DIRETORIA
@Directive({
selector: '[lang]'
})
export class LangDirective implements OnInit {
constructor(
public element: ElementRef,
public app: AppService) {
}
ngOnInit() {
let ele = this.element.nativeElement;
for (var i = 0; i < ele.children.length; i++) {
let id = ele.children[i].getAttribute('id');
let value = ele.children[i].innerHTML;
this.app.lang[id]=value;
}
}
}
MODELO
<button>{{app.lang.myButtonText}}</button>
<div lang hidden >
<span id="myButtonText" i18n="Test Button">Testing</span>
</div>
Olá @lvlbmeunier
Obrigado por fornecer esta sugestão para uma solução alternativa enquanto aguardamos a implementação oficial. Tentei implementar sua solução, mas não consigo fazer com que as chaves de tradução dinâmicas sejam reconhecidas. Eu estava tentando fazer assim:
<p *ngFor="let d of dataEntry">{{app.lang[d.name]}}</p>
<div lang hidden >
<span id="{{d.name}}" *ngFor="let d of dataEntry" i18n>{{d.name}}</span>
</div>
Essas novas chaves não aparecem nos meus arquivos xliff. É possível conseguir isso com sua solução?
Eu nunca tentei, mas tenho quase certeza de que a compilação do arquivo xliff não executa código. Ter valor dinâmico em i18n seria contrário ao conceito. Se você souber com certeza todos os nomes que estariam em sua lista, todos eles devem ser declarados independentemente e não em um loop for.
Adicionar as chaves manualmente funciona, mas é impraticável. No meu caso, recebo centenas de chaves de texto que precisam de tradução de uma API.
Você pode executar seu código e pegar a fonte e copiá-la para um arquivo. A geração do arquivo x18n é baseada em arquivo estático.
Com 4.0.0-beta
você pode atribuir um id a i18n
, por exemplo mainTitle:
<span i18n="title@@mainTitle">
Com isso podemos, pelo menos para o compilador JIT, criar um Component fictício (não precisa ser adicionado ao html do aplicativo, apenas o módulo do aplicativo) com todas as nossas traduções "extras".
Para começar, adicionaremos os provedores não apenas ao compilador, mas também ao módulo do aplicativo:
// bootstrap.ts
getTranslationProviders().then(providers => {
const options = { providers };
// here we pass "options.providers" to "platformBrowserDynamic" as extra providers.
// otherwise when we inject the token TRANSLATIONS it will be empty. The second argument of
// "bootstrapModule" will assign the providers to the compiler and not our AppModule
platformBrowserDynamic(<Provider[]>options.providers).bootstrapModule(AppModule, options);
});
Então vamos criar um componente fictício para abrigar nossas traduções extras, não se esqueça de adicionar o componente a declarations
de AppModule
. Isso é para que ng-xi18n
possa encontrar o html (eu acho) e adicioná-lo ao arquivo de tradução.
//tmpI18N.ts
import {Component} from '@angular/core';
@Component({
selector: 'tmpI18NComponent',
moduleId: module.id,
templateUrl: 'tmp.i18n.html'
})
export class TmpI18NComponent {
}
Adicione nossas traduções a tmp.i18n.html
:
<!-- tmp.i18n.html -->
<span i18n="test@@mainTitle">
test {{something}}
</span>
Agora podemos criar um serviço onde podemos buscar nossas traduções:
import {Injectable, Inject, TRANSLATIONS} from '@angular/core';
import {I18NHtmlParser, HtmlParser, Xliff} from '@angular/compiler';
@Injectable()
export class I18NService {
private _source: string;
private _translations: {[name: string]: any};
constructor(
@Inject(TRANSLATIONS) source: string
) {
let xliff = new Xliff();
this._source = source;
this._translations = xliff.load(this._source, '');
}
get(key: string, interpolation: any[] = []) {
let parser = new I18NHtmlParser(new HtmlParser(), this._source);
let placeholders = this._getPlaceholders(this._translations[key]);
let parseTree = parser.parse(`<div i18n="@@${key}">content ${this._wrapPlaceholders(placeholders).join(' ')}</div>`, 'someI18NUrl');
return this._interpolate(parseTree.rootNodes[0]['children'][0].value, this._interpolationWithName(placeholders, interpolation));
}
private _getPlaceholders(nodes: any[]): string[] {
return nodes
.filter((node) => node.hasOwnProperty('name'))
.map((node) => `${node.name}`);
}
private _wrapPlaceholders(placeholders: string[]): string[] {
return placeholders
.map((node) => `{{${node}}}`);
}
private _interpolationWithName(placeholders: string[], interpolation: any[]): {[name: string]: any} {
let asObj = {};
placeholders.forEach((name, index) => {
asObj[name] = interpolation[index];
});
return asObj;
}
private _interpolate(pattern: string, interpolation: {[name: string]: any}) {
let compiled = '';
compiled += pattern.replace(/{{(\w+)}}/g, function (match, key) {
if (interpolation[key] && typeof interpolation[key] === 'string') {
match = match.replace(`{{${key}}}`, interpolation[key]);
}
return match;
});
return compiled;
}
}
Agora podemos fazer algo como:
export class AppComponent {
constructor(i18nService: I18NService) {
// Here we pass value that should be interpolated in our tmp template as a array and
// not an object. This is due to the fact that interpolation in the translation files (xlf for instance)
// are not named. They will have names such as `<x id="INTERPOLATION"/>
// <x id="INTERPOLATION_1"/>`. And so on.
console.log(i18nService.get('mainTitle', ['magic']));
}
}
Esta é uma solução hacky. Mas pelo menos podemos alavancar o arquivo de tradução, obter por chave, interpolar e não precisar ter um html oculto em nossa aplicação.
NOTA: o atual pacote NPM @angular/compiler-cli
do 4.0.0-beta tem uma versão de dependência incorreta de @angular/tsc-wrapped
. Aponta para 0.4.2 deve ser 0.5.0. @vicb isso é facilmente corrigido? Ou devemos esperar pelo próximo lançamento?
@fredrikredflag Incrível! E o AOT?
@ghidoz AOT é outra história. O que gostaríamos de fazer é pré-compilar todas as traduções para que possamos obtê-las por chave. Mas como o ngc
substituirá todos os i18n
pela tradução correta, não podemos aproveitá-lo. Não é possível encontrar nenhuma opção/propriedade exposta que contenha as traduções analisadas de ngc
. Poderíamos usar a mesma abordagem dinâmica do JIT, buscando o arquivo xlt dessa forma ainda fornecendo-o no token TRANSLATION
. No entanto, isso vai contra o propósito da AOT.
NÃO FAÇA ISSO PARA NENHUM APP DE PRODUÇÃO .
/// bootstrap.aot.ts
function fetchLocale() {
const locale = 'sv';
const noProviders: Object[] = [];
const translationFile = `./assets/locale/messages.${locale}.xlf`;
return window['fetch'](translationFile)
.then(resp => resp.text())
.then( (translations: string ) => [
{ provide: TRANSLATIONS, useValue: translations },
{ provide: TRANSLATIONS_FORMAT, useValue: 'xlf' },
{ provide: LOCALE_ID, useValue: locale }
])
.catch(() => noProviders);
}
fetchLocale().then(providers => {
const options = { providers };
platformBrowser(<Provider[]>options.providers).bootstrapModuleFactory(AppModuleNgFactory);
});
Pensamento atual sobre como implementar isso:
@Component()
class MyComp {
// description, meaning and id are constants
monday = __('Monday', {description?, meaning?, id?});
}
__(...)
em modelos em algum momento posterior,/cc @ocombe
Suponho que __()
é para um método que ainda não tem nome (e o método não seria realmente __
, certo?)
É uma boa ideia para traduções estáticas que você pode usar em suas classes e bastante simples de implementar, eu acho.
Não __()
é o nome, você não gosta :)
É comumente usado em estruturas de tradução - mas você poderá import {__ as olivier} from '@angular/core'
se preferir outro nome!
eeeeeh não é muito auto explicativo :D
Parece uma função muito privada
Também não gosto do nome do método ___ :) Imaginava que seria um serviço?
De qualquer forma, é bom ver o progresso 👍
Eu gosto __()! :D Muito gettext-y e é curto.
No mundo JS, só tenho experiência com @ocombes ng2-translate, onde marcar todo o texto com this._translateService.instant() torna o código um pouco mais difícil de ler em comparação com uma alternativa mais curta, como proposta aqui.
nada impede você de renomear o serviço de tradução ng2 __
você sabe :)
Na verdade, não tenho ideia de como envolver um método de serviço DI em uma função simples - de qualquer maneira, não importa, isso está além do escopo deste problema :-) Meu comentário foi apenas um +1 para usar __ como é bem conhecido se você ' Já usei outros frameworks de tradução, pelo menos no mundo PHP.
ok, talvez ___ seja bom, melhor que "this.translationService.getTranslation()", muito mais curto.
E sim, você pode renomeá-lo se quiser.
Que tal i18n(...)
em vez de __(...)
?
Por favor, pare o debate sobre o nome, esse não é o ponto. Obrigado.
@vicb com monday = __('Monday', {description: 'First day of the week', id: 'firstDatOfWeek'});
será possível resolvê-lo por id, ou seja:
__('@<strong i="8">@firstDatOfWeek</strong>') // Monday
Além disso, Monday
seria local para a classe definida ou seria possível resolver de qualquer lugar? Estou pensando em traduções comuns como "fechar", "abrir" etc.
Eu queria saber qual é a melhor solução atualmente que vocês recomendam usar com AOT até que o lançamento oficial o suporte?
Cumprimentos,
Sean
Pia de cozinha angular 2: http://ng2.javascriptninja.io
e source@ https://github.com/born2net/Angular-kitchen-sink
@vicb alguma novidade, por lá ^
Até que esse recurso seja implementado, estou usando o recurso de tradução de atributos .
import {Component, Input, OnInit} from '@angular/core';
@Component({
selector: 'app-sandbox',
templateUrl: 'sandbox.html'
})
export class SandboxComponent implements OnInit {
@Input()
public title: string;
constructor() {
}
ngOnInit() {
console.log('Translated title ', this.title);
}
}
Do modelo de componente pai:
<app-sandbox i18n-title title="Sandbox"></app-sandbox>
É uma solução alternativa, mas ainda assim, acho que é a mais limpa até agora. Dá-lhe acesso ao title
traduzido dentro de ts
.
Estou começando a trabalhar neste recurso, espere um documento de design em breve :-)
este será o recurso mais esperado
Isso é uma boa notícia. Obrigado @ocombe .
O documento de design está disponível aqui: https://goo.gl/jQ6tQf
Qualquer feedback é apreciado, obrigado.
querida, estarei lendo o mais rápido possível!
Obrigado @ocombe
Eu li o documento. Belo resumo.
Ser capaz de extrair strings de arquivos ts parece incrível.
Não tenho certeza de quando a atualização do Typescript estará disponível para Angular4.
Isso significa que esse recurso que já deve estar disponível há meses, porque praticamente todo mundo se deparou com essa limitação não poderá usar essa solução antes de pelo menos 3/6 meses.
Eu posso não ser o único agora que usa ngx-translate para gerenciar traduções em meus controladores enquanto confio em angular i18n para os modelos.
O objetivo de mesclar tudo no i18n é obviamente ótimo.
Mas, além da simplificação em termos de compreensão de como implementar o i18n na estrutura angular, essa abordagem realmente aumentará o desempenho em comparação com a implementação atual do ngx-translate?
Pelo que entendi agora, o único bônus seria poder extrair strings dos controladores.
Além disso, uma grande limitação agora é a pluralização, por favor, certifique-se de que está funcionando corretamente quando você liberar toda a atualização. Eu li muitos tickets relacionados ao i18n em que xliff e xmb não lidariam com isso corretamente. Este é mais um caso em que preciso voltar ao ngx-translate para fornecer uma solução funcional.
@ocombe Obrigado pelo documento de design detalhado, parece uma solução muito boa para esta solicitação de recurso. O design atual aborda os casos de uso que estou tentando resolver.
Uma pergunta: O projeto fala de um serviço I18N para modo JIT, e um Transformador TS 2.2.x para modo AOT. Estou correto ao assumir que o transformador substituirá a chamada ao método de serviço por uma tradução estática e também removerá todas as referências restantes ao serviço I18N?
@Thommas Angular 4 usará o TypeScript 2.1 (o que significa que você terá que atualizar), mas você já pode usar qualquer versão mais recente do TypeScript (2.2.1, por exemplo) com o Angular 2 ou 4.
Em termos de ganho de desempenho em relação ao ngx-translate, depende se você usa AOT ou não. Se você usar AOT, é um ganho, mas provavelmente não verá a diferença. No JIT (sem AOT) não haverá nenhum ganho (na verdade depende se você usar o get
observável ou o método síncrono instant
, o observável custa mais do que uma simples chamada de função).
Estou falando de i18n em seu código aqui. Se estamos falando sobre os templates, então há um ganho real visível se você estiver usando o Angular i18n (em AOT e JIT) porque ele não usa ligações. Quanto mais traduções você usa, mais você ganha.
Vou garantir que a pluralização funcione exatamente da mesma forma que para os modelos. Existe algum problema agora com ele nos modelos?
@schmuli a única vez que o Angular pode substituir seu código é quando você usa o AOT. Caso contrário, as chamadas de serviço permanecerão as mesmas em seu código.
Mas se você usar AOT, a chamada de serviço será substituída por uma tradução estática (somente as variáveis que você usar permanecerão dinâmicas). Não tenho certeza se vamos remover as referências ao serviço I18n, porque ele pode ser usado para outras coisas no futuro, terei que ver o que é possível com o transformador assim que começar a escrever o código. Você está pensando em um caso de uso em que isso seria um problema?
@ocombe Não consigo pensar em um caso de uso em que deixar o código seria um problema, a menos que consideremos uma injeção extra de DI que não será usada (isso é um problema real?).
Considerando o que você escreveu que o serviço pode ser usado para outras coisas no futuro e o potencial de erros introduzidos pela alteração do código do usuário, eu diria que provavelmente é melhor evitar a remoção total do código.
Talvez seja útil usar o serviço para obter a localidade atual no AOT. Considere, por exemplo, o caso em que você tem um servidor que pode retornar texto em vários idiomas, portanto, você precisará incluir a localidade atual na solicitação. No entanto, você sempre pode usar uma string traduzida fictícia como uma solução alternativa.
@diego0020 você já pode obter a localidade, basta injetar LOCALE_ID
do núcleo
@ocombe Pluralization não é implementado com xliff e ninguém fora do google tem alguma idéia de como usá-lo com xmb. Veja também: https://github.com/angular/angular/issues/13780
De qualquer forma, nada está bloqueando nossa implementação i18n agora ngx-translate com um canal de pluralização fará por enquanto. Espero que tudo fique melhor no NG4 e a documentação reflita as melhorias. Obrigado.
@Thommas ICU com xliff será corrigido em breve: https://github.com/angular/angular/pull/15068 e se quiser saber como usar, está nos documentos: https://angular.io/docs/ ts/latest/cookbook/i18n.html#! #cardinalidade
Por favor, desculpe, existe algum ETA? Porque eu ouvi que estará disponível na versão ng4.0.0, mas não! Obrigado
Cc @ocombe
Ainda estamos trabalhando no design, há muitas coisas inesperadas a serem levadas em consideração (como como as bibliotecas podem enviar suas próprias traduções), ...
Espere isso para 4.2, mas não é garantido.
ok obrigado @ocombe , tenho duas perguntas por favor:
<span i18n>This is {{myValue}}</span>
Could not mark an element as translatable inside a translatable section
@istiti
<div i18n><span i18n>my text</span></div>
- isso não é bom<div><span i18n>my text</span></div>
- isso é bom@royiHalp
Obrigado
@istiti
<span i18n>This is {{myValue}}</span>
<source>This is <x id="INTERPOLATION"/></source>
<x id="INTERPOLATION"/>
no lugar correto na frase, para ajudar os outros a entender seu significado, você pode adicionar uma descrição à diretiva i18n assim:Could not mark an element as translatable inside a translatable section
é como eu expliquei, lembro que se eu ler o erro com atenção posso perceber em qual arquivo estou com o problema.@fredrikredflag Muito obrigado!
Seu código é super útil! Eu só tive que corrigir um problema porque parece que xliff.load
retorna um objeto diferente hoje em dia, então this._translations
precisa ser ajustado para:
const loaded = xliff.load(this._source, '');
this._translations = loaded['i18nNodesByMsgId'] ? loaded['i18nNodesByMsgId'] : {};
e uma validação menor no método get
se pedirmos uma chave inexistente:
const placeholders = this._getPlaceholders(this._translations[key] ? this._translations[key] : []);
Além disso, acho que o componente i18n vazio foi abalado em árvore ou algo assim, então tive que incluir as strings nos modelos de componentes correspondentes com:
<span hidden i18n="@@MY_STRING_1">String 1</span>
<span hidden i18n="@@MY_STRING_2">String 2</span>
Por sorte, eu só preciso de uma pequena quantidade de strings para o meu miniApp, então ele funciona muito bem em produção com AoT.
Obrigado novamente!!!
P/S: a ferramenta xliffmerge de Martin Roob é de uso obrigatório no momento, e seu TinyTranslator também B-)
Eu uso a compilação AoT e meu projeto suporta dois idiomas: inglês e russo. Encontrei uma solução temporária para o problema usando a configuração do ambiente.
O arquivo environments/environment.ts
contém:
import { messagesEn } from '../messages/messages-en';
export const environment = {
production: false
};
export const messages = messagesEn;
Também existem outros dois arquivos environment.prod-en.ts
e environment.prod-ru.ts
com o próximo conteúdo:
import { messagesEn } from '../messages/messages-en';
export const environment = {
production: true
};
export const messages = messagesEn;
E para russo:
import { messagesRu } from '../messages/messages-ru';
export const environment = {
production: true
};
export const messages = messagesRu;
Cada arquivo de mensagem pode conter algo assim:
export const messages = {
MessageKey: 'Translation',
AnotherMessageKey: 'Translation',
Group: {
MessageKey: 'Translation',
AnotherMessageKey: 'Translation',
}
};
No meu código (componentes, serviços, etc) eu apenas importo mensagens:
import { messages } from '../../environments/environment';
E use-os:
alert(messages.MessageKey);
Em .angular-cli.json
eu especifiquei os próximos ambientes para produção:
"environments": {
"dev": "environments/environment.ts",
"prod-en": "environments/environment.prod-en.ts",
"prod-ru": "environments/environment.prod-ru.ts"
}
Funciona!
@alex-chuev Você já tentou isso com JIT?
@ocombe alguma estimativa aproximada de quando isso estaria disponível?
Ótimo recurso btw :)
Está em espera até que sejam feitas alterações no compilador, então não para 4.2, ainda espero fazer isso para 4.3
alguém sabe como implementar i18n em valores de param por exemplo em [title] no exemplo a seguir:
então, em outras palavras, adicione tradução à palavra HELLO
Saudações
Sean
Se HELLO for apenas uma string que você digita no modelo HTML, você pode fazer o seguinte:
```html
````
A documentação tem um exemplo disso. Veja aqui: https://angular.io/docs/ts/latest/cookbook/i18n.html#! #translate-attributes
Se você precisar vincular a uma propriedade de string no componente, precisará aguardar esse recurso ou implementar uma maneira personalizada de tradução (que eu saiba).
@ocombe
Ainda estamos trabalhando no design, há muitas coisas inesperadas a serem levadas em consideração (como como as bibliotecas podem enviar suas próprias traduções), ...
Isso é muito importante. Espero que faça parte desse recurso também. Porque no momento não vejo como a biblioteca de terceiros pode fornecer traduções para seu aplicativo. Durante a compilação, você pode especificar apenas 1 arquivo XLIFF, e parece que você precisa pré-compilar sua biblioteca para que seu idioma tenha a capacidade de traduzi-la.
Sim, estou esperando por isso também! Isso é MUITO importante para projetos destinados a públicos que não falam inglês!
É definitivamente algo que queremos apoiar, a equipe está trabalhando na refatoração do compilador que nos permitirá fazer isso :-)
Existe uma estimativa para qual versão será direcionada? Eu li em algum lugar que pode ser em torno de 4,3?
Por causa da refatoração (e mudanças de quebra) necessárias, não será antes da v5, temo
Uau 😳 Oh não, estou esperando esse recurso para 4.2 que você disse e agora é para v5 ☹️ Eu estava pensando que a v5 será dinâmica mudando de idioma não liberando cada versão mas de qualquer forma espero que seja um dia mesmo com 36k build diferente para cada Língua. Eu só quero saber para quando é v5? Obrigado
@ocombe
@istiti eu disse que não era uma data garantida ;-)
O cronograma de lançamento está aqui: https://github.com/angular/angular/blob/master/docs/RELEASE_SCHEDULE.md
A versão final da v5 é 2017-09-18, mas haverá betas e RCs antes
Há alguma alteração para criar um arquivo de localidade para cada componente? significa, criar pedaços de messages.xlf
, por exemplo: messages.{component}.{locale}.xlf
e por exemplo apenas messages.{component}.xlf
para o idioma padrão.
Ainda não
Danmage é estrito minimu devido ao tempo de construção @ocombe
Estou confuso... Este pedido de alteração/alteração é oficial ou não?
Tendo o mesmo problema aqui, as traduções simplesmente não se aplicam apenas aos modelos.
Tendo redux, componentes de visualização em árvore personalizados etc... todos gerados a partir de objetos javascript IN CODE, não por template
É oficial e está chegando, mas tivemos que fazer outras mudanças profundas no compilador primeiro, e é por isso que ele não estava pronto para o 4.3
Sabe-se em qual versão exata esse recurso estará disponível / está planejado? 4.3.1, 4.3.2 ... 4.3.X ?
Não há mais versão principal/secundária para o branch 4.x (somente patches: https://github.com/angular/angular/blob/master/docs/RELEASE_SCHEDULE.md) o que significa que isso será para 5.x , não tenho certeza de qual.
Isso ainda é esperado para entrar em 5.x? Não consigo ver nos betas. Obrigado
Pode estar em v50.x não em v5.x 😂
5.x sim, mas provavelmente não será em 5.0
Le jeu. 3 de outubro de 2017 às 12:56, vltr [email protected] um écrit :
Pode estar em v50.x não em v5.x 😂
—
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/angular/angular/issues/11405#issuecomment-319936876 ,
ou silenciar o thread
https://github.com/notifications/unsubscribe-auth/AAQMorXMbyI8l6K3QA4jmXEKawiEC46xks5sUad0gaJpZM4J2pkr
.
Oi @ocombe Estou muito interessado no processo para fazer isso funcionar e a maneira como o compilador funciona atualmente torna isso uma tarefa mais difícil. Você tem alguma clareza sobre a aparência da linha do tempo ou isso ainda não é 5.0, mas sim 5.x?
@arackow provavelmente estará em 5.x, @vicb está trabalhando nas últimas mudanças no compilador que finalmente tornarão isso possível
@ocombe ... existe algum documento de design que descreva um conceito da solução para strings fora dos modelos? Estamos em uma fase de desenvolvimento do projeto onde seria ótimo conhecê-lo, para que pudéssemos preparar de alguma forma nossa solução temporária e depois seria muito mais fácil mudar para a sintaxe final do Angular.
Tínhamos um documento de design, mas era baseado na versão anterior do compilador e provavelmente não é a implementação que acabaremos fazendo. Faremos um novo documento de design público assim que tivermos uma ideia melhor sobre a nova implementação
@ocombe eu tenho que marcar com +1 esse recurso. necessidade séria disso agora lol :+1: Obrigado a vocês por fazerem ferramentas incríveis! :)
Pelo que entendi do documento de design atual, um autor de uma biblioteca AOT precisaria fornecer as traduções para todos os idiomas exigidos pelos vários aplicativos que estão usando essa biblioteca.
Será que entendi isso corretamente?
Este é um bom ponto @gms1.
Eu testei isso aqui .
Como autor de biblioteca, você só precisa adicionar as tags i18n.
Você não deve compilar sua biblioteca para " ngfactories " (veja a palestra de Jason Aden em ng-conf 2017), então a tag de tradução não será substituída. Desta forma, quando você executar o comando ng xi18n
, você também obterá uma tradução no xliff para os arquivos em sua pasta node_modules.
Portanto, não, você não precisa fornecer traduções, mas adicionar tags i18n com significados úteis.
citado do documento de design:
Para AOT, o código-fonte é transformado para substituir as chamadas de serviço por traduções estáticas. Para fazer isso, usaremos um transformador TypeScript.
Então, o que isso significaria se uma biblioteca angular (AOT) fosse publicada geralmente na forma transpilada? Não encontrei nenhuma referência a .metadata.json neste documento
Você não deve compilar sua biblioteca para o código final, mas prepará-la para ser compilada pelo desenvolvedor usando seu código. Veja o que @jasonaden menciona aqui . Isso também significa que você pode tornar sua biblioteca traduzível adicionando a tag i18n.
@gms1 como eu disse:
Tínhamos um documento de design, mas era baseado na versão anterior do compilador e provavelmente não é a implementação que acabaremos fazendo.
E o compilador AOT está sendo alterado extensivamente para a v5, deve ser mais fácil para as libs publicarem código "aot-ready".
Para i18n, queremos tornar isso o mais fácil/flexível possível, provavelmente será algo como: bibliotecas podem publicar arquivos de tradução que você pode usar, mas que você também pode substituir se preferir, e você deve poder fornecer idiomas adicionais também se a biblioteca não suportar por padrão
Obrigado @ocombe por este esclarecimento!
@ocombe Isso significa que os recursos do ngx-translate estarão disponíveis no próprio angular?
@ montreal91 nenhuma das partes do ngx-translate pode ser implementada como está em angular, minha lib tem uma abordagem muito ingênua, funciona "principalmente", mas queremos ser muito mais eficientes com o framework.
Dito isto, o angular fornecerá recursos semelhantes (mesmo que a implementação final seja diferente).
Esta é a minha abordagem (FLUX) enquanto estou trabalhando em um sistema de notificação de interface do usuário baseado em (https://github.com/PointInside/ng2-toastr). O problema é que o conteúdo da notificação é definido na chamada de serviço ao invés de um template a ser gerenciado pelo sistema angular i18n (xi18n)
Não é o que eu gostaria, mas é uma solução _funcionando_. Você pode _extrair_ a ideia dos seguintes fragmentos de código. Espero que ajude :)
qualquer lugar
// this call in any other component, service...
// "info" method parameter is the "id" of the HTML element in template NotificationComponent.html
this.notificationActionCreator.success("myMessage");
NotificationComponent.ts
@Component({
selector: 'notification-cmp',
templateUrl: '../../public/html/NotificationComponent.html'
})
export class NotificationComponent implements OnInit, OnDestroy, AfterViewInit {
notificationMap: Map<string, any> = new Map();
subscription: Subscription;
constructor(private toastr: ToastsManager,
private vcr: ViewContainerRef,
private store: NotificationStore,
private elementRef: ElementRef) {
this.toastr.setRootViewContainerRef(vcr);
}
ngOnInit() {
this.subscription = this.store.payload
.subscribe((payload: NotificationStorePayload) => this.handleStorePayload(payload));
}
ngOnDestroy(): void {
this.store.destroy();
if (null != this.subscription) {
this.subscription.unsubscribe();
}
}
ngAfterViewInit(): void {
this.elementRef.nativeElement.querySelectorAll("div[notification-title][notification-text]")
.forEach(el => this.notificationMap.set(el.id, {
title: el.attributes["notification-title"].value,
text: el.attributes["notification-text"].value,
})
);
}
handleStorePayload(payload: NotificationStorePayload): void {
if (null != payload.action) {
let notification = this.notificationMap.get(payload.notification.id);
switch (payload.notification.type) {
case NotificationType.SUCCESS:
this.toastr.success(notification.text, notification.title);
break;
case NotificationType.INFO:
this.toastr.info(notification.text, notification.title);
break;
case NotificationType.WARNING:
this.toastr.warning(notification.text, notification.title);
break;
case NotificationType.ERROR:
this.toastr.error(notification.text, notification.title);
break;
}
}
}
}
NotificationComponent.html
<div hidden
id="myMessage"
i18n-notification-title="@@notificationTitleMyMessage"
i18n-notification-text="@@notificationTextMyMessage"
notification-title="Greeting"
notification-text="Hello world"></div>
<div hidden
id="error"
i18n-notification-title="@@notificationTitleError"
i18n-notification-text="@@notificationTextError"
notification-title="Error"
notification-text="Something went wrong!"></div>
Agora que o Angular 5 foi lançado, temos algum retorno sobre quando as mudanças no módulo i18n serão integradas?
Parece que esse recurso depende de alterações no compilador angular, mas as equipes responsáveis pelo compilador parecem menos interessadas. Não parece que há uma tarefa ou um PR ou commits:- (. Desculpe por desabafar, mas esta solicitação de recurso que descreve uma funcionalidade muito básica presente em todos os outros frameworks de tradução agora tem mais de um ano. Eu dei espero que esse recurso essencial chegue. Pelo menos para 5.x...
Pessoal fiquem tranquilos. Não é uma coisa boba implementar em um compilador AOT. Tenha um pouco de confiança, @ocombe disse:
"provavelmente será em 5.x, @vicb está trabalhando nas últimas alterações no compilador que finalmente tornarão isso possível"
Sim, estamos trabalhando no tempo de execução i18n agora, que é o primeiro passo.
Runtime i18n significa: um pacote para todos os idiomas, bibliotecas compiladas AOT podem usar i18n e talvez mais tarde a capacidade de alterar o idioma em tempo de execução. Isso também significa que podemos fazer traduções em tempo de execução, o que é necessário para traduções dentro do código (porque precisamos de um analisador de tempo de execução para traduções, etc...).
Feito isso, a próxima prioridade serão as traduções dentro do código.
Mas não podíamos fazer o runtime i18n antes de mudarmos o compilador para usar transformadores typescript (o que foi feito para 5.0)
Alguma idéia de qual versão 5.x terá quais melhorias i18n? Alguma coisa sendo lançada com o próprio 5.0.0?
5.0:
5.1 ou 5.2 (se não houver bloqueador inesperado):
5.x:
E outras coisas que adicionaremos ao longo do caminho, mas ainda não decididas (você pode seguir https://github.com/angular/angular/issues/16477).
Apenas pensamentos curiosos, embora eu esteja um pouco atrasado, apenas considerando o suporte a i18n em um arquivo TS, por que não pensamos na sintaxe da anotação? (Achei que alguém mencionou isso acima também)
Exemplo seria:
@i18n (id='mensagem1')
message1 = "Esta é uma mensagem que precisa ser traduzida";
@i18n (id='dynamicMessage')
dynamicMessage = "Esta é uma mensagem dinâmica com {0}";
Com a anotação para dynamicMessage, podemos injetar uma função através de anotação para esta instância de string, cujo nome é format , então podemos usar como abaixo:
var mensagem final = dynamicMessage.format('value1')
Uma abordagem semelhante pode ser possível para cuidar de parâmetros nomeados , etc.
Acho que a questão não é como fazer uma boa experiência de desenvolvedor. A questão é sobre a compilação.
Além disso, o que acontece se você alterar message1 para outra string? Todas as variáveis i18n precisam ser sempre constantes então. Eu não acho que usar variáveis funcionaria. Por exemplo, o Symfony tem um serviço de tradução com uma função de tradução que funcionaria assim na sintaxe JS: let translated = this.translator.trans('Hello %name%', [{'%name%': nameVariable}]);
que resultará em: <source>Hello %name%</source> <target>Bonjour %name%</target>
@MickL o ponto da tradução -aot atual é fazer um programa mínimo e eficiente. É por isso que ainda não existe uma abordagem para tradução dinâmica.
Acredito firmemente que a abordagem atual é muito boa, no sentido de que não estamos usando o serviço de dinâmica para traduzir strings. Isso significa que, se você souber que algum texto é estático, traduza dessa maneira sem usar um serviço.
O problema com a tradução dinâmica é simples, ou seja, se você vai traduzir uma string toda vez que a estiver mostrando. Não é uma maneira muito boa,
Por quê?
Do meu ponto de vista, a solução futura deve ser:
Pense nisso, se você realmente tem texto dinâmico para mostrar, você pode recebê-lo do backend, e se você realmente precisa de uma cópia desse "texto dinâmico", você sempre pode usar o cache para isso.
Na minha opinião, não há mais necessidade de discutir este assunto. Na verdade tem um cara (Olivier Combe) trabalhando FULLTIME no i18n. AOT é muito especial e muito trabalho teve que ser feito antes de tornar essa questão ainda mais próxima possível. Em breve teremos traduções dinâmicas: Não há mais necessidade de construir cada idioma separadamente! Quando isso for feito, teremos traduções dentro do código (essa questão) mais tarde. Ele disse que o caminho até que esse problema seja resolvido, espero, leve meio ano a partir de agora.
Se você estiver interessado, confira o discurso dele no Angular Connect em 07.11.17 sobre o presente e o futuro do i18n em Angular: https://youtu.be/DWet6RvhHWI?t=21m12s
Isso cheira a um bom caso de uso para strings de modelo marcadas com texto datilografado ...
Isso cheira em geral. Eu visito este tópico uma vez por mês para verificar o progresso e parei de me decepcionar por causa das expectativas baixas. A única coisa que os desenvolvedores querem é ter as mesmas opções para tradução de strings no código e nos templates. Meu código está cheio de strings de modelo traduzidas ocultas devido a essa falta de funcionalidade. Se isso eventualmente é realizado com um serviço ou anotações é irrelevante e não importa se leva um milissegundo extra. Já estou observando algo para mudanças quando estou escolhendo uma string do código. O único requisito é que o código seja analisado e as strings relevantes acabem nos mesmos arquivos com o mesmo formato que minhas traduções baseadas em modelo.
@eliasre você pode tentar https://github.com/ngx-translate/i18n-polyfill se estiver com pressa para tradução de código
sem promessas de que será o mesmo, na verdade provavelmente será diferente (como mais fácil de usar), há limitações para o que é possível agora ... e adicionará ~ 80ko ao seu aplicativo para usar essa lib
Você pode usar ngx-translate se não quiser esperar
@ocombe você se importaria de fornecer atualizações sobre o progresso para que possamos acompanhar e planejar de acordo com os cronogramas de desenvolvimento ao aguardar decisões sobre quais plug-ins ou estruturas usar? seria muito útil e apreciado
@eliasre Acho que o google quer fazer uma boa solução de uma só vez. Sem quebrar mudanças no futuro. Concordo que está demorando muito mais do que pensamos.
Não incomode o pobre @ocombe , ele está trabalhando muito, MUITO duro!
Mantem! :)
Não sou eu quem está trabalhando nesse recurso, e é o feriado de fim de ano. Avisarei assim que souber mais
obrigado @ocombe
obrigado @ocombe , qualquer atualização seria muito apreciada aqui. Eu estive esperando desesperadamente pelo tempo de execução i18n nos últimos meses, e o último ETA de compilação foi 5.2. Você pode nos informar assim que tiver um ETA atualizado aqui?
Desculpe por ser tão persistente, mas construir para 20 idiomas acaba sendo terrivelmente lento no momento.
Como o Angular 5.2 saiu e infelizmente não consegui encontrar nada relacionado ao i18n (ou esqueci de algo?) ... - @ocombe talvez você possa nos atualizar sobre o plano de lançamento? Thx muito & thx muito para o seu esforço em i18n!
@ocombe não é o cara que estamos esperando aqui... confira o link do youtube neste comentário: https://github.com/angular/angular/issues/11405#issuecomment -343933617
O planejamento está em constante evolução. Sempre que eu dou uma data provável de lançamento, acontece que outra coisa obtém a prioridade ou se torna necessária e muda a data mais uma vez. Eu sei como é decepcionante para todos vocês que estão esperando por esse recurso, e estou fazendo tudo o que posso para aumentar a prioridade.
Temos uma reunião amanhã para discutir o backlog/planejamento do i18n, avisarei se tiver algo novo.
@ocombe se você lançar o i18n esse mês eu compro um pacote de 24 cervejas artesanais
Adicionarei 24 garrafas de cerveja alemã e outras 24 garrafas se você perguntar o que o Angular Elements e o suporte da biblioteca estão fazendo. Porra, não obter informações do que está acontecendo é horrível.
@ocombe , você tem essa rara oportunidade única na vida de adquirir 72 garrafas de cerveja artesanal cara e deixar a comunidade de desenvolvimento feliz. Cumpriremos nossas promessas se você realizar essas coisas, meu amigo.
@MickL Angualr Elments, pelo que entendi, nos permitirá construir páginas não SPA e usar componentes angulares como elementos nativos (como self-widgets também)
Sim eu sei. Esses são outros 2 recursos que todos estão esperando, mas ninguém sabe qual é o status e quando esperar...
Se alguém prometer adicionar as últimas 27 garrafas de cerveja, podemos começar a contar!
http://www.99-bottles-of-beer.net/language-javascript-1948.html
Vou adicioná-los, @ocombe : nomeie sua marca favorita :D
Edit: alguém cria um serviço semelhante ao eth bounty chamado beerbounty: p
Como prometido, uma pequena atualização: ainda pretendemos lançar o runtime i18n na v6, o que nos dá 5 semanas. Será curto, provavelmente será adicionado em um dos últimos lançamentos e estará atrás de uma bandeira.
Runtime i18n deve vir com traduções de código, porque é assim que funcionará para templates também (deveria usar o mesmo mecanismo).
Dito isto, não é certo que o serviço esteja 100% pronto, e podemos adiá-lo para garantir que não o quebraremos logo após o lançamento, se acharmos que é a escolha certa. Mas ele seguirá o tempo de execução i18n em qualquer caso (esse é nosso roteiro), e não precisamos de uma versão principal para lançá-lo porque estará atrás de um sinalizador e não deve quebrar nada de qualquer maneira).
O que poderia nos impedir de liberá-lo a tempo:
- Desenvolvedor angularJS sênior, usa a lib de tradução do PascalPrecht há 3 anos.
- Excitou-me. Novato em Angular 2. Navegando ingenuamente https://angular.io/guide/i18n
- Integrando com sucesso o i18n no meu projeto profissional
- Passar um dia inteiro mexendo com todos os rótulos codificados de front-end, portando-os para um arquivo xlf de 100+kb
- Na necessidade de traduzir rótulos brutos em serviços ng
- Procurando no google, esteja aqui
- Descubra que não há solução antes das
6 idades do Angular.- eu rn
@Macadoshis você pode usar minha lib polyfill por enquanto: https://github.com/ngx-translate/i18n-polyfill
@Macadoshis agora imagine o que passamos desde alpha.46 ! ;)
Obrigado por apontar o i18n-polyfill para mim @ocombe , mas vou usar o ngx-translate , pois ele suporta o carregamento assíncrono das chaves de tradução.
A fábrica de i18n-polyfill para o provedor TRANSLATIONS
parece oferecer suporte apenas ao carregamento bruto de sincronização de uma localidade fixa conhecida antes do bootstrap.
// sync loading
return require(`raw-loader!../locale/messages.${locale}.xlf`);
// @ngx-translate/i18n-polyfill/esm5/ngx-translate-i18n-polyfill.js
Tokenizer.prototype._advance = function () {
//...
this._index++;
// "this._input" needs to be a string and can't handle a Promise or an Observable
this._peek = this._index >= this._length ? $EOF : this._input.charCodeAt(this._index);
this._nextPeek = this._index + 1 >= this._length ? $EOF : this._input.charCodeAt(this._index + 1);
}
@ocombe quão próximo está o polyfill que você escreveu do que está sendo lançado? Algo que devemos estar cientes ou nos prepararmos? Além disso, você se importaria de listar uma lista dos recursos do i18n que estão sendo lançados na versão 6 e como estão os testes com o i18n?
Não tenho mais detalhes sobre o serviço de tradução de código por enquanto, provavelmente trabalharemos nele na próxima semana (estou viajando para Mountain View). Tudo o que sei é que nos bastidores será semelhante a goog.getMsg
da biblioteca de fechamento (já que é o que o google está usando internamente por enquanto): https://github.com/google/closure-library /blob/db9bc1a2e71d4b6ee8f57eebe37eb0c6494e9d7e/closure/goog/base.js#L2379 -L2387 que também é semelhante ao meu polyfill.
Na v6, lançaremos o runtime i18n: um pacote para todas as localidades, traduções resolvidas em tempo de execução e talvez traduções de código se tivermos tempo (caso contrário, virá logo depois). Tudo isso estará atrás de uma bandeira porque requer o uso do novo renderizador (chamado ng-ivy) que não será testado em batalha.
THX! @ocombe ... isso soa muito bem!
Haverá mudanças significativas na sintaxe para tradução de templates? Estou pensando em adicionar traduções ao nosso projeto agora - mas não quero refazê-lo completamente em algumas semanas.
Não, a sintaxe do modelo será a mesma
Obrigado @ocombe pela ótima notícia, isso é extremamente promissor. Que tipo de prontidão de produção podemos esperar do renderizador ng-ivy que seria lançado com a v6? Eu entendo que não será testado em batalha, mas ainda estaria pronto para uso em produção e funcionaria em todos os principais navegadores de versão quase atual, certo?
Você pode acompanhar o progresso aqui: https://github.com/angular/angular/issues/21706
Eu não acho que tudo estará pronto para a v6, já que está sob uma bandeira, continuaremos progredindo mesmo após o lançamento da v6 (não é uma mudança de ruptura nem nada)
Sinceramente não sei o que são essas coisas :D
Eu sei que um aplicativo hello world do cli já está funcionando.
Eu acho que algumas dessas coisas são necessárias para se beneficiar das otimizações do novo renderizador, mas provavelmente pode funcionar sem ter tudo verificado
Dito isto, também significa que não estará pronto para produção, não aposte seu produto nele ainda. Ele não será testado em aplicativos internos do Google e talvez precisemos fazer algumas alterações importantes para corrigir coisas. O uso do novo renderizador fica a seu critério e por sua conta e risco
Isso está presente no v6-beta4?
Não, não é. Verifique este roteiro , este recurso está bloqueado pelo tempo de execução do i18n.
atualizações @ocombe ?
O primeiro PR para o runtime i18n foi mesclado no master, juntamente com um aplicativo de demonstração hello world que usaremos para testar os recursos. Ele funciona em tempo de execução e suporta teoricamente traduções de código, mesmo que ainda não haja serviço para isso.
Por enquanto, é um suporte mínimo (strings estáticas), estamos trabalhando para adicionar novos recursos (farei a extração funcionar na próxima semana e, em seguida, string dinâmica com espaços reservados e variáveis).
Depois disso faremos o serviço de tradução de código.
Assim que um novo recurso é concluído, ele é mesclado ao mestre, você não terá que esperar por um novo major.
@ocombe i heart i18n recursos já devem estar aqui na v4.3 !! Tantos lançamentos, mas nada no i18n. O gerente de equipe angular pode alocar mais trabalhos / desenvolvedores nele, posso entender você sozinho ou dois desenvolvedores não podem avançar rapidamente, esse recurso i 18n é o recurso obrigatório para fingir que o angular é um aplicativo de negócios / aplicativo grande com construção rápida, é claro esses dois recursos são os mais importantes para aplicativos grandes, você não acha? Obrigado
Acho que a única coisa que podemos dizer ao @ocombe é agradecer a ele por todo o esforço que ele está colocando nesse recurso. Tenho certeza de que se não houver mais desenvolvedores não é porque ele não os pediu. Apenas deixe-o fazer, tenho certeza que não vamos nos arrepender quando for lançado.
Somente para referência...
Eu tenho uma ferramenta alternativa para importar e exportar strings, originalmente desenvolvida para uso com Aurelia, que inclui suporte para strings armazenadas em arquivos json
- é bastante útil, pois o Webpack permite importar diretamente json
em seus arquivos ts
, dando ao seu código acesso fácil a essas strings.
Essa ferramenta também funciona com modelos Angular e possui vários outros recursos úteis - use-o se quiser ou sinta-se à vontade para emprestar ideias para melhorar as ferramentas Angular. Há também um carregador Webpack baseado nisso - veja o link nos documentos.
Temos um problema mais simples e não tenho certeza se precisamos do próximo recurso (ou do polyfill de @ocombe).
Definimos a estrutura de todas as formas reativas com constantes, nas quais definimos as propriedades de cada elemento do formulário. Por exemplo:
loginForm = [
{
type: 'email',
placeholder: 'EMAILPLACEHOLDER' // "Your email"
},
{
type: 'password,
placeholder: 'PASSWORDPLACEHOLDER' // "Your password"
}
];
Atualmente usamos ngx-translate
, então no template traduzimos strings assim:
<input *ngFor="let ele of loginForm" [type]="ele.type" [placeholder]="ele.placeholder | translate">
Agora gostaríamos de migrar para o Angular i18n. No entanto, como nem todas as nossas strings estão em um modelo, parece que não podemos usar o Angular i18n pronto para uso.
Nossa situação parece mais simples do que aquela em que as traduções precisam ser recuperadas em tempo de execução. Todos os nossos textos são pré-definidos em constantes, e podem ser substituídos em tempo de compilação, assim como x18n atualmente faz para strings em templates.
Por exemplo, poderíamos ter uma string mais complexa como a seguinte
placeholder: 'I18N:description|meaning@<strong i="16">@PASSWORDPLACEHOLDER</strong>:Your password'
Em tempo de compilação, a string pode ser substituída por:
placeholder: 'Your password'
Isso é algo que pode ser considerado para implementação?
você definitivamente poderia fazer isso com o tempo de execução i18n, você poderia usar o novo serviço i18n em um pipe, por exemplo, para transformar seus espaços reservados em suas traduções
Percebo que este tópico está aberto há algum tempo, mostra o grande interesse em desenvolver sites multilíngue em Angular de maneira simples, abordando de perto tanto textos HTML quanto de código componente.
ocombe, por favor, não se esqueça de enviar um alerta a todos os assinantes quando isso for feito - eu entendi que está chegando em maio de 2018. E obrigado por suas contribuições gentis!
@ocombe devemos usar o Ivy para poder usar esses serviços de tempo de execução ou funcionará com o mecanismo antigo também?
será apenas com ivy, que você não pode usar por enquanto, pois não está finalizado
Obrigado por todo o seu trabalho duro @ocombe !
Alguma palavra sobre quando podemos usar esses novos recursos?
A Ivy pode ser habilitada no angular 6 com um sinalizador do compilador agora, em um estado de pré-lançamento. Esses novos recursos de 18n podem ser usados usando o pré-lançamento da Ivy neste momento?
Ainda não, mas estou fazendo um bom progresso (trabalhando em tempo integral nisso agora). Vou postar uma atualização aqui assim que estiver disponível no master para testar
muito obrigado @ocombe ! Tantas pessoas estão se beneficiando de seu trabalho duro. Todos nós agradecemos muito!
@ocombe As traduções estáticas em ts ainda estão planejadas? Quero dizer, substituição de expressão em tempo de compilação, provavelmente com transformação datilografada.
Se não, seremos capazes de conectar a transformação ts personalizada no pipeline ng build
sem extrair ?
Não tenho certeza de entender o que você quer dizer com @TinyMan ? Você quer dizer ser capaz de mesclar traduções em tempo de compilação (como está agora), ou ser capaz de usar traduções em código ts (além das traduções de templates que já temos)?
@ocombe , quero dizer, poder usar a tradução em ts, mas não por meio de um serviço ou tradução de DI / tempo de execução. Quero dizer tradução em tempo de compilação, mas para texto datilografado. Como o pré-processador C. Eu pensei que foi planejado de acordo com o comentário vicb :
- também podemos oferecer suporte a traduções estáticas como fazemos hoje para modelos - as strings seriam substituídas em tempo de compilação, melhor desempenho, mas uma versão do aplicativo por localidade,
Por exemplo, eu quero ser capaz de escrever:
export const Notifications = {
newComment: i18n("New comment notification@@newComment", "New comment on your story !"),
newStory: i18n("New story notification@@newStory", "{{0}} wrote a new story !"),
}
E então isso é transpilado para algo como (in fr):
export const Notifications = {
newComment: "Un nouveau commentaire a été ajouté a votre article !",
newStory: "{{0}} a écrit un nouvel article !",
}
Atualmente para isso uso ngx-translate com um marcador personalizado para a extração ( i18n
neste exemplo), e quando preciso exibir a mensagem tenho que chamar this.translate.instant(Notifications.newStory, ["TinyMan"])
que faz a tradução + a interpolação. O que quero dizer é que precisaríamos ser capazes de escrever Notifications.newComment
sem chamar o serviço de tradução. E para interpolação de strings poderíamos ter um método de interpolação que faça apenas o ICU e a interpolação (a string do template já estaria traduzida)
Notification.newStory // {{0}} a écrit un nouvel article, static string, no runtime translation
template(Notification.newStory, "TinyMan") // TinyMan a écrit un nouvel article !
Aqui, apenas nos livramos da solicitação HTTP de traduções e da sobrecarga de serviço.
espero que esclareça?
O que você descreve está realmente no roteiro para i18n.
No momento, https://github.com/ngx-translate/i18n-polyfill fará o trabalho.
@TinyMan Ainda não tenho certeza se será por meio de um serviço ou de uma função global. Ambos são possíveis, mas um serviço também tem muitas vantagens: você pode zombar dele para testes, ou substituí-lo pelo seu próprio, você também pode alterar seu comportamento para cada módulo/componente
Eu sei que internamente o Google usará Closure i18n (via goog.getMsg
) que é uma função global, e a função provavelmente será substituída pelo serviço durante a compilação com base em um sinalizador global. Vou tentar ver se esse sinalizador também pode ser usado externamente, mas não vejo porque não. Mas se você usar isso, será para modelos e traduções de código
@ocombe Eu quero agradecer aqui também. Eu super aprecio o trabalho que você está fazendo nisso, que será incrivelmente útil para mim no meu trabalho. Uma pergunta: existe uma maneira, ou _haverá_ uma maneira, de fazer a compilação AOT que faz apenas um conjunto de arquivos de pacote que, ao procurar por texto, referencia o xlf em tempo de execução para obter a string correta?
então, em essência, você precisaria de 1 arquivo xlf por idioma mais os 5 ou 6 arquivos de pacote. No momento, se tivermos 10 idiomas e compilação AOT, são mais de 50 arquivos: um conjunto de arquivos de pacote por idiomas...
Não sei o esforço ou a complexidade de algo assim, mas seria bom ter uma compilação mas com apenas 1 conjunto de arquivos.
sim, é isso que faremos com ivy, runtime i18n
agrupar seu aplicativo uma vez e carregar as traduções em tempo de execução (você pode carregar as traduções com preguiça)
@ocombe isso. é. incrível.
Isso me deixa tão inacreditavelmente feliz. OBRIGADA!
Sem a capacidade de traduzir modelos externos, o recurso i18n
é completamente inútil para mim.
@ocombe Olá Olivier!
Alguma atualização?
Obrigado!
Se for feito, não importa, pois temos que esperar que Ivy esteja completo, que está programado para Angular 7 (setembro/outubro de 2018)
Por Angular 7 esta edição terá dois anos LOL.
De qualquer forma, Ivy foi o que mais atrasou esse novo recurso ...
@ocombe , é ótimo ouvir isso. Atualmente, estamos presos usando um serviço i18n herdado que lançamos desde o início puramente por esse motivo. Não poder fazer isso em JS torna extremamente difícil fazer algumas coisas simples para nós:
types
. Em nosso contexto, precisamos localizar dinamicamente esses erros e uma abordagem orientada por modelo seria complicada.TitleService
como sugere a equipe do Angular, mas não há como fornecer texto localizado!Estou meio curioso como a equipe Angular lida com isso atualmente ...
Olá @vincentjames501 ,
Em nossa empresa, tentamos fazer o mesmo que você está fazendo agora, mas foi muito problemático, então acabamos usando o i18n-polyfill mencionado anteriormente neste tópico, e até agora está funcionando muito bem.
A única desvantagem que temos é o tamanho dos pacotes do nosso aplicativo. Temos três arquivos de tradução, e cada pacote contém todos eles dentro (não descobrimos uma maneira de gerar o pacote apenas com a tradução que ele usa). Mas tudo isso são apenas incômodos que esperamos que sejam resolvidos quando Ivy sair.
Saúde,
Incluí um mapa de tradução e o reexportei no arquivo environment.ts de cada idioma. Funciona sem problemas, não está incluído em todos os pacotes e não requer uma biblioteca externa. O único problema que tenho é que, como cada site é diferente, não posso ter o mesmo service worker para todos os idiomas e, se alguém mudar de idioma, meu site não pode dizer se ele já está registrado para notificações push ou não ...
@ocombe alguma novidade no angular 6?
Não será em Angular v6, conforme explicado acima. Dependemos de Ivy que está planejada para v7.
@ocombe posso sugerir que você bloqueie este tópico, para que apenas a equipe possa fornecer atualizações significativas quando apropriado e evitarmos as perguntas repetitivas que você continua respondendo?
Meu hack para uso com o Angular atual é usar um ng-template
e criar a view incorporada programaticamente:
<ng-template #messagetotranslate i18n>This message should be translated</ng-template>
e depois no arquivo ts do componente:
@ViewChild('messagetotranslate') messagetotranslate: TemplateRef<any>;
createTranslatedMessage(): string {
return this.messagetotranslate.createEmbeddedView({}).rootNodes[0].textContent;
}
O método createTranslatedMessage
retorna a mensagem traduzida. Embora eu esteja usando o modelo para declarar a mensagem que não é ideal, isso possibilita que a ferramenta de tradução da CLI a registre nos arquivos xlf, e tenho uma maneira de obter a mensagem traduzida programaticamente para uso em modelos externos.
Espero que a API funcione para as rotas também! Por exemplo
export const routes: Routes = [
{
path: '',
component: HomeComponent,
data: {
title: i18n('Home'),
breadcrumb: i18n('Home')
}
}
]
Se esse recurso for lançado, haveria uma mudança significativa em relação à API i18n atual? Você recomendaria que eu iniciasse meu projeto com o i18n agora ou devo esperar pela nova i18n Api quando o Angular 7 for lançado?
Alguma atualização Quando teremos suporte para tradução dinâmica e em tempo de execução?
As traduções em tempo de execução são feitas e mescladas (com ivy), mas o lado do compilador ainda não está concluído.
Estou trabalhando em expressões de UTI agora.
Ainda não comecei a codificar as traduções dinâmicas (serviço), mas provavelmente é a próxima coisa que farei depois das expressões ICU.
@vincentjames501 Podemos usar i18n-polyfills com expressão ICU? Não tenho solução para implementar isso
@ocombe , você pode esclarecer a diferença entre o tempo de execução e as traduções dinâmicas?
provavelmente não há denominação oficial, mas do jeito que eu vejo é:
Adiei a adição de suporte i18n ao projeto atual que estamos desenvolvendo, mas estamos chegando perto do lançamento, alguma ideia se isso será final no angular 7? Ou devo considerar outras formas de adicionar traduções?
@andrei-tatar i18n está funcionando perfeitamente desde Angular 2. As únicas desvantagens:
Para os dois últimos pontos, você pode usar @ngx-translate. Mas funciona de maneira diferente do i18n integrado do Angular, portanto, uma atualização posterior pode levar algum tempo. Para o polyfill, a atualização não será demorada, provavelmente sem alterações importantes.
@shobhit12345
Usamos o ngSwitch para modelar todas as mensagens, para que possamos anexar tags i18n a elas individualmente.
<div>
<ng-container [ngSwitch]="paymentMethod.historyOpned">
<ng-container *ngSwitchCase="true" i18n="@@hide">Hide</ng-container>
<ng-container *ngSwitchCase="false" i18n="@@show">Show</ng-container>
</ng-container>
<ng-container> <ng-container>
<ng-container i18n="@@history">History</ng-container>
</div>
Usamos muito esse método para contornar as traduções dinâmicas ausentes. Dado um pouco de pensamento, uma quantidade surpreendente de texto pode ser expressa dessa maneira em modelos. Um padrão comum é ter uma matriz de mensagens e usar isso com ngFor e ngSwitch para modelar as mensagens, algo assim:
ts
messsages = [ 'this is the first message', 'this is the second message' ]
````
html
```
É um pouco verboso - mas funciona!
Muito obrigado, entendi a ideia.
Em sex, 24 de agosto de 2018, 16:56 David Walther Birk Lauridsen, <
[email protected]> escreveu:
@shobhit12345 https://github.com/shobhit12345
Usamos o ngSwitch para modelar todas as mensagens, para que possamos anexar tags i18n a
eles individualmente.Esconder Mostrar História Usamos muito esse método para contornar as traduções dinâmicas ausentes.
Com um pouco de reflexão, uma quantidade surpreendente de texto pode ser expressa em
desta forma nos modelos. Um padrão comum é ter uma matriz de mensagens,
e, em seguida, use isso com ngFor e ngSwitch para modelar as mensagens,
algo assim:ts
mensagens = [ 'esta é a primeira mensagem', 'esta é a segunda mensagem' ]
html
i18n="@@firstMesssage">Esta é a primeira mensagem i18n="@@secondMesssage">Esta é a segunda mensagem É um pouco verboso - mas funciona!
—
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/angular/angular/issues/11405#issuecomment-415731284 ,
ou silenciar o thread
https://github.com/notifications/unsubscribe-auth/AGwM6jcWIpwtGxhkH1fwnVXNagRxmMnoks5uT-LxgaJpZM4J2pkr
.
Se for feito, não importa, pois temos que esperar que Ivy esteja completo, que está programado para Angular 7 (setembro/outubro de 2018)
Já é outubro. Você acha que teremos os novos recursos até o final de outubro?
@lizzymendivil de acordo com https://is-angular-ivy-ready.firebaseapp.com Ivy está 65% concluída e parece improvável que seja concluída em apenas 30 dias
Sim, a hera não será concluída em um mês.
@ocombe você pode bloquear isso para que apenas você possa postar atualizações. é um pouco chato receber todas as notificações de todos os "quando é feito?" comentários
@ocombe parece que Ivy está agora em aproximadamente 94%, você acha que isso pode estar pronto até o final do ano?
Acho que não. Estar pronto para recursos e livre de bugs (= utilizável) é muito diferente. Estamos trabalhando principalmente para consertar as coisas agora.
@ocombe podemos acreditar que o i18n veio antes do angular 8?
Acho que não. Estar pronto para recursos e livre de bugs (= utilizável) é muito diferente. Estamos trabalhando principalmente para consertar as coisas agora.
Ok, obrigado pela pronta resposta, muito apreciado.
Alguma atualização @ocombe que até quando devemos esperar (Fim do ano, vejo nos últimos comentários) a parte "Tradução de código" disponível junto com "Tradução de modelo" para suporte a I18N com Angular? Pensamos em juntar ngx-translate-polyfill para o mesmo junto com o recurso Angular I18n, mas também parece que o suporte xlf não está disponível para mesclar o arquivo xlf existente usando https://github.com/biesbjerg/ngx-translate-extract CLI .
Obrigado !
@Abekonge
Usamos o ngSwitch para modelar todas as mensagens, para que possamos anexar tags i18n a elas individualmente.
É um pouco verboso - mas funciona!
Obrigado pela sugestão! Parece o mais fácil de entender. Minha pergunta é, você ainda usa essa implementação em situações em que o array tem muitos valores, como 10 ou mais? Parece que o código ficaria muito volumoso.
Não sei se temos algum com tantos, mas por que não. Se as mensagens são usadas em vários lugares, fazemos pequenos componentes i18n que são basicamente apenas o switch e as tags i18n.
Davi
Den 23. jan. 2019 k. 19.24 skrev Andrew Bissada [email protected] :
@Abekonge
Usamos o ngSwitch para modelar todas as mensagens, para que possamos anexar tags i18n a elas individualmente.
É um pouco verboso - mas funciona!Obrigado pela sugestão! Parece o mais fácil de entender. Minha pergunta é, você ainda usa essa implementação em situações em que o array tem muitos valores, como 10 ou mais? Parece que o código ficaria muito volumoso.
—
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub ou silencie a conversa.
Como usar i18n-polifills nas classes do Validador. Não consigo usar a mensagem do validador secreto por meio do serviço i18n.
//No componentenet
this.crForm= this.fb.group({
nome do usuário: [''],
Senha eletrônica: [''],
}, { validador: new AccValidator(this.i18n).validate()}
);
//Validador
import { AbstractControl, ValidationErrors, FormGroup, FormControl } de '@angular/forms';
importe { I18n } de '@ngx-translate/i18n-polyfill';
export class AccValidator{
construtor(i18n:I18n)
{
}
validate() {
return (group: FormGroup): createAccountError => {
if (group) {
this.i18n("test");
}}}
ficando abaixo do erro
Erro RROR: Não capturado (em promessa): TypeError: i18n não é uma função
TypeError: i18n não é uma função
em FormGroup.eval [como validador] (acc-validator.ts:9)
em FormGroup.AbstractControl._runValidator (forms.js:3433)
em FormGroup.AbstractControl.updateValueAndValidity (forms.js:3387)
no novo FormGroup (forms.js:4326)
em FormBuilder.group (forms.js:7864)
@ocombe
Como usar i18n-polyfills com const em arquivos .ts
export const glossayModel= () => [
{
título: 'dados de teste',
ativo: verdadeiro,
dados: [
[
{
title: 'test data',
data: "test data."
},
{
title: 'test data',
data: "test data"
},
{
title: 'test data',
data: "test data"
},
{
title: 'test data',
data: "test data."
},
{
title: 'Past Due',
data: "test data."
}
]]}];
Catastrófica ### & Dental{Catastrophic y Dental} Catastrophic {Catastrophic} }
Quando estou usando a expressão ICU com caractere especial, não está convertendo.
@ocombe Como lidar com migalhas de pão usando i18n-polyfills?
export const rotas: Rotas = [
{
caminho: '',
componente: HomeComponent,
dados: {
título: 'Casa',
pão ralado: 'Casa'
}
}
]
@ocombe
Como usar i18n-polyfills com const em arquivos .ts
export const glossayModel= () => [
{
título: 'dados de teste',
ativo: verdadeiro,
dados: [[ { title: 'test data', data: "test data." }, { title: 'test data', data: "test data" }, { title: 'test data', data: "test data" }, { title: 'test data', data: "test data." }, { title: 'Past Due', data: "test data." }
]]}];
Você pode usar assim
{
dados: 'dados de teste',
título: this.i18n({ valor: 'Nome', id: 'nome' }),
}
injetar polyfill I18n no construtor de componentes como este
privado i18n: I18n
Ao usar traduções no arquivo ts, você precisa usar ngx-extractor e xliffmerge para traduzir esses arquivos ts. https://www.npmjs.com/package/ngx-i18nsupport
@ Janne Harju
não está funcionando, não está obtendo os dados no arquivo xlf.
Aqui está o meu script de tradução:
"translate-i18n": "ng xi18n --output-path locale && ngx-extractor -i src/**/*.ts projects/**/*.ts -f xlf -o src/locale/messages.xlf && xliffmerge --profile xliffmerge.json fi en",
e aqui está xliffmerge.json
{
"xliffmergeOptions": {
"srcDir": "src/locale",
"genDir": "src/locale",
"i18nFile": "messages.xlf",
"defaultLanguage": "en",
"useSourceAsTarget": true
}
}
@ Janne Harju
Sim, estou usando a mesma configuração e capaz de extrair mensagens .ts no arquivo xlf.
Mas const eu tenho em diferentes arquivos .ts
export const glossayModel= () => [
{
}
estou importando em componente, quando estou tentando usar i18n com const, não está extraindo os valores.
E se você usar valores const como provedor.
{
provide: glossayModel,
useFactory: () => glossayModel()
}
o código pode estar quebrado, mas talvez você ganhe ponto.
como traduzir breadcrumbs
const rotas: Rotas = [
{
caminho: './enroll-new.component',
componente: InscreverNovoComponente,
dados: {
breadcrumb: 'Inscrição'
},
}
]
vocês podem parar de usar este tópico como um tópico de suporte para i18n-polyfill ou outros problemas? se você tiver uma pergunta sobre o i18n-polyfill, levante um problema nesse repositório.
@ocombe talvez você possa bloquear este tópico? praticamente tudo o que é importante deve ser coberto.
qual é a versão angular que você planeja liberar o suporte i18n mencionado neste tópico?
Sim, bloqueado por enquanto.
Estamos trabalhando duro para ter o ivy disponível com a v8 como uma versão beta opcional. O tempo de execução i18n será utilizável com o fechamento do google (o que o google usa internamente), o que nos permitirá depurá-lo (é uma mudança muito grande). Para todos os outros, você poderá testar o ivy com o i18n, mas não poderá carregar as traduções. O aplicativo será executado com o idioma original usado para codificar o aplicativo.
O serviço de tempo de execução necessário para traduzir atualmente retorna o texto não traduzido. Como estamos todos trabalhando na correção de bugs com o código existente, os novos recursos serão limitados após o lançamento. Trabalharemos nisso assim que a v8 for lançada, deve ser minha primeira tarefa.
Vou adicionar uma atualização e desbloquear este tópico assim que tivermos algumas novidades.
Pelo que vale a nova tag $localize
que estamos trabalhando pode ser usada programaticamente.
Por exemplo
const name = 'World';
$localize `Hello ${name}:name!`;
E então poderá fornecer traduções para Hello {$name}!
que podem ser substituídas em tempo de compilação (ou tempo de execução).
Isso agora está disponível (se não documentado).
Comentários muito úteis
Eu acho que isso é um verdadeiro showtopper, i18n não está pronto para uso até que isso seja implementado.
Por exemplo, não consigo definir mensagens de validação traduzidas no código