valor-software / ngx-bootstrap

Fast and reliable Bootstrap widgets in Angular (supports Ivy engine)
https://valor-software.com/ngx-bootstrap
MIT License
5.53k stars 1.69k forks source link

feat(datepicker): add regional settings #455

Closed johanchouquet closed 7 years ago

johanchouquet commented 8 years ago

Hi,

I'm not sure this is actually an issue. But I didn't find a way of setting regional configuration on the datepicker component. I'd like to use it in french projects for example, and all labels are set in english.

Is there a way of doing that ? I see that the datepicker is inspired by the jquery.ui datepicker component, which allows that.

valorkin commented 8 years ago

need to check

johanchouquet commented 8 years ago

Thanks @valorkin . As soon as it's possible, it'd be used in my project !

To get the right format (french way) of the date, for the time being, i tried to use a custom pipe, as suggested on github elsewhere, but it doesn't work neither for the time being :

import {Pipe, PipeTransform} from "angular2/core";
import {DateFormatter} from 'angular2/src/facade/intl';

@Pipe({name: 'dateFormat'})
export class DateFormatPipe implements PipeTransform {
  transform(value: any, args: string[]): any {
    if (value) {
      var date = value instanceof Date ? value : new Date(value);
      return DateFormatter.format(date, 'fr', 'dd/MM/yyyy');
    }
  }
}

Then, I import this class in my Component, and use the custom pipe in the template.

I think that my locale might be wrong, or i don't know yet.

valorkin commented 8 years ago

most probably, check your browser settings

johanchouquet commented 8 years ago

Thanks @valorkin . But my browser settings are OK. I user Chrome 49 / 50. Everything is set to French.

My workaround for now is to add several pipes in the template : {{ getDate() | date:'d'}}/{{ getDate() | date:'MM'}}/{{ getDate() | date:'y'}}

Using Angular 2 beta 16 this outputs : 27/04/2016

A little bit ugly but that does the job.

danielle5 commented 8 years ago

@dargoan were you able to get the popup functionality working or just using inline?

johanchouquet commented 8 years ago

@danielle5, what i do to get the popup functionality is :

Template:

<i class="glyphicon glyphicon-calendar" (click)="toggleDP()"></i><br/>
jj/mm/aaaa (french format of date)
<datepicker [hidden]="!clicked"
      [(ngModel)]="dt"
      [minDate]="minDate"
      [showWeeks]="true">
 </datepicker>

Component:

public clicked:boolean = false;

  public toggleDP():boolean {
    this.clicked = !this.clicked;
    return !this.clicked;
  }

But my initial problem is not resolved, i still only have english labels. I don't find a way for setting regional configuration, with Locale or something else.

charesbast commented 8 years ago

+1 Every foreign projet will eventually need translations for the labels...

valorkin commented 8 years ago

i18n is coming, please join to follow up https://www.hamsterpad.com/chat/ng2

seeka commented 7 years ago

You can do this with "moment.js", like this :

date = moment(new Date()).format("DD/MM/YYYY");

If you want change language of datepicker :

import 'moment/locale/fr'; [...] ngOnInit() { moment.locale('fr'); } You can put what you want.

oleksandr-shynkariuk commented 7 years ago

@seeka nice one, works for me!

valorkin commented 7 years ago

@seeka same applies to next version of datepicket

wonderjar commented 7 years ago
import 'moment/locale/zh-cn';
import * as moment from 'moment';

ngOnInit(): void {
  moment.locale('zh-cn');
}

I put these codes in app.component.ts, but not working. Is this correct?

kinglionsoft commented 7 years ago

@Jar-18 I put your "moment.locale('zh-cn');" in constructor of AppModule. It works.

bigbo26 commented 7 years ago

Hi ! I try your suggestions but without success..

In my main appModule :

import * as moment from 'moment';

export class AppModule {
    constructor(){
        moment.locale('fr');
    }
}

In my StudentsComponent :

import * as moment from 'moment';

[...]

export class StudentsComponent implements OnInit {

    //config DatePicker
    public dateOptions:any = {
        formatYear: 'YYYY',
        startingDay: 1
    };

     ngOnInit() {
            let datePicker = moment(new Date());
            console.log(moment.months()); // **display months in french**
    }
}

In the template for StudentsComponent : <datepicker [(ngModel)]="datePicker" [formatYear]="dateOptions.formatYear" [startingDay]="dateOptions.startingDay" [showWeeks]="true"></datepicker>

