Our pure JavaScript Scheduler component


Post by nico-lgtech »

Hello,
I'm in angular and i don't know how to change the language of the scheduler in runtime.
And another question. Have a complete template of a translate file ?

Thanks

Post by mats »


Post by nico-lgtech »

Yes i know but there isn't full information. Where i can define for example "Monday" to "Lundi" in french ? :/

Post by pmiklashevich »

Thanks for your feedback. We will improve localization guide in the future releases. Please pay attention to the LocaleManager API.

1. You need to register new French locale using registerLocale and there you can provide translation for your own classes, and also you have to translate Bryntum words, so all menus, buttons, labels which are used for example in EventEditor are translated to French.

2. You need to extend Bryntum locales if you're planning to use them and add only translations for your new keywords.

3. To use your translation, please see Localizable mixin. All Bryntum classes are localizable by default. If you need your class to be localizable, please use the mixin. So there are 2 "L" functions: static and not static, so you can call YourClass.L('keyword'), or somewhere in scope of the class this.L('keyword').

Please copy this code to Localization demo in Scheduler to see how it works, examples/localization/app.js:
import LocaleManager from '../../lib/Common/localization/LocaleManager.js';
import Localizable from '../../lib/Common/localization/Localizable.js';

class YourClass extends Localizable() {}

