94
PrimeNG I18N API Usage with ngx-translate
How can we use PrimeNG I18N with ngx-translate? Let's start!
Let's create a brand new angular application using angular-cli.
ng new primeng-i18n-with-ngx
cd primeng-i18n-with-ngx
Let's add PrimeNG, PrimeFlex, PrimeIcons, and ngx-translate.
npm install primeng primeicons primeflex@2.0.0 @ngx-translate/core @ngx-translate/http-loader @angular/localize
We need to import PrimeNG's CSS dependencies to Angular.json.
node_modules/primeicons/primeicons.css
node_modules/primeng/resources/themes/vela-blue/theme.css
node_modules/primeng/resources/primeng.min.css
Now we need a couple of PrimeNG components and ngx-translate setup.
Note: Detailed ngx-translate setup can be found in official docs.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 { } |
I want to use English to French translation because ngx-translation uses in their example.
en.json:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"demo": { | |
"greetings": "Hello!", | |
"en": "English", | |
"fr": "French" | |
} | |
} |
fr.json:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"demo": { | |
"greetings": "Bonjour!", | |
"en": "Anglaise", | |
"fr": "Français" | |
} | |
} |
Let's create our translation logic! We gonna use TranslateService and translate pipe for the general translation functionality for the translation.
app.component.html:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
It's cool, right?
We need to use PrimeNGConfig for the translationing the PrimeNG components. Usage is quite simple.
Usage from the Documentation:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
constructor(private config: PrimeNGConfig) {} | |
ngOnInit() { | |
this.config.setTranslation({ | |
accept: 'Accept', | |
reject: 'Cancel', | |
//translations | |
}); | |
} |
But we want use in the our I18N JSON.
Let's create a calendar and change the month and day names!
Firstly we need to add month and day names to translation files.
PrimeNGConfig uses;
Month names for: monthNames
Min day names for: dayNamesMin.
Our files should be like this:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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" | |
] | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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" | |
] | |
} | |
} |
Note: "primeng" usage just an example.
Let's create our Calendar.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> | |
<div class="p-fluid p-formgrid p-grid p-jc-center p-mt-3 p-mr-0"> | |
<div class="p-col-6"> | |
<div class="p-field p-col-12"> | |
<label for="date">{{ 'demo.date' | translate }}</label> | |
<p-calendar inputId="date" [(ngModel)]="date"></p-calendar> | |
</div> | |
</div> | |
</div> |
Now we want to change PrimeNG I18N API when ngx-translate trigger. We can use ngx-translate's "stream" observable for the detection.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} | |
} |
Stream is giving to us primeng section(According to the which translation option used). Coming data is:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"dayNamesMin": [ | |
"Su", | |
"Mo", | |
"Tu", | |
"We", | |
"Th", | |
"Fr", | |
"Sa" | |
], | |
"monthNames": [ | |
"January", | |
"February", | |
"March", | |
"April", | |
"May", | |
"June", | |
"July", | |
"August", | |
"September", | |
"October", | |
"November", | |
"December" | |
] | |
} |
We just binding our translation data to PrimeNGConfig with setTranslation function. And Voilà! Our calendar translated!


Let's use this logic for Dropdown, ColumnFilter, ConfirmPopup and FileUpload too!
PrimeNG I18N API keys are on available at the documentation.
Now we're gonna update our translation JSONs again.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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" | |
} | |
} |
Now we're just gonna create our components. Because our translation logic is already present. We don't need any logical change. We already did update the translation JSONs!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> | |
<div class="p-fluid p-formgrid p-grid p-jc-center p-mt-3 p-mr-0"> | |
<div class="p-col-6"> | |
<div class="p-field p-col-12"> | |
<label for="date">{{ 'demo.date' | translate }}</label> | |
<p-calendar inputId="date" [(ngModel)]="date"></p-calendar> | |
</div> | |
<div class="p-field p-col-12"> | |
<label for="empty">{{ 'demo.emptyMessage' | translate }}</label> | |
<p-dropdown [filter]="true" inputId="empty"></p-dropdown> | |
</div> | |
<div class="p-field p-col-12"> | |
<p-fileUpload name="demo[]" (onUpload)="onUpload($event)" [multiple]="true"> | |
<ng-template pTemplate="content"> | |
<ul *ngIf="uploadedFiles.length"> | |
<li *ngFor="let file of uploadedFiles">{{file.name}} - {{file.size}} bytes</li> | |
</ul> | |
</ng-template> | |
</p-fileUpload> | |
</div> | |
<div class="p-field p-col-12"> | |
<p-table [value]="customers"> | |
<ng-template pTemplate="header"> | |
<tr> | |
<th> | |
<div class="p-d-flex p-jc-between p-ai-center"> | |
{{ 'demo.name' | translate }} | |
<p-columnFilter type="text" field="name" display="menu"></p-columnFilter> | |
</div> | |
</th> | |
</tr> | |
</ng-template> | |
<ng-template pTemplate="body" let-customer> | |
<tr> | |
<td> | |
{{customer.name}} | |
</td> | |
</tr> | |
</ng-template> | |
</p-table> | |
</div> | |
<div class="p-field p-col-12"> | |
<p-button (click)="confirm($event)" icon="pi pi-check" [label]="translate.instant('demo.confirm')"> | |
</p-button> | |
<p-confirmPopup></p-confirmPopup> | |
</div> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} | |
} |
Here we go!


Voilà!
Thanks for the reading!
For Spanish readers: https://www.ibidemgroup.com/edu/internacionalizacion-i18n-primeng-ngx-translate/ (Translated by Chema Bescós 🙏🏻)
Repos:
94