I use SystemJs, my config is :

(function (global) {
    System.config({
        defaultJSExtensions: true,
        paths: {
            // paths serve as alias
            'npm:': 'node_modules/'
        },
        // map tells the System loader where to look for things
        map: {
            // our app is within the app folder
            app: 'app',

           'moment': 'npm:/moment/min/moment-with-locales.js',
          'ng2-bootstrap': 'npm:ng2-bootstrap/bundles/ng2-bootstrap.umd.js',
         }
        });
})(this);
seeka commented 7 years ago

@bigbo26 add

import 'moment/locale/fr';

in your appModule ?

bigbo26 commented 7 years ago

@seeka thx for your answer.

with SystemJs you can only import 'moment' : on stackoverflow

console.log(moment.months()); display months in french ...

dh-lex commented 7 years ago

@seeka which version of ng2-bootstrap are you using in which this fix works?

seeka commented 7 years ago

@dh-lex 1.1.16-9

beabri commented 7 years ago

The same as @seeka for me. My ng2-bootstrap version is 1.2.5.

seawave23 commented 7 years ago

Thanks! It works with the locale! But what would you propose for the still untranslated things like "Select year", "Today", "Apply"?

dh-lex commented 7 years ago

Thanks for the info @seeka, I wasn't able to get it working I same results similar to @bigbo26. I think its because I am wrapping the component as part of a library that I use for other apps, so I don't know that it's being created the same as it is in your use case.

@valorkin when this is completed in a release will users have the ability to pass in strings to use inside of the component for translations or pass in the locale? Also just out of curiosity, do you have an idea of when this will be included in a release?

valorkin commented 7 years ago

@dh-lex oh dude, if only I had more free time :( It would be done a long time ago

dh-lex commented 7 years ago

@valorkin I understand completely, maintaining a library of this size has to be quite the chore. I was considering attempting a PR for the functionality but I noticed this branch you have is including locale data, so maybe it's not necessary?

valorkin commented 7 years ago

:) yes, it is a new datepicker My playground preview http://valorkin.github.io/ng2-bootstrap/#/datepicker

AlexKhymenko commented 7 years ago

Trying to make it work with ngUpgrade with no success. Maybe somebody have ideas. With pure angular 2-4 works. Have the same issue as @bigbo26 . In console.log it also shows changed language.

unsafecode commented 7 years ago

Having same problem here... Wouldn't be just easier to pass locales directly to the component?

unsafecode commented 7 years ago

May have found the reason: when using webpack, there's a chance to have multiple versions of momentat the same time, due to dependencies mismatch (that was my case). Because of that, the locale you set in your code will apply to an instance of momentdifferent than the one used by ngx-bootstrap.

In this scenario, you can either make sure your version of momentand ngx-bootstrap one match, or set your webpack config as follows:

resolve: {
        alias: {
            // Freeze moment instance, to avoid multiple versions
            "moment": helpers.root("/node_modules/moment"),
        }
    },
runeabrahams1 commented 7 years ago

I've tried to do the same as @unsafecode , but for SystemJS. ... map: { ..., "moment": "bower:moment/min/moment-with-locales.min.js" }, packages: { ... , "ngx-bootstrap": { map: { moment: "bower:moment/min/moment-with-locales.min.js" } } }, meta: { moment: { format: "global" }, }

Problem is it still don't work for me. console.log(moment.months()) This gives me months in Norwegian, but the datepicker have months in english.

@valorkin Any suggestions on how to solve this or an estiamte for some "locale" options ?

edit: im using an angular hybrid project with angular@4.0.2 and ngx-bootstrap@1.6.5

sebek64 commented 7 years ago

In my opinion, this bug would be fixed by un-bundling momentjs library from ngx-bootstrap bundle, and moving it into peer dependencies. If I understand the build system correctly, this would require a change to npm-submodules (ngm) first - add moment to externals in src/ngm/models/webpack-umd.config.ts.

sebek64 commented 7 years ago

I'm willing to contribute a patch that moves momentjs into peer dependencies. But first, I need the referenced pull request in npm-submodules to be merged.

If you disagree with the proposed solution, please tell me. Fixing this bug is quite important for me in a reasonable time frame.

mahabubakram commented 7 years ago

Hi, can anyone tell me how to show date format in the De(German) format. As it would be like this When I will click the datepicker it will show month labels in different language not the english. Do I need to change any options in the datepicker to do that?