LocaleManager.registerLocale('Fr', {
    desc   : 'French',
    locale : {
        localeName : 'Fr',
        localeDesc : 'French',

        // The class name you want to localize
        YourClass : {
            Monday : 'Lundi'
        },

        // All key => value phrases below are taken from examples/localization/custom-locale-de.js
        // please translate to French by yourself....

        //region Columns

        TemplateColumn : {
            noTemplate : 'TemplateColumn braucht eine template',
            noFunction : 'TemplateColumn.template muss eine funktion sein'
        },

        ColumnStore : {
            columnTypeNotFound : function(data) {
                return 'Spalte typ ' + data.type + 'nicht registriert';
            }
        },

        //endregion

        //region Mixins

        InstancePlugin : {
            fnMissing : function(data) {
                return 'Trying to chain fn ' + data.plugIntoName + '#' + data.fnName + ', but plugin fn ' + data.pluginName + '#' + data.fnName + ' does not exist';
            },
            overrideFnMissing : function(data) {
                return 'Trying to override fn ' + data.plugIntoName + '#' + data.fnName + ', but plugin fn ' + data.pluginName + '#' + data.fnName + ' does not exist';
            }
        },

        //endregion

        //region Features

        ColumnPicker : {
            columnsMenu     : 'Spalten',
            hideColumn      : 'Versteck spalte',
            hideColumnShort : 'Versteck'
        },

        Filter : {
            applyFilter  : 'Filter anwenden',
            filter       : 'Filter',
            editFilter   : 'Filter redigieren',
            on           : 'Auf',
            before       : 'Vor',
            after        : 'Nach',
            equals       : 'Gleichen',
            lessThan     : 'Weniger als',
            moreThan     : 'Mehr als',
            removeFilter : 'Filter entfernen'
        },

        FilterBar : {
            enableFilterBar  : 'Filterleiste anzeigen',
            disableFilterBar : 'Filterleiste ausblenden'
        },

        Group : {
            groupAscending       : 'Aufsteigend gruppieren',
            groupDescending      : 'Absteigend gruppieren',
            groupAscendingShort  : 'Aufsteigend',
            groupDescendingShort : 'Absteigend',
            stopGrouping         : 'Stoppen gruppierung',
            stopGroupingShort    : 'Stoppen'
        },

        Search : {
            searchForValue : 'Suche nach Wert'
        },

        Sort : {
            'sortAscending'          : 'Aufsteigend sortierung',
            'sortDescending'         : 'Absteigend sortierung',
            'multiSort'              : 'Multi sortieren',
            'removeSorter'           : 'Sortierung entfernen',
            'addSortAscending'       : 'Aufsteigend sortieren hinzufügen',
            'addSortDescending'      : 'Absteigend sortieren hinzufügen',
            'toggleSortAscending'    : 'Ändern Sie auf aufsteigend',
            'toggleSortDescending'   : 'Zu absteigend wechseln',
            'sortAscendingShort'     : 'Aufsteigend',
            'sortDescendingShort'    : 'Absteigend',
            'removeSorterShort'      : 'Entfernen',
            'addSortAscendingShort'  : '+ Aufsteigend',
            'addSortDescendingShort' : '+ Absteigend'
        },

        Tree : {
            noTreeColumn : 'To use the tree feature one column must be configured with tree: true'
        },

        //endregion

        //region Grid

        Grid : {
            featureNotFound : function(data) {
                return 'Feature "' + data + '" not available, make sure you have imported it';
            },
            invalidFeatureNameFormat : function(data) {
                return 'Invalid feature name "' + data + '", must start with a lowercase letter';
            },
            removeRow         : 'Zeile löschen',
            removeRows        : 'Zeilen löschen',
            loadMask          : 'Laden...',
            loadFailedMessage : 'Wird geladen, bitte versuche es erneut',
            moveColumnLeft    : 'Bewegen Sie sich zum linken Bereich',
            moveColumnRight   : 'Bewegen Sie sich nach rechts',
            noRows            : 'Keine Zeilen zum Anzeigen'
        },

        //endregion

        //region Widgets

        Field : {
            invalidValue          : 'Ungültiger Feldwert',
            minimumValueViolation : 'Mindestwertverletzung',
            maximumValueViolation : 'Maximalwertverletzung',
            fieldRequired         : 'Dieses Feld wird benötigt',
            validateFilter        : 'Der Wert muss aus der Liste ausgewählt werden'
        },

        DateField : {
            invalidDate : 'Ungültige Datumseingabe'
        },

        TimeField : {
            invalidTime : 'Ungültige Zeitangabe'
        },

        //endregion

        //region Others

        DateHelper : {
            locale       : 'de',
            shortWeek    : 'W',
            shortQuarter : 'q',
            week         : 'Woche',
            weekStartDay : 1,
            unitNames    : [
                { single : 'Millisekunde', plural : 'Millisekunden', abbrev : 'ms' },
                { single : 'Sekunde', plural : 'Sekunden', abbrev : 's' },
                { single : 'Minute', plural : 'Minuten', abbrev : 'min' },
                { single : 'Stunde', plural : 'Stunden', abbrev : 'std' },
                { single : 'Tag', plural : 'Tage', abbrev : 't' },
                { single : 'Woche', plural : 'Wochen', abbrev : 'W' },
                { single : 'Monat', plural : 'Monathe', abbrev : 'mon' },
                { single : 'Quartal', plural : 'Quartal', abbrev : 'Q' },
                { single : 'Jahr', plural : 'Jahre', abbrev : 'jahr' }
            ],
            // Used to build a RegExp for parsing time units.
            // The full names from above are added into the generated Regexp.
            // So you may type "2 w" or "2 wk" or "2 week" or "2 weeks" into a DurationField.
            // When generating its display value though, it uses the full localized names above.
            unitAbbreviations : [
                ['mil'],
                ['s', 'sec'],
                ['m', 'min'],
                ['h', 'hr'],
                ['d'],
                ['w', 'wk'],
                ['mo', 'mon', 'mnt'],
                ['q', 'quar', 'qrt'],
                ['y', 'yr']
            ],
            parsers : {
                'L'  : 'DD.MM.YYYY',
                'LT' : 'HH:mm'
            },
            ordinalSuffix : function(number) {
                return number;
            }
        },

        BooleanCombo : {
            'Yes' : 'Ja',
            'No'  : 'Nein'
        },

        //endregion

        //region Scheduler

        ExcelExporter : {
            'No resource assigned' : 'Keine Ressource zugewiesen'
        },

        ResourceInfoColumn : {
            eventCountText : function(data) {
                return data + ' Veranstaltung' + (data !== 1 ? 'en' : '');
            }
        },

        Dependencies : {
            from     : 'Von',
            to       : 'Zo',
            valid    : 'Gültig',
            invalid  : 'Ungültig',
            Checking : 'Überprüfung…'
        },

        DependencyEdit : {
            From              : 'Von',
            To                : 'Zu',
            Type              : 'Typ',
            Lag               : 'Verzögern',
            'Edit dependency' : 'Abhängigkeit bearbeiten',
            Save              : 'Speichern',
            Delete            : 'Löschen',
            Cancel            : 'Abbrechen',
            StartToStart      : 'Anfang-Anfang',
            StartToEnd        : 'Anfang-Ende',
            EndToStart        : 'Ende-Anfang',
            EndToEnd          : 'Ende-Ende'
        },

        EventEdit : {
            Name         : 'Name',
            Resource     : 'Ressource',
            Start        : 'Start',
            End          : 'Ende',
            Save         : 'Speichern',
            Delete       : 'Löschen',
            Cancel       : 'Abbrechen',
            'Edit Event' : 'Buchung redigieren'
        },

        Scheduler : {
            'Add event'      : 'Ereignis hinzufügen',
            'Delete event'   : 'Buchung löschen',
            'Unassign event' : 'Ereignis nicht zuordnen'
        },

        HeaderContextMenu : {
            pickZoomLevel   : 'Zoomen',
            activeDateRange : 'Datumsbereich',
            startText       : 'Anfangsdatum',
            endText         : 'Endtermin',
            todayText       : 'Heute'
        },

        EventFilter : {
            filterEvents : 'Aufgaben filtern',
            byName       : 'Namentlich'
        },

        TimeRanges : {
            showCurrentTimeLine : 'Aktuelle Zeitleiste anzeigen'
        },

        PresetManager : {
            minuteAndHour : {
                topDateFormat : 'ddd DD.MM, HH:mm'
            },
            hourAndDay : {
                topDateFormat : 'ddd DD.MM'
            },
            weekAndDay : {
                displayDateFormat : 'HH:mm'
            }
        }

        //endregion
    }
});

