akveo / ng2-smart-table

Angular Smart Data Table component
https://akveo.github.io/ng2-smart-table/
MIT License
1.63k stars 878 forks source link

i18n problems ? #277

Open chaouiy opened 7 years ago

chaouiy commented 7 years ago

ng2-smart-table is not compatible with translation process.

dima12qw commented 7 years ago

Any ideas with this problem? Cause I have the same issue now and I don't know how to fix it

GrigoriLomonosov commented 7 years ago

I had the same problem and found a solution:

  1. First I made global-language-event.service.ts to broadcast an event that says the language was changed.
import {Output} from "@angular/core";
import {EventEmitter} from "@angular/common/src/facade/async";

export class GlobalLanguageEventService {

  @Output()
  languageChanged: EventEmitter<string> = new EventEmitter<string>();

  constructor() {}

  public setLanguage(lang: string){
    this.languageChanged.emit(lang);
  }
}
  1. In the navigationbar is where the language was changed. The navbar was coded in the NavComponent and that's where the global event was triggered.
import {Component} from '@angular/core';
import {TranslateService} from '@ngx-translate/core';
import {AuthService} from '../../../services/authentication/authentication.service';
import {GlobalLanguageEventService} from "../../../services/global-language-event.service";

@Component({
  selector: 'app-nav',
  templateUrl: 'nav.component.html',
  styleUrls: ['nav.component.css']
})
export class NavComponent {

  selectedLanguage = 'nl';

  constructor(public translate: TranslateService,
              public authService: AuthService,
              public globalEventService: GlobalLanguageEventService) {
    translate.addLangs(['en', 'nl']);
    const browserLang = translate.getBrowserLang();
    translate.use(browserLang.match(/en|nl/) ? browserLang : 'nl');
  }

  onChange(newValue) {
    this.selectedLanguage = newValue;
    this.translate.use(this.selectedLanguage);
    //BROADCAST EVENT
    this.globalEventService.setLanguage(this.selectedLanguage);
  }
}
  1. Then in the components where a smarttable was used e.g. UsersComponent, I created a function that loaded the settings of the table and a second function that set the columnheaders. Then I had the component listen to the global events triggered in the NavComponent. Then these 2 methods where called in the subscribe callback from the GlobalLanguageEventService.
import {Component, OnInit, Inject} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';

import {LocalDataSource} from 'ng2-smart-table';
import {USER_REST} from '../../../services/users/users.service';
import {TranslateService} from "@ngx-translate/core";
import {GlobalLanguageEventService} from "../../../services/global-language-event.service";

@Component({
  selector: 'app-customers',
  templateUrl: 'users.component.html',
  styleUrls: ['users.component.css']
})

export class UsersComponent implements OnInit {

  //Table-settings
  settings = {};

  //Table datasource
  source: LocalDataSource;

  //Table columnheaders
  columnheaders: string[];

  constructor(@Inject(USER_REST) private userService: any,
              private router: Router,
              private route: ActivatedRoute,
              private translationService: TranslateService,
              private globalLanguageService: GlobalLanguageEventService) {
    this.source = new LocalDataSource();
  }

  getUsers(): void {
    this.userService.getList().subscribe(users => this.source.load(users));
  }

  setColumnheaders(): void {
    //USER.FIRST_NAME,... are in the i18n file
    let firstName = 'USER.FIRST_NAME';
    let lastName = 'USER.LAST_NAME';
    let email = 'USER.EMAIL';
    this.columnheaders = ['','','']
   //Used TranslateService from @ngx-translate/core
    this.translationService.get(firstName).subscribe(label => this.columnheaders[0] = label);
    this.translationService.get(lastName).subscribe(label => this.columnheaders[1] = label);
    this.translationService.get(email).subscribe(label => {
      this.columnheaders[2] = label;
      this.loadTableSettings();
    });
  }

  loadTableSettings(): void {
    this.settings = {
      mode: 'external',
      edit: {
        editButtonContent: 'Details'
      },
      actions: {
        add: false
      },
      pager: {
        display: true,
        perPage: 3
      },
      columns: {
        firstName: {
          title: this.columnheaders[0]
        },
        lastName: {
          title: this.columnheaders[1],
          sort: true
        },
        email: {
          title: this.columnheaders[2]
        }
      }
    };
  }

