如何在 Angular 4 中翻译 mat-paginator?

Posted

技术标签:

【中文标题】如何在 Angular 4 中翻译 mat-paginator?【英文标题】:How to translate mat-paginator in Angular 4? 【发布时间】:2018-05-15 13:50:37 【问题描述】:

您知道如何翻译 Angular 的 mat-paginator 标记中的“每页项目数”吗? mat-paginator 是 Material Design 中的一个元素。

【问题讨论】:

【参考方案1】:

您可以为此使用MatPaginatorIntl。 Will Showell made 一个不再有效的示例,所以这里有一个更新版本(带有荷兰语)和分步指南。

    MatPaginatorIntl@angular/material 导入您的应用程序。 为您的语言环境创建一个新的分页器文件(在本例中我使用荷兰语)并将其导入:import getDutchPaginatorIntl from './app/dutch-paginator-intl'; in main.ts 文件 在 main.ts 文件中为 Paginator 设置一个 provider,以便它采用本地文件的翻译(而不是英语作为默认语言):
providers: [
    provide: MatPaginatorIntl, useValue: getDutchPaginatorIntl() 
]
    在您的 paginator-intl 文件中,为可以翻译的字符串设置标签并导出这些标签。该文件最重要的部分(有关详细信息,请参阅示例):
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 以分页器翻译文件为起点。


2018 年 6 月 - 更新到 Angular 6.x 这个更新的Example on StackBlitz 升级到 Angular 6.x 以适应最新版本的框架。只有包发生了变化,分页器内部没有任何变化。


2019 年 6 月 - 更新到 Angular 8.x 这个更新的Example on StackBlitz 升级到 Angular 8.x 以适应最新版本的框架。只有包发生了变化,分页器内部没有任何变化。


2020 年 2 月 - 更新到 Angular 9.x 这个更新的Example on StackBlitz 升级到 Angular 9.x 以适应最新版本的框架。软件包版本已更改。主要变化是从 Angular Material 导入的方式。您不能再从 Material 根目录导入。您需要从模块 (material/paginator) 本身指定导入:

import  MatPaginatorModule, MatPaginatorIntl  from '@angular/material/paginator';

2020 年 6 月 - 更新到 Angular 10.x 这个更新的Example on StackBlitz 升级到 Angular 10.x 以适应最新版本的框架。只有包发生了变化,分页器内部没有任何变化。


2020 年 12 月 - 更新到 Angular 11.x 这个更新的Example on StackBlitz 升级到 Angular 11.x 以适应最新版本的框架。只有包发生了变化,分页器内部没有任何变化。


2021 年 5 月 - 更新到 Angular 12.x 这个更新的Example on StackBlitz 升级到 Angular 12.x 以适应最新版本的框架。只有包发生了变化,分页器内部没有任何变化。

【讨论】:

对于一些翻译字符串来说有点复杂,但它可以工作,谢谢 国际化对我来说非常有效,但它仍然以大写显示工具提示的值?我不知道为什么会这样? 是的,但是您如何将它与 TranslateService 一起使用,这可能是最常见的用例 我相信你打错了;最新更新中的 19.x 应该是 10.x。 年复一年,从 6 到 10 角,你应该得到超过 123 个赞:D【参考方案2】:

要获得快速而肮脏的解决方案,请使用 this.paginator._intl 属性。

在我的...component.ts 我有:

@ViewChild(MatPaginator) paginator: MatPaginator;

ngOnInit() 
  ...
  this.paginator._intl.itemsPerPageLabel = 'My translation for items per page.';
  ...

【讨论】:

在使用这种方法时,我们如何翻译'of'? "31-60 0f 20000" 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; ; 这将在您在使用分页器的所有其他组件中触发后被调用【参考方案3】:

根据@ngx-translate 接受的答案修改解决方案(使用 Angular 6):

@NgModule(
  imports: [...],
  providers: [
    
      provide: MatPaginatorIntl, deps: [TranslateService],
      useFactory: (translateService: TranslateService) => new PaginatorI18n(translateService).getPaginatorIntl()
    
  ]
)
export class CoreModule 

还有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 );
    

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"
  

app.module.ts中配置ngx-translate

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  

【讨论】:

