Issues with moment.js and localization

Issues with moment.js and localization

rf1234rf1234 Posts: 2,810Questions: 85Answers: 406
edited February 2017 in Free community support

Hi Allan,

I am using moment.js to format dates. I have included the MomentJS-2.13.0 Javascript. In addition I am using two locales:

<!--    Locales for moment.js-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/locale/de.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/locale/en-gb.js"></script>

To initialize moment.js I do this:

//Moment.js (date time) location settings
if (lang === 'de') {
    moment.locale('de');
} else {
    moment.locale('en-gb');
}
// Return today's date and time
var currentTime = new Date();

The Data Table uses this - and it works perfectly fine. For German (lang === 'de') it returns 'DD.MM.YYYY' else it returns the English Version of 'DD/MM/YYYY'.

{   data: "rfp.start_date",
    render: function ( data, type, row ) {                   
            return moment(new Date(data)).format('L');
    }    
},

My problem is with Editor. The only thing that works here is the default unfortunately which correctly returns the current date in the German or English format.

fields: [ {
                label: "Start Date:",
                name:  "rfp.start_date",
                type:  "datetime",
                def:   function () { return moment(currentTime).format('L');},
                format: 'DD.MM.YYYY',
                opts:  {
                    showWeekNumber: true,
                    momentLocale: 'de'
                }
            }, {
                label: "End Date:",
                name:  "rfp.end_date",
                type:  "datetime",
                def:   function () { return moment(currentTime).format('L');}
            } ] 

"Start Date" in this fashion only works for German because Editor forced me to hard code the format to be 'MM.DD.YYYY'. Editor does not accept the format 'L' which is a moment.js standard format used with localization. You can also see it in the respective moment locale scripts mentioned above. I tried to use a global variable predefined with one of the two formats but that produced an error. So how can I localize this? How can I preset the format so that is used correctly by Editor since it does not acceopt 'L'?

And there is another issue: Editor ignores "momentLocale: 'de'". "showWeekNumber" works however. For that reason my date picker is only in English and not shown in German.

Let's assume I get "momentLocale" working: How do I dynamically set the locale to either German or English?

"End Date" is even worse: Only the default works fine in German or English. Once you start editing the date it shows it in 'YYYY-MM-DD'. For the German language setting it starts with the default of '03.02.2017'. Then I open the date picker which is in English only and if I select February 4th the date picker returns '2017-02-04' which is a problem ...

Please help!

This question has accepted answers - jump to:

