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.

- 7,811
- 4
- 24
- 47

- 1,137
- 3
- 13
- 20
14 Answers
You can use the MatPaginatorIntl
for this. Will Howell made an example that no longer works, so here is an updated version (with Dutch) and step-by-step guidance.
- Import the
MatPaginatorIntl
from@angular/material
into your application. - Create a new paginator file for your locale (in this example I use Dutch) and import that:
import { getDutchPaginatorIntl } from './app/dutch-paginator-intl';
inmain.ts
file - Set a
provider
for the Paginator inside of themain.ts
file, so it takes the translations of your local file (instead of English as default language):
providers: [
{ provide: MatPaginatorIntl, useValue: getDutchPaginatorIntl() }
]
- Inside your paginator-intl file, set the labels for the strings that can be translated and export these. Most important part of that file (see the example for more info):
paginatorIntl.itemsPerPageLabel = 'Items per pagina:';
paginatorIntl.firstPageLabel = 'Eerste pagina';
paginatorIntl.previousPageLabel = 'Vorige pagina';
paginatorIntl.nextPageLabel = 'Volgende pagina';
paginatorIntl.lastPageLabel = 'Laatste pagina';
paginatorIntl.getRangeLabel = dutchRangeLabel;
Example on StackBlitz with the paginator translations file as starting point.
June 2018 - Update to Angular 6.x
This updated Example on StackBlitz is upgraded to Angular 6.x to accommodate the latest version of the framework. Only packages have changed, nothing inside the paginator has changed.
June 2019 - Update to Angular 8.x
This updated Example on StackBlitz is upgraded to Angular 8.x to accommodate the latest version of the framework. Only packages have changed, nothing inside the paginator has changed.
February 2020 - Update to Angular 9.x
This updated Example on StackBlitz is upgraded to Angular 9.x to accommodate the latest version of the framework. Package versions have changed. Major change is the way to import from Angular Material. You cannot import from Material root anymore. You need to specify the import from the module (material/paginator
) itself:
import { MatPaginatorModule, MatPaginatorIntl } from '@angular/material/paginator';
June 2020 - Update to Angular 10.x
This updated Example on StackBlitz is upgraded to Angular 10.x to accommodate the latest version of the framework. Only packages have changed, nothing inside the paginator has changed.
December 2020 - Update to Angular 11.x
This updated Example on StackBlitz is upgraded to Angular 11.x to accommodate the latest version of the framework. Only packages have changed, nothing inside the paginator has changed.
May 2021 - Update to Angular 12.x
This updated Example on StackBlitz is upgraded to Angular 12.x to accommodate the latest version of the framework. Only packages have changed, nothing inside the paginator has changed.
January 2022 - Update to Angular 13.x
This updated Example on StackBlitz is upgraded to Angular 13.x to accommodate the latest version of the framework. Only packages have changed, nothing inside the paginator has changed.
June 2022 - Update to Angular 14.x
This updated Example on StackBlitz is upgraded to Angular 14.x to accommodate the latest version of the framework. Only packages have changed, nothing inside the paginator has changed.
November 2022 - Update to Angular 15.x
This updated Example on StackBlitz is upgraded to Angular 15.x to accommodate the latest version of the framework. Only packages have changed, nothing inside the paginator has changed.

- 7,811
- 4
- 24
- 47
-
4a bit complicated for a few translation strings but it works thanks – Ruben May 14 '18 at 09:09
-
The internationalization it worked perfectly for me, but its still showing values of tooltip in uppercase? I dont know why its happening? – Talk is Cheap Show me Code Jun 09 '18 at 12:43
-
7Yeah, but how would you use this with a TranslateService, which is probably the most common use case – Kai Schneider Aug 16 '18 at 09:28
-
I believe you've made a typo; 19.x in your newest update should probably be 10.x. – Luctia Jul 22 '20 at 20:47
-
There is still a small issue out there. You can't translate the word `van` – k.vincent Oct 29 '20 at 10:39
-
1Year afteryear, from angular 6-10 you deserve over 123 upvotes :D – TLVF2627 Oct 04 '21 at 13:05
-
Regarding the example codes: how could the pageSize be 0? – pihentagy Aug 23 '22 at 08:20
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 { }

- 31,141
- 6
- 88
- 120

- 3,999
- 3
- 42
- 66
-
13The only solution that propose dynamic translations - which is the way you should want it. This should be the accepted answer. – Michal Stepan Oct 11 '18 at 10:00
-
@MichalStepan I agree, through I tried to make it work on StackBlitz several times, but they're not accepting static assets yet. See https://github.com/stackblitz/core/issues/577 – Roy Oct 20 '18 at 15:03
-
@puntanet I have update the answer, see the very bottom. The `cz.json` is then located under `src/assets/i18n`. – Felix Nov 23 '18 at 15:12
-
9This answer is good but it doesn't update the translations when the language is changed. Instead of returning the object in `getPaginatorIntl` it is better to make the class extend `MatPaginatorIntl` and return the object itself. It is also necessary to call `this.changes.next()` for existing tables to be refreshed. Check out this other post https://stackoverflow.com/questions/46869616/how-to-use-matpaginatorintl – iberbeu Dec 06 '18 at 11:22
-
To account for language switch, I used `this.translate.stream()` that reports a new value each time language changed. – Ahmad Shahwan Apr 29 '21 at 12:52
-
-
as @iberbeu said, to i used another response from this post https://stackoverflow.com/a/49532776/1977459 – bilelz Jul 12 '23 at 10:02
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.';
...
}

