Traducción de un interesantísimo artículo de Yiğit Findikli, donde nos explica detalladamente como podemos utilizar y sacar provecho de la API de internacionalización PrimeNG con ngx-translate.
Guía de uso de la API de i18n PrimeNG sobre una aplicación Angular, para traducir un calendario y un formulario. Texto original escrito por Yiğit Findikli.
Disclaimer: Artículo traducido por un traductor en formación. Si necesitas una traducción profesional, ponte en contacto con la empresa de traducción Ibidem Group, Tienen una agencia de traducción en Barcelona y una oficina de traducción en Madrid.
Vamos a crear una nueva aplicación angular usando angular-cli.
ng new primeng-i18n-with-ngx
cd primeng-i18n-with-ngx
Añadiremos PrimeNG, PrimeFlex, PrimeIcons y ngx-translate.
npm install primeng primeicons primeflex@2.0.0 @ngx-translate/core @ngx-translate/http-loader @angular/localize
Necesitamos importar las dependencias CSS de PrimeNG a Angular.json.
node_modules/primeicons/primeicons.css
node_modules/primeng/resources/themes/vela-blue/theme.css
node_modules/primeng/resources/primeng.min.css
Ahora necesitamos un par de componentes PrimeNG y la configuración de ngx-translate.
Nota: La configuración detallada de ngx-translate se puede encontrar en la documentación oficial.
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { RadioButtonModule } from 'primeng/radiobutton';
import { CalendarModule } from 'primeng/calendar';
import { DropdownModule } from 'primeng/dropdown';
import { FileUploadModule } from 'primeng/fileupload';
import { TableModule } from 'primeng/table';
import { ButtonModule } from 'primeng/button';
import { ConfirmPopupModule } from 'primeng/confirmpopup';
import { AppComponent } from './app.component';
// AoT requires an exported function for factories
export function HttpLoaderFactory(httpClient: HttpClient) {
return new TranslateHttpLoader(httpClient);
}
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
HttpClientModule,
FormsModule,
RadioButtonModule,
DropdownModule,
CalendarModule,
FileUploadModule,
TableModule,
ConfirmPopupModule,
ButtonModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
})
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Quiero utilizar la traducción del Inglés al Francés porque ngx-translation la utiliza en su ejemplo.
Vamos a
crear nuestros archivos JSON de traducción. La ruta debe ser así:
en.json:
{
"demo": {
"greetings": "Hello!",
"en": "English",
"fr": "French"
}
}
fr.json:
{
"demo": {
"greetings": "Bonjour!",
"en": "Anglaise",
"fr": "Français"
}
}
¡Vamos a crear nuestra lógica de traducción! Vamos a utilizar TranslateService y translate pipe para la funcionalidad de traducción general para la traducción.
app.component.html:
<div class="p-d-flex p-ai-center p-jc-between p-mt-3">
<div class="p-col-6">
<h2 class="p-ml-3">{{ 'demo.greetings' | translate }}</h2>
</div>
<div class="p-d-flex p-col-6 p-jc-end">
<div class="p-mr-3">
<p-radioButton (ngModelChange)="changeLang($event)" name="language" value="en" [(ngModel)]="lang"
inputId="en"></p-radioButton>
<label class="p-ml-1" for="en">{{ 'demo.en' | translate }}</label>
</div>
<div class="p-mr-3">
<p-radioButton (ngModelChange)="changeLang($event)" name="language" value="fr" [(ngModel)]="lang"
inputId="fr"></p-radioButton>
<label class="p-ml-1" for="fr">{{ 'demo.fr' | translate }}</label>
</div>
</div>
</div>
app.component.ts:
import { Component } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { ConfirmationService, PrimeNGConfig } from 'primeng/api';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [ConfirmationService]
})
export class AppComponent {
lang: string = "en";
constructor(public translate: TranslateService, public primeNGConfig: PrimeNGConfig, private confirmationService: ConfirmationService) {
translate.addLangs(['en', 'fr']);
translate.setDefaultLang('en');
const browserLang = translate.getBrowserLang();
let lang = browserLang.match(/en|fr/) ? browserLang : 'en';
this.changeLang(lang);
}
changeLang(lang: string) {
this.translate.use(lang);
}
}
Muy bien, ¡probemos!
Es genial, ¿verdad?
Necesitamos utilizar PrimeNGConfig para la traducción de los componentes PrimeNG. El uso es bastante simple.
Uso de la documentación:
constructor(private config: PrimeNGConfig) {}
ngOnInit() {
this.config.setTranslation({
accept: 'Accept',
reject: 'Cancel',
//translations
});
}
Pero queremos usarlo en nuestro JSON I18N.
Creemos un calendario y cambiemos los nombres de los meses y los días.
En primer lugar, tenemos que añadir los nombres de los meses y los días a los archivos de traducción.
PrimeNGConfig utiliza;
Nuestros archivos deberían ser así:
{
"demo": {
"greetings": "Hello!",
"en": "English",
"fr": "French",
"date": "Date"
},
"primeng": {
"dayNamesMin": [
"Su",
"Mo",
"Tu",
"We",
"Th",
"Fr",
"Sa"
],
"monthNames": [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
]
}
}
{
"demo": {
"greetings": "Bonjour!",
"en": "Anglaise",
"fr": "Français",
"date": "La datte"
},
"primeng": {
"dayNamesMin": [
"Di",
"Lu",
"Ma",
"Me",
"Je",
"Ve",
"Sa"
],
"monthNames": [
"Janvier",
"Février",
"Mars",
"Avril",
"Mai",
"Juin",
"Juillet",
"Août",
"Septembre",
"Octobre",
"Novembre",
"Décembre"
]
}
}
Nota: el uso de «primeng» es sólo un ejemplo.
Vamos a crear nuestro Calendario.view raw app.component.html hosted with ❤ by GitHub
Ahora queremos cambiar la API I18N de PrimeNG cuando se active ngx-translate. Podemos utilizar el observable «stream» de ngx-translate para la detección.
import { Component, OnDestroy } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { ConfirmationService, PrimeNGConfig } from 'primeng/api'; import { Subscription } from 'rxjs'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], providers: [ConfirmationService] }) export class AppComponent implements OnDestroy { lang: string = "en"; date: any; subscription: Subscription; constructor(public translate: TranslateService, public primeNGConfig: PrimeNGConfig, private confirmationService: ConfirmationService) { translate.addLangs(['en', 'fr']); translate.setDefaultLang('en'); const browserLang = translate.getBrowserLang(); let lang = browserLang.match(/en|fr/) ? browserLang : 'en'; this.changeLang(lang); this.subscription = this.translate.stream('primeng').subscribe(data => { this.primeNGConfig.setTranslation(data); }); } changeLang(lang: string) { this.translate.use(lang); } ngOnDestroy() { if (this.subscription) { this.subscription.unsubscribe(); } } }view raw app.component.ts hosted with ❤ by GitHub
Stream nos está dando la sección primeng (según la opción de traducción utilizada). Los datos que vienen son:
{ "dayNamesMin": [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ], "monthNames": [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ] }
Sólo vinculamos nuestros datos de traducción a PrimeNGConfig con la función setTranslation. Y ¡Voilà! ¡Nuestro calendario traducido!
Utilicemos esta lógica también para Dropdown, ColumnFilter, ConfirmPopup y FileUpload.
Las claves de la API PrimeNG I18N están disponibles en la documentación.
Ahora vamos a actualizar nuestros JSONs de traducción de nuevo.
{ "demo": { "greetings": "Hello!", "en": "English", "fr": "French", "date": "Date", "emptyMessage": "Empty Message", "message": "Are you sure that you want to proceed?", "confirm": "Confirm", "name": "Name" }, "primeng": { "dayNamesMin": [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ], "monthNames": [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], "emptyMessage": "No results found", "emptyFilterMessage": "No results found - Filter", "choose": "Choose", "upload": "Upload", "cancel": "Cancel", "startsWith": "Starts with", "contains": "Contains", "notContains": "Not contains", "endsWith": "Ends with", "equals": "Equals", "notEquals": "Not equals", "clear": "Clear", "apply": "Apply", "matchAll": "Match All", "matchAny": "Match Any", "addRule": "Add Rule", "removeRule": "Remove Rule", "accept": "Yes", "reject": "No" } }
{ "demo": { "greetings": "Bonjour!", "en": "Anglaise", "fr": "Français", "date": "La datte", "emptyMessage": "Message vide", "message": "Êtes-vous sûr de vouloir continuer?", "confirm": "Confirmer", "name": "Nom" }, "primeng": { "dayNamesMin": [ "Di", "Lu", "Ma", "Me", "Je", "Ve", "Sa" ], "monthNames": [ "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre" ], "emptyMessage": "Aucun résultat trouvé", "emptyFilterMessage": "Aucun résultat trouvé - Filtre", "choose": "Choisir", "upload": "Télécharger", "cancel": "Annuler", "startsWith": "Commence avec", "contains": "Contient", "notContains": "Ne contient pas", "endsWith": "Se termine par", "equals": "Équivaut à", "notEquals": "Pas égal", "clear": "Dégager", "apply": "Appliquer", "matchAll": "Faire correspondre tout", "matchAny": "Correspondre à n'importe quel", "addRule": "Ajouter une règle", "removeRule": "Supprimer la règle", "accept": "Oui", "reject": "Non" } }
Ahora vamos a crear nuestros componentes. Porque nuestra lógica de traducción ya está presente. No necesitamos ningún cambio lógico. Ya hemos actualizado los JSON de traducción.
import { Component, OnDestroy } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { ConfirmationService, PrimeNGConfig } from 'primeng/api'; import { Subscription } from 'rxjs'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], providers: [ConfirmationService] }) export class AppComponent implements OnDestroy { lang: string = "en"; date: any; uploadedFiles: any[] = []; password: string = ""; subscription: Subscription; customers = [ { "name": "Yancey" }, { "name": "Chilton" }, { "name": "Angelo" }, { "name": "Carita" }, { "name": "Wernher" } ] constructor(public translate: TranslateService, public primeNGConfig: PrimeNGConfig, private confirmationService: ConfirmationService) { translate.addLangs(['en', 'fr']); translate.setDefaultLang('en'); const browserLang = translate.getBrowserLang(); let lang = browserLang.match(/en|fr/) ? browserLang : 'en'; this.changeLang(lang); this.subscription = this.translate.stream('primeng').subscribe(data => { this.primeNGConfig.setTranslation(data); }); } changeLang(lang: string) { this.translate.use(lang); } onUpload(event: any) { for (let file of event.files) { this.uploadedFiles.push(file); } } confirm(event: any) { this.confirmationService.confirm({ target: event.target, message: this.translate.instant('demo.message'), icon: 'pi pi-exclamation-triangle' }); } ngOnDestroy() { if (this.subscription) { this.subscription.unsubscribe(); } } }
¡Aquí vamos!
¡Voilà!
Gracias por la lectura.
Articulos relacionados
Traducción de un interesante artículo de Dana Woodman explicando cómo añadir traducciones y localización sencilla a una app Svelte. El método se basa en un post de Matthias Stahl, pero Dana Woodman explica cómo hacerlo sin necesidad de crear un repositorio adicional para las...
Traducción de Inglés a Español de un interesantísimo artículo de Matt Layman, ingeniero de software experto en open source y Python, que nos muestra en esta guía cómo hacer la internacionalización (i18n) para una aplicación de Python.
Traducción de Inglés a Español de un interesantísimo artículo de Dawei Ma, desarrollador de Xian, que nos explica detalladamente cómo implementar un proyecto de traducción de software, incluyendo tanto internacionalización (varios entornos lingüísticos) como localización...