唯一提出动态翻译的解决方案 - 这是您应该想要的方式。这应该是公认的答案。 @MichalStepan 我同意,通过我多次尝试让它在 StackBlitz 上运行,但他们还不接受静态资产。见github.com/stackblitz/core/issues/577 @puntanet 我已经更新了答案,请看最底部。然后cz.json 位于src/assets/i18n 下。 这个答案很好,但是当语言改变时它不会更新翻译。与其在getPaginatorIntl 中返回对象,不如让类扩展MatPaginatorIntl 并返回对象本身。还需要调用this.changes.next() 来刷新现有表。查看其他帖子***.com/questions/46869616/… 为了解释语言切换,我使用了this.translate.stream(),它在每次语言更改时报告一个新值。【参考方案4】:
this.dataSource.paginator._intl.itemsPerPageLabel = "Your string here";

这在最新的 angular8 + material8 中有效;

【讨论】:

【参考方案5】:

您可以破解到MatPaginator._intl 并使用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;
);

【讨论】:

【参考方案6】:

对于 Angular 9.0.0,如果你使用的是 i18n 包,你可以这样做

要求:ng add @angular/localization

创建一个名为 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

导入到 app.modudle.ts

import  MatPaginatorIntl  from '@angular/material/paginator'
import  MyPaginatorIntl  from './shared/paginator-int/my-paginator-intl'

@NgModule(
    providers: [
         provide: MatPaginatorIntl, useValue: MyPaginatorIntl() ,
    ]
)

将以下内容复制到您的语言 xlf 文件中

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

【讨论】:

【参考方案7】:

按照当前的 Angular Material 文档 (10.2.0) 修改显示的标签和文本,创建 MatPaginatorIntl 的新实例并将其包含在自定义提供程序中。您必须导入 MatPaginatorModule(无论如何您都需要它来显示分页器组件)

import  MatPaginatorModule  from '@angular/material/paginator';

在您的组件中(您使用分页器的地方)您可以通过以下方式使用它:

 constructor(private paginator: MatPaginatorIntl) 
    paginator.itemsPerPageLabel = 'Your custom text goes here'; 

【讨论】:

【参考方案8】:

更改 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;

【讨论】:

【参考方案9】:

我以Felix' answers 为基础,他以Roy's answer 为基础。

考虑到动态语言切换,我的工厂方法使用TranslateServicestream() 方法(而不是instance()),该方法返回一个每次设置语言时触发的可观察对象。我还打电话给分页器的change.next() 强制重绘。

TranslateService 能够返回词汇的“字典”。使用 JSON 文件中的正确键,Object.assign() 可以完成大部分工作。

最后,我没有重新实现分页器的getRangeLabel()。相反,我采用旧值并将出现的“of”替换为翻译文本。

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;

这里以fr.json 为例。


    "paginator": 
        "paginatorIntl" : 
            "itemsPerPageLabel": "Items par page",
            "nextPageLabel": "Page suivante",
            "previousPageLabel": "Page précédente",
            "firstPageLabel": "Première page",
            "lastPageLabel": "Dernière page"
        ,
        "of": "de"
    

【讨论】:

【参考方案10】:

使用 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;

【讨论】:

这是一个断章取义的 sn-p。没有上下文,没有完整的类定义,也没有如何使用它的示例。【参考方案11】:

@Felix 答案的另一个版本,但在这里您可以直接在函数中注入您的服务,而无需创建或实例化一个类:

app.module.ts 添加您的提供商:

providers: [
    YourCustomService,
    provide: MatPaginatorIntl, useFactory: getPaginatorI18n, deps: [YourCustomService]
  ]

使用您的函数创建一个新的 ts 文件(例如 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;

【讨论】:

【参考方案12】:

如果你想动态改变语言,你可以输入这个代码:

    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`;
    

它是 import insert 'changes.next();'对象 matPaginatorIntl 编辑后。

【讨论】:

以上是关于如何在 Angular 4 中翻译 mat-paginator?的主要内容,如果未能解决你的问题,请参考以下文章

如何最好地组织角度翻译中的翻译字符串?

翻译对比Angular1和Angular2中的依赖注入

Angular 5 - 在 TypeScript 中翻译字符串

如何用管道翻译 Ionic/Angular 中 *ngFor 循环的返回

在混合 AngularJS/Angular 5 应用程序中重用 *.resx(AngularJS) 翻译文件

(翻译)Angular 1.3中的验证器管道