DEV Community

Cover image for PrimeNG I18N API Usage with ngx-translate
Yiğit FINDIKLI
Yiğit FINDIKLI

Posted on • Edited on

16 2 2

PrimeNG I18N API Usage with ngx-translate

How can we use PrimeNG I18N with ngx-translate? Let's start!

Project Setup

Let's create a brand new angular application using angular-cli.



ng new primeng-i18n-with-ngx
cd primeng-i18n-with-ngx


Enter fullscreen mode Exit fullscreen mode

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


Enter fullscreen mode Exit fullscreen mode

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


Enter fullscreen mode Exit fullscreen mode

Now we need a couple of PrimeNG components and ngx-translate setup.

Note: Detailed ngx-translate setup can be found in official docs.

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 { }
view raw app.module.ts hosted with ❤ by GitHub

I want to use English to French translation because ngx-translation uses in their example.

Let's create our translation JSON files. The path should be like this:
structure

en.json:

{
"demo": {
"greetings": "Hello!",
"en": "English",
"fr": "French"
}
}
view raw en.json hosted with ❤ by GitHub

fr.json:

{
"demo": {
"greetings": "Bonjour!",
"en": "Anglaise",
"fr": "Français"
}
}
view raw fr.json hosted with ❤ by GitHub

Let's create our translation logic! We gonna use TranslateService and translate pipe for the general translation functionality for the translation.

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);
}
}

Alright, let's try it!
English
French

It's cool, right?

We need to use PrimeNGConfig for the translationing the PrimeNG components. Usage is quite simple.

Usage from the Documentation:

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:

{
"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"
]
}
}
view raw en.json hosted with ❤ by GitHub
{
"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"
]
}
}
view raw fr.json hosted with ❤ by GitHub

Note: "primeng" usage just an example.

Let's create our Calendar.

<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.

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:

{
"dayNamesMin": [
"Su",
"Mo",
"Tu",
"We",
"Th",
"Fr",
"Sa"
],
"monthNames": [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
]
}
view raw data-object hosted with ❤ by GitHub

We just binding our translation data to PrimeNGConfig with setTranslation function. And Voilà! Our calendar translated!

date

la-datte

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.

{
"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"
}
}
view raw en.json hosted with ❤ by GitHub
{
"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"
}
}
view raw fr.json hosted with ❤ by GitHub

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!

<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>
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!

en-full

fr-full

Voilà!

Thanks for the reading!

For Spanish readers: https://www.ibidemgroup.com/edu/internacionalizacion-i18n-primeng-ngx-translate/ (Translated by Chema Bescós 🙏🏻)

Repos:

Retry later

Top comments (0)

Retry later
Retry later