Answers

  • allanallan Posts: 62,044Questions: 1Answers: 10,171 Site admin

    Editor does not accept the format 'L' which is a moment.js standard format used with localization.

    That's odd. I'm not sure why that would be the case as there is no special handling for that code. One thing, your def should really just return a Date object, not a formatted value.

    I'll try to replicate the issue with L locally, or if you have a page you can link me to that would be useful.

    Allan

  • rf1234rf1234 Posts: 2,810Questions: 85Answers: 406
    edited February 2017

    Thanks, Allan! Sorry I can't provide you with a page ...
    I tried this now in Editor:

    {
    label: "Start Date:",
    name:  "rfp.start_date",
    type:  "datetime",
    def:   function () { return new Date();},
    format: 'L',
    opts:  {
           showWeekNumber: true,
            momentLocale: 'de'
     }
    },
    

    Now the 'L' works and even the locale works! It returns 03.02.2017.
    If I change the locale to 'en' it returns 02/03/2017. And if I use 'en-gb' it returns
    03/02/2017. PERFECT!

    There is only ony thing unfortunately:
    Using 'L' instead of e.g. 'DD-MM-YYYY' makes the datepicker freeze! That is quite an issue. "freeze" means you cannot even open it.

    So I tried this:

    {
    label: "Start Date:",
    name:  "rfp.start_date",
    type:  "datetime",
    def:   function () { return new Date();},
    format: 'DD-MM-YYYY',
    opts:  {
           showWeekNumber: true,
            momentLocale: 'de'
     }
    },
    

    03-02-2017 is being returned. So the format overwrites the locale.In this case the datepicker works almost normally since it is in English while it should be in German.

    I now tried this to get closer to the problem:

    {
    label: "Start Date:",
    name:  "rfp.start_date",
    type:  "datetime",
    format: 'L',
    },
    

    This returns an empty field and you can't open the datepicker due to some error which is caused by the 'L'.

    Now my next guess:

    {
    label: "Start Date:",
    name:  "rfp.start_date",
    type:  "datetime",
    format: 'DD-MM-YYYY',
    },
    

    Result: Empty field, datepicker opens and then I click on today's date. It returns: 03-02-2017. ok!

    In summary these are the issues:
    - solution for the datepicker using 'L' instead of e.g. 'DD-MM-YYYY'
    - making the datepicker respect the locale instead of only returning English
    - dynamic setting of locale (right now it is hard coded in "momentLocale: 'de'" and my global settings for moment.js (see above) are ignored in Editor but NOT in datatables which is amazing ..

  • rf1234rf1234 Posts: 2,810Questions: 85Answers: 406

    I also had trouble on the server side but I could figure it out myself like this:

    Editor::inst( $db, 'rfp' )
    ->field(            
    Field::inst( 'rfp.start_date' )
    ->validator( 'Validate::notEmpty', array('message' => $msg[0]) )
    // ->getFormatter( 'Format::date_sql_to_format', Format::DATE_ISO_8601 )
    // ->setFormatter( 'Format::date_format_to_sql', Format::DATE_ISO_8601 ),
    ->getFormatter( function ( $val, $data, $opts ) {
        if ($_SESSION['lang'] === 'de') {     
             return date( 'd.m.Y', strtotime( $val ) );
          } else {
               return date( 'd/m/Y', strtotime( $val ) );
           }                        
    } )
    ->setFormatter( function ( $val, $data, $opts ) {
        return date( 'Y-m-d H:i:s', strtotime( $val ) );
    } ) 
    )
    

    This code does the job dynamically - and I don't have to do any rendering in the data table display any longer. The German or English date formats are displayed on the screen depending on the language set ...

    I also would need such a solution for Java Script ... Please.

  • allanallan Posts: 62,044Questions: 1Answers: 10,171 Site admin

    Using 'L' instead of e.g. 'DD-MM-YYYY' makes the datepicker freeze! That is quite an issue. "freeze" means you cannot even open it.

    In dataTables.editor.js could you find the line:

    date:    this.c.format.match( /[YMD]/ ) !== null,
    

    and add an L into that regex (e.g. /[YMDL]/). I think that should resolve that issue.

    What is happening there is that the code is trying to determine what parts of the picker should be shown.

    Allan

  • rf1234rf1234 Posts: 2,810Questions: 85Answers: 406
    edited February 2017

    Thanks a lot Alan! That worked.
    I could also resolve the dynamic "momentLocale" setting. I had messed up global variable definition ... and fixed it in the meantime.
    Now the code looks like this:

    {
    label: "Start Date:",
    name:  "rfp.start_date",
    type:  "datetime",
    def:   function () { return currentTime},
    format: 'L',
    opts:  {
           showWeekNumber: true,
            momentLocale: momentLocale
             }
    }
    

    This works fine! There is only one issue left:
    - making the datepicker respect the locale instead of only returning English

  • allanallan Posts: 62,044Questions: 1Answers: 10,171 Site admin

    Good to hear that helped.

    • making the datepicker respect the locale instead of only returning English

    If you provide a format of L shouldn't that automatically mean that the date format returned is the localised format?

    Allan

  • rf1234rf1234 Posts: 2,810Questions: 85Answers: 406
    edited February 2017

    Yes, the format is the localized format. That is fine. But the date picker itself is always in English, never in German. "February" should be "Februar" for example.
    Is there a solution for this?
    If so, is there a similar solution for Quill? The menu bar is only in English as well ...

    I found this: http://bootstrap-datepicker.readthedocs.io/en/latest/i18n.html
    How could I use this with Editor?
    I am using the plugin for Bootstrap DateTimePicker (2)
    Here is another good hint, but I don't know how to use this with Editor:
    http://stackoverflow.com/questions/19382189/change-language-for-bootstrap-datetimepicker

  • allanallan Posts: 62,044Questions: 1Answers: 10,171 Site admin
    Answer ✓

    Oh I see what you mean. You need to use the language options to set the language information for the date picker (such as the month name). That doesn't come from Moment, but rather from the initialisation options.

    Allan

  • allanallan Posts: 62,044Questions: 1Answers: 10,171 Site admin
    Answer ✓

    p.s. For Quill - you'd need to use the initialisation options for Quill to set its language options. Which you can access using that plug-in's opts parameter.

    Allan

  • rf1234rf1234 Posts: 2,810Questions: 85Answers: 406
    edited February 2017

    also found a solution for quill now.
    1. Translated the toolbar from your plugin

    var quillToolbar = 
            '<span class="ql-format-group">'+
        '  <select title="Schriftart" class="ql-font">'+
        '    <option value="sans-serif" selected="">Sans Serif</option>'+
        '    <option value="serif">Serif</option>'+
        '    <option value="monospace">Feste Zeichenbreite</option>'+
        '  </select>'+
        '  <select title="Größe" class="ql-size">'+
        '    <option value="10px">Klein</option>'+
        '    <option value="13px" selected="">Normal</option>'+
        '    <option value="18px">Groß</option>'+
        '    <option value="32px">Riesig</option>'+
        '  </select>'+
        '</span>'+
        '<span class="ql-format-group">'+
        '  <span title="Fett" class="ql-format-button ql-bold"></span>'+
        '<span class="ql-format-separator"></span>'+
        '<span title="Kursiv" class="ql-format-button ql-italic"></span>'+
        '<span class="ql-format-separator"></span>'+
        '<span title="Unterstreichen" class="ql-format-button ql-underline"></span>'+
        '<span class="ql-format-separator"></span>'+
        '<span title="Durchstreichen" class="ql-format-button ql-strike"></span>'+
        '</span>'+
        '<span class="ql-format-group">'+
        '  <select title="Textfarbe" class="ql-color">'+
        '    <option value="rgb(0, 0, 0)" label="rgb(0, 0, 0)" selected=""></option>'+
        '    <option value="rgb(230, 0, 0)" label="rgb(230, 0, 0)"></option>'+
        '    <option value="rgb(255, 153, 0)" label="rgb(255, 153, 0)"></option>'+
        '    <option value="rgb(255, 255, 0)" label="rgb(255, 255, 0)"></option>'+
        '    <option value="rgb(0, 138, 0)" label="rgb(0, 138, 0)"></option>'+
        '    <option value="rgb(0, 102, 204)" label="rgb(0, 102, 204)"></option>'+
        '    <option value="rgb(153, 51, 255)" label="rgb(153, 51, 255)"></option>'+
        '    <option value="rgb(255, 255, 255)" label="rgb(255, 255, 255)"></option>'+
        '    <option value="rgb(250, 204, 204)" label="rgb(250, 204, 204)"></option>'+
        '    <option value="rgb(255, 235, 204)" label="rgb(255, 235, 204)"></option>'+
        '    <option value="rgb(255, 255, 204)" label="rgb(255, 255, 204)"></option>'+
        '    <option value="rgb(204, 232, 204)" label="rgb(204, 232, 204)"></option>'+
        '    <option value="rgb(204, 224, 245)" label="rgb(204, 224, 245)"></option>'+
        '    <option value="rgb(235, 214, 255)" label="rgb(235, 214, 255)"></option>'+
        '    <option value="rgb(187, 187, 187)" label="rgb(187, 187, 187)"></option>'+
        '    <option value="rgb(240, 102, 102)" label="rgb(240, 102, 102)"></option>'+
        '    <option value="rgb(255, 194, 102)" label="rgb(255, 194, 102)"></option>'+
        '    <option value="rgb(255, 255, 102)" label="rgb(255, 255, 102)"></option>'+
        '    <option value="rgb(102, 185, 102)" label="rgb(102, 185, 102)"></option>'+
        '    <option value="rgb(102, 163, 224)" label="rgb(102, 163, 224)"></option>'+
        '    <option value="rgb(194, 133, 255)" label="rgb(194, 133, 255)"></option>'+
        '    <option value="rgb(136, 136, 136)" label="rgb(136, 136, 136)"></option>'+
        '    <option value="rgb(161, 0, 0)" label="rgb(161, 0, 0)"></option>'+
        '    <option value="rgb(178, 107, 0)" label="rgb(178, 107, 0)"></option>'+
        '    <option value="rgb(178, 178, 0)" label="rgb(178, 178, 0)"></option>'+
        '    <option value="rgb(0, 97, 0)" label="rgb(0, 97, 0)"></option>'+
        '    <option value="rgb(0, 71, 178)" label="rgb(0, 71, 178)"></option>'+
        '    <option value="rgb(107, 36, 178)" label="rgb(107, 36, 178)"></option>'+
        '    <option value="rgb(68, 68, 68)" label="rgb(68, 68, 68)"></option>'+
        '    <option value="rgb(92, 0, 0)" label="rgb(92, 0, 0)"></option>'+
        '    <option value="rgb(102, 61, 0)" label="rgb(102, 61, 0)"></option>'+
        '    <option value="rgb(102, 102, 0)" label="rgb(102, 102, 0)"></option>'+
        '    <option value="rgb(0, 55, 0)" label="rgb(0, 55, 0)"></option>'+
        '    <option value="rgb(0, 41, 102)" label="rgb(0, 41, 102)"></option>'+
        '    <option value="rgb(61, 20, 102)" label="rgb(61, 20, 102)"></option>'+
        '  </select>'+
        '  <span class="ql-format-separator"></span>'+
        '<select title="Hintergrundfarbe" class="ql-background">'+
        '   <option value="rgb(0, 0, 0)" label="rgb(0, 0, 0)"></option>'+
        '   <option value="rgb(230, 0, 0)" label="rgb(230, 0, 0)"></option>'+
        '   <option value="rgb(255, 153, 0)" label="rgb(255, 153, 0)"></option>'+
        '   <option value="rgb(255, 255, 0)" label="rgb(255, 255, 0)"></option>'+
        '   <option value="rgb(0, 138, 0)" label="rgb(0, 138, 0)"></option>'+
        '   <option value="rgb(0, 102, 204)" label="rgb(0, 102, 204)"></option>'+
        '   <option value="rgb(153, 51, 255)" label="rgb(153, 51, 255)"></option>'+
        '   <option value="rgb(255, 255, 255)" label="rgb(255, 255, 255)" selected=""></option>'+
        '   <option value="rgb(250, 204, 204)" label="rgb(250, 204, 204)"></option>'+
        '   <option value="rgb(255, 235, 204)" label="rgb(255, 235, 204)"></option>'+
        '   <option value="rgb(255, 255, 204)" label="rgb(255, 255, 204)"></option>'+
        '   <option value="rgb(204, 232, 204)" label="rgb(204, 232, 204)"></option>'+
        '   <option value="rgb(204, 224, 245)" label="rgb(204, 224, 245)"></option>'+
        '   <option value="rgb(235, 214, 255)" label="rgb(235, 214, 255)"></option>'+
        '   <option value="rgb(187, 187, 187)" label="rgb(187, 187, 187)"></option>'+
        '   <option value="rgb(240, 102, 102)" label="rgb(240, 102, 102)"></option>'+
        '   <option value="rgb(255, 194, 102)" label="rgb(255, 194, 102)"></option>'+
        '   <option value="rgb(255, 255, 102)" label="rgb(255, 255, 102)"></option>'+
        '   <option value="rgb(102, 185, 102)" label="rgb(102, 185, 102)"></option>'+
        '   <option value="rgb(102, 163, 224)" label="rgb(102, 163, 224)"></option>'+
        '   <option value="rgb(194, 133, 255)" label="rgb(194, 133, 255)"></option>'+
        '   <option value="rgb(136, 136, 136)" label="rgb(136, 136, 136)"></option>'+
        '   <option value="rgb(161, 0, 0)" label="rgb(161, 0, 0)"></option>'+
        '   <option value="rgb(178, 107, 0)" label="rgb(178, 107, 0)"></option>'+
        '   <option value="rgb(178, 178, 0)" label="rgb(178, 178, 0)"></option>'+
        '   <option value="rgb(0, 97, 0)" label="rgb(0, 97, 0)"></option>'+
        '   <option value="rgb(0, 71, 178)" label="rgb(0, 71, 178)"></option>'+
        '   <option value="rgb(107, 36, 178)" label="rgb(107, 36, 178)"></option>'+
        '   <option value="rgb(68, 68, 68)" label="rgb(68, 68, 68)"></option>'+
        '   <option value="rgb(92, 0, 0)" label="rgb(92, 0, 0)"></option>'+
        '   <option value="rgb(102, 61, 0)" label="rgb(102, 61, 0)"></option>'+
        '   <option value="rgb(102, 102, 0)" label="rgb(102, 102, 0)"></option>'+
        '   <option value="rgb(0, 55, 0)" label="rgb(0, 55, 0)"></option>'+
        '   <option value="rgb(0, 41, 102)" label="rgb(0, 41, 102)"></option>'+
        '   <option value="rgb(61, 20, 102)" label="rgb(61, 20, 102)"></option>'+
        '</select>'+
        '</span>'+
        '<span class="ql-format-group">'+
        '  <span title="numerierte Liste" class="ql-format-button ql-list"></span>'+
        '<span class="ql-format-separator"></span>'+
        '<span title="Bullet" class="ql-format-button ql-bullet"></span>'+
        '<span class="ql-format-separator"></span>'+
        '<select title="Textausrichtung" class="ql-align">'+
        '   <option value="left" label="Links" selected=""></option>'+
        '   <option value="center" label="Zentriert"></option>'+
        '   <option value="right" label="Rechts"></option>'+
        '   <option value="justify" label="Blocksatz"></option>'+
        '</select>'+
        '</span>'+
        '<span class="ql-format-group">'+
        '      <span title="Link" class="ql-format-button ql-link"></span>'+
        '</span>';
    
    
    1. Depending on the language use the translated toolbar or "true" as parameter
    if (lang !== 'de') {
       quillToolbar = true;
    }
    
    
    1. Adjust the definition for the quill field in Editor:
    {
    label: "Description:",
    name:  "rfp.description",
     type:  "quill",
     toolbar: quillToolbar,
             opts: {
                      theme: 'snow'
              }                
    }
    
  • rf1234rf1234 Posts: 2,810Questions: 85Answers: 406

    The solution for the datepicker was to translate the i18n Editor defaults. That fixed the issue. I translated all of these options into German now:

    //Editor default settings!
        if (lang === 'de') {
            $.extend( true, $.fn.dataTable.Editor.defaults, {            
                i18n: {
                    remove: {
                        button: "Löschen",
                        title:  "Eintrag löschen",
                        submit: "Endgültig Löschen",
                        confirm: {
                            _: 'Sind Sie sicher, dass Sie die %d ausgwählten Zeilen löschen wollen?',
                            1: 'Sind Sie sicher, dass Sie die ausgewählte Zeile löschen wollen?'
                        }
                    },
                    edit: {
                        button: "Bearbeiten",
                        title:  "Eintrag bearbeiten",
                        submit: "Änderungen speichern"
                    },
                    create: {
                        button: "Neuer Eintrag",
                        title:  "Neuen Eintrag anlegen",
                        submit: "Neuen Eintrag speichern"
                    },
                    datetime: {
                previous: 'Zurück',
                next:     'Weiter',
                months:   [ 'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember' ],
                weekdays: [ 'So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa' ],
                amPm:     [ 'am', 'pm' ],
                unknown:  '-'
                    },
                    error: {            
                system: "Ein Systemfehler ist aufgetreten (<a target=\"_blank\" href=\"//datatables.net/tn/12\">Für mehr Informationen</a>)."
            },
                    multi: {
                title: "Mehrere Werte",         
                            info: "Die ausgewählten Elemente enthalten verschiedene Werte für das Feld. Um alle Elemente für diess Feld auf den gleichen Wert zu setzen, klicken Sie bitte hier. Ansonsten werden die Elemente ihren jeweiligen Wert behalten.",
                restore: "Änderungen rückgängig machen",
                noMulti: "Dieses Feld kann einzeln bearbeitet werden, aber nicht als Teil einer Gruppe."
            },
                }      
            });
    
This discussion has been closed.