LocaleManager.applyLocale('Fr');

console.log(YourClass.L('Monday'));

LocaleManager.extendLocale('Ru', {
    extends : 'Ru',

    // The class name you want to localize
    YourClass : {
        Monday : 'Понедельник'
    }
});

LocaleManager.applyLocale('Ru');

console.log(YourClass.L('Monday'));

Pavlo Miklashevych
Sr. Frontend Developer


Post by pawel.szwak »

How to use it for Angular?

Post by saki »

Locales are written in vanilla javascript so they are framework agnostic. Therefore, our vanilla Localization demo should be enough to demonstrate how to create and use a custom locale (French in your case). The example creates and uses German locale so look for anything related to German in the source code.

Regarding Angular, you probably already use a localization library with Angular so you need to consult that library documentation on how to use it. We have an Angular Localization example that uses i18next localization library so you can use it as a reference point.

As to switching locales at runtime, it should be enough to:
import {LocaleManager} from 'bryntum-scheduler';

LocaleManager.locale = 'Fr';

// or

LocaleManager.locale = 'SvSE'
See applySchedulerLocale method in app.component.ts in the aforementioned angular example source code.

Post by pawel.szwak »

I'm will try. Thank you for support.

Post by pawel.szwak »

I am trying to reproduce an example but I have a problem

Look at the code below, locale is not avaliable

 
 
 import { GanttComponent } from 'bryntum-angular-shared';
 
  @ViewChild('gantt') gantt : GanttComponent;
 
 applyGanttLocale = ( schedulerLocale : string ) : void => {
        const localeManager = this.gantt.ganttEngine.localeManager;

        switch (schedulerLocale) {
            case 'se':
                localeManager.locale = 'SvSE'; // locale is not avaliable
                break;

            case 'ru':
                localeManager.locale = 'Ru';
                break;

            default:
                localeManager.locale = 'En';
                break;
        }
    };
 
 

This can be set in yet another way?

Post by saki »

Have they been imported? See schedulerLocales.js of the example.

Post Reply