- 5,966
- 2
- 28
- 31
-
when using this method, how can we translate 'of'? "31-60 0f 20000" – Peyman Kheiri Mar 25 '20 at 16:35
-
1`this.paginator._intl.getRangeLabel = (page: number, pageSize: number, length: number) => { if (length == 0 || pageSize == 0) { return `0 din ${length}`; } length = Math.max(length, 0); const startIndex = page * pageSize; const endIndex = startIndex < length ? Math.min(startIndex + pageSize, length) : startIndex + pageSize; return `${startIndex + 1} - ${endIndex} **of** ${length}`; };` – GoTo Mar 26 '20 at 19:38
-
this will get called after you fire it in every other compoent which uses paginator – Mohit Harshan Jul 30 '20 at 05:06
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>
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;
});

- 4,083
- 6
- 28
- 58
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"
}
}

- 1,662
- 18
- 29
this.dataSource.paginator._intl.itemsPerPageLabel = "Your string here";
this worked in latest angular8 + material8;

- 1,077
- 2
- 12
- 19
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;
}

- 11
- 1
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;
}

- 1,452
- 1
- 17
- 30
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';
}

- 205
- 3
- 14
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;
}

- 121
- 1
- 2
-
1This is an out of context snippet. No context, no full class definition and no example how to use it. – Ya. Jul 22 '21 at 13:08
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.
If you use transloco and you need to translate mat-paginator
strings, add this typescript class to your project:
import { Injectable } from '@angular/core';
import { TranslocoService } from '@ngneat/transloco';
import { MatPaginatorIntl } from '@angular/material/paginator';
@Injectable()
export class CustomMatPaginatorIntl extends MatPaginatorIntl {
ofLabel: string = 'of';
constructor(private _translate: TranslocoService) {
super();
this._translate.langChanges$.subscribe((lang) => {
this.getAndInitTranslations();
});
this.getAndInitTranslations();
}
getAndInitTranslations(): void {
this._translate.selectTranslate('paginator.itemsPerPageLabel').subscribe((value) => {
this.itemsPerPageLabel = value;
this.changes.next();
});
this._translate.selectTranslate('paginator.nextPageLabel').subscribe((value) => {
this.nextPageLabel = value;
this.changes.next();
});
this._translate.selectTranslate('paginator.previousPageLabel').subscribe((value) => {
this.previousPageLabel = value;
this.changes.next();
});
this._translate.selectTranslate('paginator.firstPageLabel').subscribe((value) => {
this.firstPageLabel = value;
this.changes.next();
});
this._translate.selectTranslate('paginator.lastPageLabel').subscribe((value) => {
this.lastPageLabel = value;
this.changes.next();
});
this._translate.selectTranslate('paginator.ofLabel').subscribe((value) => {
this.ofLabel = value;
this.changes.next();
});
}
getRangeLabel = (
page: number,
pageSize: number,
length: number,
): string => {
if (length === 0 || pageSize === 0) {
return `0 ${this.ofLabel} ${length}`;
}
length = Math.max(length, 0);
const startIndex = page * pageSize;
const endIndex =
startIndex < length
? Math.min(startIndex + pageSize, length)
: startIndex + pageSize;
return `${startIndex + 1} - ${endIndex} ${
this.ofLabel
} ${length}`;
};
}
Then in your Module
call it like this:
@NgModule({
imports: [
...
TranslocoModule,
],
providers: [
{ provide: MatPaginatorIntl, useClass: CustomMatPaginatorIntl } // >> add this line
]
})

- 5,353
- 1
- 35
- 38
Local solution for ES internationalization (just change the values for the labels with the corresponding ones in your language), super direct and without touching the app.moulde:
import { MatPaginatorIntl } from '@angular/material/paginator';
...
constructor(
...
private paginator: MatPaginatorIntl
) {
paginator.nextPageLabel = 'Siguiente';
paginator.previousPageLabel = 'Anterior';
paginator.lastPageLabel = 'Última Página';
paginator.firstPageLabel = 'Primera Página';
paginator.itemsPerPageLabel = 'Registros por Página';
paginator.getRangeLabel = (page: number, pageSize: number, length: number) => {
if (length == 0 || pageSize == 0) { return `0 de ${length}`; }
length = Math.max(length, 0);
const startIndex = page * pageSize;
const endIndex = startIndex < length ? Math.min(startIndex + pageSize, length) : startIndex + pageSize;
return `${startIndex + 1} - ${endIndex} de ${length}`;
};
}

- 439
- 2
- 7