wladimar commented 7 years ago

Hi, I'm using the ng2-bootstrap DatePicker in my angular 2 Project and the users are asking for already half a year whether it is possible to change the datepicker's language to German. I was waiting for this Feature, but it seems not to be possible.. How can it be done in a simple manner? Perhaps a simple workaround?

thx

sebek64 commented 7 years ago

@wladimar In my opinion, the only way is to make a cusom ngx-bootstrap bundle at the moment. You need access to momentjs library, which is hidden in the current bundle.

@valorkin Do you agree with my proposed solution (moving momentjs to peer dependencies)? If not, why? I'm offering to write the change. It is quite a big issue for any user of ngx-bootstrap who needs multi-language support.

sebek64 commented 7 years ago

I'd like to share my solution for AoT builds, which provides a localization in production environment. Still, JiT builds and development environment use UMD bundle of ngx-bootstrap (because I use systemjs module loader). UMD bundle contains an internal copy of momentjs, and that breaks localization.

In AoT, I import all possible locales into main-aot.ts:

import "moment/src/locale/XX";

Then, after building with ngc, I use rollup:

rollup -c rollup-config.js -o ts-generated-aot/bundle-XX.js --environment VERSION:$npm_package_version,LOCALE:XX

with configuration file

import rollup from "rollup"
import nodeResolve from "rollup-plugin-node-resolve"
import commonjs from "rollup-plugin-commonjs";
import uglify from "rollup-plugin-uglify"
import annotate from "rollup-plugin-ng-annotate"

import {readdirSync} from "fs"

var external = readdirSync("node_modules/moment/src/locale")
    .map(f => f.replace(".js", ""))
    .filter(l => l !== process.env.LOCALE)
    .map(l => "moment/src/locale/" + l);

export default {
  entry: "ts-generated-aot/main-aot.js",
  sourceMap: false,
  format: "iife",
  external: external,
  plugins: [
    nodeResolve({jsnext: true, module: true}),
    commonjs({
      include: "node_modules/rxjs/**",
    }),
    annotate(),
    uglify({
      compress: {
        global_defs: {
          DEBUG: false,
          VERSION: process.env.VERSION
        }
      }
    })
  ]
}

This ensures that only required locale import is included, and other are stripped by rollup.

The way rollup creates the bundle also ensures that only one momentjs copy is included.

valorkin commented 7 years ago

localization is already added in new datepicker (new style and pop up version) available in v1.9.0+ check this out: http://valor-software.com/ngx-bootstrap/#/datepicker#examples

it will evolve in nearest weeks, and it will be additional doc on how to extend\replace localizations

eyerean commented 7 years ago

@valorkin Did this change the old datepicker maybe? I'm still using the old one and don't want to switch to the new one because of styling issues. Before the update the locale was working (@1.8.1), months were displayed in the correct language, but now not, they appear always in English.

valorkin commented 7 years ago

@eyerean I have cut off moment.js localization will get back in v1.9.2

valorkin commented 7 years ago

problem with old localization was, that it was working not for everyone :(

sebek64 commented 7 years ago

I'm another user of ngx-bootstrap, and I also cannot upgrade from 1.8 to 1.9 because of missing localization. momentjs localization was working in production (AoT) builds well, and incorrect behavior in development (JiT) builds was not a huge issue. Now, it wouldn't work in both.

I don't have any reason for upgrade (everything works fine in 1.8). I just like to note that this is considered a huge regression between 1.8 and 1.9. In my opinion, this should not have been merged into a stable release before ready.

valorkin commented 7 years ago

Real issue, that I had to release new datepicker without appropriate docs Thing is you can use custom localization and they are compatible with moment.js Tomorrow I will add docs and demo on custom localization

valorkin commented 7 years ago

locales for old calendar will be back in v1.9.2 available as locale field in config to add locale just do

import { defineLocale } from 'ngx-bootstrap/bs-moment';
import { ar } from 'ngx-bootstrap/locale';

defineLocale(ar.abbr, ar);

before module initialize

image

available locales image

valorkin commented 7 years ago

https://ngx-home.slack.com/files/valorkin/F6X2YG6E8/dp_colors.mp4 https://ngx-home.slack.com/files/valorkin/F6X1CPMC2/dp_locale.mp4

check this one, may be you will like new calendar :) just so you know, current datepicker will be added as theme too