'How to translate mat-paginator in Angular 4?
Do you have any ideas how can I translate "Items per page" in Angular's mat-paginator tag? The mat-paginator is an element from Material Design.
Solution 1:[1]
Modified solution (with Angular 6) based on accepted answer with @ngx-translate:
@NgModule({
imports: [...],
providers: [
{
provide: MatPaginatorIntl, deps: [TranslateService],
useFactory: (translateService: TranslateService) => new PaginatorI18n(translateService).getPaginatorIntl()
}
]
})
export class CoreModule {}
And the PaginatorI18n:
import { MatPaginatorIntl } from '@angular/material';
import { TranslateService } from '@ngx-translate/core';
export class PaginatorI18n {
constructor(private readonly translate: TranslateService) {}
getPaginatorIntl(): MatPaginatorIntl {
const paginatorIntl = new MatPaginatorIntl();
paginatorIntl.itemsPerPageLabel = this.translate.instant('ITEMS_PER_PAGE_LABEL');
paginatorIntl.nextPageLabel = this.translate.instant('NEXT_PAGE_LABEL');
paginatorIntl.previousPageLabel = this.translate.instant('PREVIOUS_PAGE_LABEL');
paginatorIntl.firstPageLabel = this.translate.instant('FIRST_PAGE_LABEL');
paginatorIntl.lastPageLabel = this.translate.instant('LAST_PAGE_LABEL');
paginatorIntl.getRangeLabel = this.getRangeLabel.bind(this);
return paginatorIntl;
}
private getRangeLabel(page: number, pageSize: number, length: number): string {
if (length === 0 || pageSize === 0) {
return this.translate.instant('RANGE_PAGE_LABEL_1', { length });
}
length = Math.max(length, 0);
const startIndex = page * pageSize;
// If the start index exceeds the list length, do not try and fix the end index to the end.
const endIndex = startIndex < length ? Math.min(startIndex + pageSize, length) : startIndex + pageSize;
return this.translate.instant('RANGE_PAGE_LABEL_2', { startIndex: startIndex + 1, endIndex, length });
}
}
and cz.json
{
"ITEMS_PER_PAGE_LABEL": "Po?et ?ádk?:",
"NEXT_PAGE_LABEL": "Další stránka",
"PREVIOUS_PAGE_LABEL": "P?edchozí stránka",
"FIRST_PAGE_LABEL": "První stránka",
"LAST_PAGE_LABEL": "Poslední stránka",
"RANGE_PAGE_LABEL_1": "0 z {{length}}",
"RANGE_PAGE_LABEL_2": "{{startIndex}} - {{endIndex}} z {{length}}"
}
Configure ngx-translate in app.module.ts:
import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core';
const httpLoaderFactory = (http: HttpClient) => new TranslateHttpLoader(http, './assets/i18n/', '.json');
@NgModule({
imports: [
TranslateModule.forRoot({
loader: { provide: TranslateLoader, useFactory: httpLoaderFactory, deps: [HttpClient] }
})
],
providers: [{ provide: LOCALE_ID, useValue: 'cs' }],
bootstrap: [AppComponent]
})
export class AppModule { }
Solution 2:[2]
For a quick and dirty solution use this.paginator._intl property.
In my ...component.ts I have:
@ViewChild(MatPaginator) paginator: MatPaginator;
ngOnInit() {
...
this.paginator._intl.itemsPerPageLabel = 'My translation for items per page.';
...
}
Solution 3:[3]
For angular 9.0.0, if you are using i18n package, you can do
require: ng add @angular/localization
Create a file called my-paginator-intl.ts
import { MatPaginatorIntl } from '@angular/material/paginator'
const matRangeLabelIntl = (page: number, pageSize: number, length: number) => {
if (length === 0 || pageSize === 0) {
return $localize`:@@paginator.zeroRange:0 in ${length}`
}
length = Math.max(length, 0)
const startIndex = page * pageSize
// If the start index exceeds the list length, do not try and fix the end index to the end.
const endIndex = startIndex < length ? Math.min(startIndex + pageSize, length) : startIndex + pageSize
return $localize`:@@paginator.rangeOfLabel:${startIndex + 1} - ${endIndex} in ${length}`
}
export function MyPaginatorIntl() {
const paginatorIntl = new MatPaginatorIntl()
paginatorIntl.itemsPerPageLabel = $localize`:@@paginator.displayPerPage:Items per page`
paginatorIntl.nextPageLabel = $localize`:@@paginator.nextPage:Next page`
paginatorIntl.previousPageLabel = $localize`:@@paginator.prevPage:Prev page`
paginatorIntl.getRangeLabel = matRangeLabelIntl
return paginatorIntl
}
Import to app.modudle.ts
import { MatPaginatorIntl } from '@angular/material/paginator'
import { MyPaginatorIntl } from './shared/paginator-int/my-paginator-intl'
@NgModule({
providers: [
{ provide: MatPaginatorIntl, useValue: MyPaginatorIntl() },
]
})
Copy following to your language xlf file
<trans-unit id="paginator.zeroRange">
<source>0 of <x id="PH" /></source>
<target>0 trong <x id="PH" /></target>
</trans-unit>
<trans-unit id="paginator.rangeOfLabel">
<source><x id="PH" /> - <x id="PH_1" /> of <x id="PH_2" /></source>
<target><x id="PH" /> - <x id="PH_1" /> trong <x id="PH_2" /></target>
</trans-unit>
<trans-unit id="paginator.displayPerPage">
<source>Items per page</source>
<target>Hi?n th?/Trang</target>
</trans-unit>
<trans-unit id="paginator.nextPage">
<source>Next page</source>
<target>Trang k?</target>
</trans-unit>
<trans-unit id="paginator.prevPage">
<source>Prev page</source>
<target>Trang tr??c</target>
</trans-unit>
Solution 4:[4]
You can hack your way into MatPaginator._intl and put your string there using ngx-translate.
forkJoin({
itemsPerPageLabel: this.translate.get('paginator.itemsPerPageLabel'),
nextPageLabel: this.translate.get('paginator.nextPageLabel'),
previousPageLabel: this.translate.get('paginator.previousPageLabel'),
firstPageLabel: this.translate.get('paginator.firstPageLabel'),
lastPageLabel: this.translate.get('paginator.lastPageLabel'),
}).subscribe(values => {
this.paginator._intl.itemsPerPageLabel = values.itemsPerPageLabel;
this.paginator._intl.nextPageLabel = values.nextPageLabel;
this.paginator._intl.previousPageLabel = values.previousPageLabel;
this.paginator._intl.firstPageLabel = values.firstPageLabel;
this.paginator._intl.lastPageLabel = values.lastPageLabel;
// 1 – 10 of 100
// https://github.com/angular/components/blob/master/src/material/paginator/paginator-intl.ts#L41
this.paginator._intl.getRangeLabel = (page: number, pageSize: number, length: number): string => {
length = Math.max(length, 0);
const startIndex = page * pageSize;
const endIndex = startIndex < length ? Math.min(startIndex + pageSize, length) : startIndex + pageSize;
return this.translate.instant('paginator.getRangeLabel', {
startIndex: startIndex + 1,
endIndex,
length,
});
};
// Otherwise, the paginator won't be shown as translated.
this.dataSource.paginator = this.paginator;
});
Solution 5:[5]
I build on Felix' answers, who builds on Roy's answer.
To account for dynamic language switch, my factory method uses TranslateService's stream() method (instead of instance()) that returns an observable that fires each time language is set. I also call paginator's change.next() to force redraw.
TranslateService is able to return a "dictionary" of vocabularies. With the right keys in the JSON file, Object.assign() can do most of the job.
Finally, I do not re-implement paginator's getRangeLabel(). Rather I take the old value and replace occurrences of "of" with translated text.
public getPaginatorIntl(): MatPaginatorIntl {
const paginatorIntl = new MatPaginatorIntl();
this.translation.stream('paginator.paginatorIntl').subscribe(dict => {
Object.assign(paginatorIntl, dict);
paginatorIntl.changes.next();
});
const originalGetRangeLabel = paginatorIntl.getRangeLabel;
paginatorIntl.getRangeLabel = (page: number, size: number, len: number) => {
return originalGetRangeLabel(page, size, len)
.replace('of', this.translation.instant('paginator.of'));
};
return paginatorIntl;
}
Here is the fr.json for example.
{
"paginator": {
"paginatorIntl" : {
"itemsPerPageLabel": "Items par page",
"nextPageLabel": "Page suivante",
"previousPageLabel": "Page précédente",
"firstPageLabel": "Première page",
"lastPageLabel": "Dernière page"
},
"of": "de"
}
}
Solution 6:[6]
this.dataSource.paginator._intl.itemsPerPageLabel = "Your string here";
this worked in latest angular8 + material8;
Solution 7:[7]
Another version of @Felix's answer, but here you inject your service directly in the function without the need to make or instantiate a class:
In app.module.ts Add your provider:
providers: [
YourCustomService,
{provide: MatPaginatorIntl, useFactory: getPaginatorI18n, deps: [YourCustomService]}
]
Create a new ts file with your function (Example paginator-i18n.ts):
import {MatPaginatorIntl} from '@angular/material/paginator';
// This is the word that shows up in the range label
let paginPerRng = '';
const i18nRangeLabel = (page: number, pageSize: number, length: number) => {
if (length == 0 || pageSize == 0) {
return `0 ${paginPerRng} ${length}`;
}
length = Math.max(length, 0);
const startIndex = page * pageSize;
// If the start index exceeds the list length, do not try and fix the end index to the end.
const endIndex = startIndex < length ?
Math.min(startIndex + pageSize, length) :
startIndex + pageSize;
return `${startIndex + 1} - ${endIndex} ${paginPerRng} ${length}`;
};
export function getPaginatorI18n(YourCustomService: customService) {
const paginatorIntl = new MatPaginatorIntl();
// Call the localization methods in your service
paginatorIntl.itemsPerPageLabel = customService.getResource(...);
paginatorIntl.nextPageLabel = customService.getResource(...);
paginatorIntl.previousPageLabel = customService.getResource(...);
paginatorIntl.firstPageLabel = customService.getResource(...);
paginatorIntl.lastPageLabel = customService.getResource(...);
// We localize the word that shows up in the range label before calling the RangeLabel constant
paginPerRng = customService.getResource(...);
paginatorIntl.getRangeLabel = i18nRangeLabel;
return paginatorIntl;
}
Solution 8:[8]
Following the current Angular Material documentation (10.2.0) to modify the labels and text displayed, create a new instance of MatPaginatorIntl and include it in a custom provider. You have to import MatPaginatorModule (you would need it anyway to display paginator component)
import { MatPaginatorModule } from '@angular/material/paginator';
and in your component (where you are using paginator) you could use it in following way:
constructor(private paginator: MatPaginatorIntl) {
paginator.itemsPerPageLabel = 'Your custom text goes here';
}
Solution 9:[9]
A laconic solution to change all labels of MatPaginator.
const rangeLabel: string = '??';
const itemsPerPageLabel: string = '???????i? ?? ????i??i:';
const firstPageLabel: string = '????? ????????';
const lastPageLabel: string = '??????? ????????';
const previousPageLabel: string = '????????? ????????';
const nextPageLabel: string = '???????? ????????';
const getRangeLabel: (page: number, pageSize: number, length: number) => string = (
page: number,
pageSize: number,
length: number
): string => {
return new MatPaginatorIntl().getRangeLabel(page, pageSize, length).replace(/[a-z]+/i, rangeLabel);
};
export function getPaginatorIntl(): MatPaginatorIntl {
const paginatorIntl: MatPaginatorIntl = new MatPaginatorIntl();
paginatorIntl.itemsPerPageLabel = itemsPerPageLabel;
paginatorIntl.firstPageLabel = firstPageLabel;
paginatorIntl.lastPageLabel = lastPageLabel;
paginatorIntl.previousPageLabel = previousPageLabel;
paginatorIntl.nextPageLabel = nextPageLabel;
paginatorIntl.getRangeLabel = getRangeLabel;
return paginatorIntl;
}
Solution 10:[10]
A simple solution using ngx-translate.
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
constructor(private translate: TranslateService){}
ngOnInit() {
this.translatePaginator();
}
async translatePaginator() {
const label = await this.translate.get('COMMON.ItemsPerPageLabel').toPromise();
this.paginator._intl.itemsPerPageLabel = label;
}
Solution 11:[11]
If you want to change dynamically the languange, you can enter this code:
this.translate.onLangChange.subscribe(() => {
this.getPaginatorIntl(matPaginatorIntl);
});
private getPaginatorIntl(matPaginatorIntl: MatPaginatorIntl): void {
matPaginatorIntl.itemsPerPageLabel = this.translate.instant('PAGINATOR.ITEM');
matPaginatorIntl.nextPageLabel = this.translate.instant('PAGINATOR.NEXT_PAGE');
matPaginatorIntl.previousPageLabel = this.translate.instant('PAGINATOR.PREVIOUS_PAGE');
matPaginatorIntl.firstPageLabel = this.translate.instant('PAGINATOR.FIRST_PAGE');
matPaginatorIntl.lastPageLabel = this.translate.instant('PAGINATOR.LAST_PAGE');
matPaginatorIntl.getRangeLabel = this.getRangeLabel.bind(this);
matPaginatorIntl.changes.next();
}
private getRangeLabel(page: number, pageSize: number, length: number): string {
if (length === 0 || pageSize === 0) {
return `0 ${this.translate.instant('PAGINATOR.OF')} ${ length }`;
}
length = Math.max(length, 0);
const startIndex = page * pageSize;
// If the start index exceeds the list length, do not try and fix the end index to the end.
const endIndex = startIndex < length ? Math.min(startIndex + pageSize, length) : startIndex + pageSize;
return `${startIndex + 1} - ${endIndex} ${this.translate.instant('PAGINATOR.OF')} ${length}`;
}
It's import insert 'changes.next();' after the edit of the object matPaginatorIntl.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