  ngOnInit(): void {
    this.setColumnheaders();
   //LISTEN TO EVENTS
    this.globalLanguageService.languageChanged.subscribe(item => {
      this.setColumnheaders();
    });
    this.getUsers();
  }
  1. In the setColumnheaders function I used the TranslateService from @ngx-translate/core

Conclusion: this works for me and is quite easy to reuse for other components

edmondko commented 7 years ago

@GrigoriLomonosov Good one! I've done a similar implementation but with a loop that translates all the strings since this is not a very dynamic solution

In the Component I set the name strings:

  columnNames = ['client_name', 'client_email', 'product', 'keys', 'created', 'expires', 'type', 'period', 'plan'];

  setTableSettings(colNames) {
    let tableSettings = {
      columns: {
        reseller_name : { title: ''},
        reseller_email : {title: ''},
        product : { title: ''},
        numUsers : { title: ''},
        created : { title: ''},
        expires : { title: ''},
        period : { title: ''},
        subPeriod : { title: ''},
        plan : { title: '' }
      },
      actions: {
        add: false,
        edit: false,
        delete: false
      }
    };
    let cols = tableSettings.columns;
    let i = 0;
    for (const key of Object.keys(cols)) {
      cols[key].title = colNames[i];
      i++;
    }
    this.tableSettings = tableSettings;
  }

  setColumnHeaders() {
    let arr = [];
    for (let i = 0; i <= this.columnNames.length; i++) {
      this.translate.get('columns.' +  this.columnNames[i]).map((label) => {
        arr.push(label);
      }).subscribe(() => {
        this.setTableSettings(arr);
      });
    }
  }

  ngOnInit() {
    this.setColumnHeaders();
  }
Newan commented 6 years ago

little bit faster solution:

 ......
    for (const column in tableSettings.columns) {
      if (tableSettings.columns.hasOwnProperty(column)) {
        tableSettings.columns[column].title = colNames[column];
      }
    }
    this.tableSettings = tableSettings;

  }

  setColumnHeaders() {
    this.translate.get(this.columnNames).subscribe(res => {
      this.setTableSettings(res);

    });
  }

edit: tableSettings.actions.columnTitle don´t update after first render

rahul0698 commented 5 years ago

I have found a way to counter this issue.

import * as _ from "lodash";
tableSettings = {
actions: {
add: false,
edit: false,
delete: false
},
columns:  {
id: {
title: "TABLE.COLUMN.ID"  // your translation file key
},
status: {
title: "TABLE.COLUMN.STATUS"
}
}
constructor() {
_.each(this.tableSettings.columns, (column) => {
this.translate.get(column.title).subscribe(res => {
column.title = res;
});
})
}
hkkhchan commented 3 years ago

:) I do the similar stuff. but I pefer directly type them in the component.

  ngOnInit(){
    this.initSetting();
    this.trans.onLangChange.subscribe(e=>{ //this.trans = TranslateService 
      this.initSetting();
    });
  }

initSetting(){
    let settings:any = {
      add: {
        addButtonContent: '<i class="nb-plus"></i>',
        createButtonContent: '<i class="nb-checkmark"></i>',
        cancelButtonContent: '<i class="nb-close"></i>',
      },
      edit: {
        editButtonContent: '<i class="nb-edit"></i>',
        saveButtonContent: '<i class="nb-checkmark"></i>',
        cancelButtonContent: '<i class="nb-close"></i>',
      },
      delete: {
        deleteButtonContent: '<i class="nb-trash"></i>',
        confirmDelete: true,
      }
    };
    if (this.trans.currentLang == 'tc'){
      settings.columns = {
        id: { title: 'id', type: 'number' },
        cname: { title: '名稱', type: 'string' },
        cat: { title: '類別', type: 'string' },
        price: { title: '價錢', type: 'number' }
      }
    } else {
      settings.columns = {
        id: { title: 'id', type: 'number' },
        cname: { title: 'Name', type: 'string'},
        cat: { title: 'Category', type: 'string' },
        price: { title: 'Price', type: 'number' }
      }
    }
    this.settings = settings;
  }
hanalice commented 3 years ago

but how can I tarnalate pagination display? for example:per:20