Get Started with Localization

Localization

All Smart UI components support localization - the process of adapting software to both the culture and language of an end user. All information such as text content, numeric and date formats and built-in Error messages thrown by the Custom Elements can be customized and set to multiple languages/cultures.

Setup Grid

The demo below will showcase how to dynamically switch Smart.Grid's langauge between two different options - English and Italian.

  1. Follow the Download & Installation guide to set up Smart UI in your JS project

  2. Create a <smart-grid> element and two radio buttons in your Web Page:
    <smart-radio-button group-name="Language" checked>English</smart-radio-button>
    <smart-radio-button group-name="Language">Italian</smart-radio-button>
    <smart-grid id="grid"></smart-grid>
  3. Then inside index.js, set the grid's properties.:
    window.Smart('#grid', class {
      get properties() {
        return {
          header: {
            visible: true
          },
          columnMenu: {
            dataSource: {
              columnMenuItemRename: {
                visible: true
              },
              columnMenuItemEditDescription: {
                visible: true
              },
              columnMenuItemHide: {
                visible: true
              },
              columnMenuItemDelete: {
                visible: true
              }
            }
          },
          dataSource: new Smart.DataAdapter({
            dataSource: [{
                firstName: "John",
                lastName: "Smith",
                balance: 500,
                birthDate: "1995/05/01"
              },
              {
                firstName: "Beate",
                lastName: "Wilson",
                balance: 200,
                birthDate: "1999/01/10"
              },
              {
                firstName: "Regina",
                lastName: "Fuller",
                balance: 0,
                birthDate: "2000/01/20"
              },
              {
                firstName: "Petra",
                lastName: "Burke",
                balance: 1000,
                birthDate: "1982/06/06"
              },
              {
                firstName: "Martin",
                lastName: "Ohno",
                balance: 700,
                birthDate: "1993/02/01"
              },
              {
                firstName: "Ian",
                lastName: "Nodier",
                balance: 3000,
                birthDate: "1992/10/07"
              },
              {
                firstName: "Sven",
                lastName: "Devling",
                balance: 200,
                birthDate: "1989/02/15"
              },
              {
                firstName: "Beate",
                lastName: "Devling",
                balance: 500,
                birthDate: "1990/07/20"
              },
              {
                firstName: "Will",
                lastName: "Johnson",
                balance: 400,
                birthDate: "2001/04/11"
              },
            ],
            dataFields: [
              'firstName: string',
              'lastName: string',
              'balance: number',
              'birthDate: date',
            ]
          }),
          grouping: {
            enabled: true
          },
          filtering: {
            enabled: true
          },
          sorting: {
            enabled: true,
          },
          editing: {
            enabled: true
          },
          columns: [
            {
              label: 'First Name',
              dataField: 'firstName',
            },
            {
              label: 'Last Name',
              dataField: 'lastName',
            },
            {
              label: 'Account Balance',
              dataField: 'balance',
              cellsFormat: 'c2'
            },
            {
              label: 'Birth Date',
              dataField: 'birthDate',
              cellsFormat: 'd'
            },
          ]
        };
      }
    });
    window.onload = function () {
      const buttons = document.querySelectorAll("smart-radio-button")
      let engButton = buttons[0];
      let itButton = buttons[1]
      engButton.addEventListener('click', englishTranslate);
      itButton.addEventListener('click', italianTranslate);
    
    };
    
    function englishTranslate(){
      
    }
    function italianTranslate(){
    
    }
Basic grid

Localize Text Content

All messages, tooltips and text content the user can recieve are defined in the messages property.
By deafult, messages contains only an "en" key, which specifies the english translation of the text content.

messages = {
  "en": {
    "invalidColumnProperty": "{{elementType}}: Invalid property name \"{{propertyName}}\" set for Column: \"{{type}}\"",
    "invalidRowProperty": "{{elementType}}: Invalid property name \"{{propertyName}}\" set for Row\"",
    "invalidCellValue": "Invalid cell value \"{{value}}\", Validation rule: \"{{validationRule}}\"",
    .....
  }
}
We will expand this by adding an Italian translation to all filter related content:
messages = {
  "en": {
    "invalidColumnProperty": "{{elementType}}: Invalid property name \"{{propertyName}}\" set for Column: \"{{type}}\"",
    "invalidRowProperty": "{{elementType}}: Invalid property name \"{{propertyName}}\" set for Row\"",
    "invalidCellValue": "Invalid cell value \"{{value}}\", Validation rule: \"{{validationRule}}\"",
    .....
  },
  "it":{
    "columnMenuItemFilter": "Filtro",
    "columnMenuItemRemoveFilter": "Rimuovi filtro",
    "commandBarFilter": "Filtro",
    "dialogFilterButtonConfirm": "FILTRO",
    "dialogFilterButtonCancel": "CLEAR",
    "dialogFilterHeader": "Filtra per",
    "dialogFilterMinLabel": "Min",
    "dialogFilterMaxLabel": "Massimo",
    "CLEAR_FILTER": "Cancella filtro",
    "STARTS_WITH": "Inizia con",
    "addFilter": "+ Aggiungi filtro",
    "and": "e",
    "filter": "Filtro",
    "filteredByMultiple": "{{n}} filtri",
    "filteredByOne": "1 filtro",
    "NOT_NULL": "non nullo",
    "NULL": "nullo",
    "CONTAINS": "Contiene",
    "DOES_NOT_CONTAIN": "Non contiene",
    "ENDS_WITH": "Finisce con",
    "EQUAL": "Uguale",
    "GREATER_THAN": "Maggiore di",
    "GREATER_THAN_OR_EQUAL": "Maggiore o uguale di",
    "LESS_THAN": "Meno di",
    "LESS_THAN_OR_EQUAL": "Inferiore o uguale",
    "NOT_EQUAL": "Non uguale",
    "where": "Dove",
    "apply": "Applica",
  }
}

When the messages have been set, the langauge/culture of the Grid is set using the locale property.
Modify the englishTranslate and italianTranslate functions to change the grid's locale when they are executed:

function englishTranslate() {
  let grid = document.querySelector('smart-grid');
  grid.locale = 'en';

}

function italianTranslate() {
  let grid = document.querySelector('smart-grid');
  grid.locale = 'it';

}

Now, when the radio button is set to Italian, the text content of the Grid's filter will also be set to Italian:

Grid filtering

The object below is the full Italian translation of all possible messages:

let messages = {
  "en":{
    .....
  },
  "it": {
    "invalidColumnProperty": "{{elementType}}: Nome proprietà non valido \"{{propertyName}}\" impostato per Colonna: \"{{type}}\"",
    "invalidRowProperty": "{{elementType}}: nome proprietà non valido \"{{propertyName}}\" impostato per Row\"",
    "invalidCellValue": "Valore cella non valido \"{{value}}\", Regola di convalida: \"{{validationRule}}\"",
    "frozenColumns": "{{elementType}}: per bloccare/bloccare un gruppo di colonne, tutte le colonne al suo interno devono essere bloccate.",
    "frozenRows": "{{elementType}}: per bloccare/bloccare una cella speciale, tutte le righe al suo interno devono essere bloccate.",
    "columnGroups": "{{elementType}}: per favore, controlla l'inizializzazione dell'array di colonne di smartGrid. Le colonne in un gruppo di colonne dovrebbero essere fratelli nell'array di colonne.",
    "min": "Min: {{value}}",
    "max": "Massimo: {{value}}",
    "sum": "Somma: {{value}} ",
    "avg": "Media: {{value}}",
    "count": "Conteggio: {{value}}",
    "pagerFirstButton": "Primo",
    "pagerLastButton": "Ultimo",
    "pagerPreviousButton": "Precedente",
    "pagerNextButton": "Avanti",
    "pagerNavigateToLabel": "Vai a:",
    "pagerPageSizeLabel": "Mostra:",
    "pagerNavigateToInputPlaceholder": "",
    "pagerEllipsis": "...",
    "pagerSummaryString": "di",
    "pagerSummaryPrefix": "di",
    "pagerSummarySuffix": "",
    "columnMenuCustomizeType": "Personalizza tipo",
    "columnMenuItemRename": "Rinomina",
    "columnMenuItemEditDescription": "Modifica descrizione",
    "columnMenuItemDuplicate": "Duplica",
    "columnMenuItemInsertLeft": "Inserisci a sinistra",
    "columnMenuItemInsertRight": "Inserisci a destra",
    "columnMenuItemSortAsc": "Ordina {{mode}}",
    "columnMenuItemSortDesc": "Ordina {{mode}}",
    "columnMenuItemRemoveSort": "Rimuovi ordinamento",
    "columnMenuItemFilter": "Filtro",
    "columnMenuItemRemoveFilter": "Rimuovi filtro",
    "columnMenuItemGroupBy": "Raggruppa per questa colonna",
    "columnMenuItemRemoveGroupBy": "Rimuovi gruppo",
    "columnMenuItemHide": "Nascondi",
    "columnMenuItemDelete": "Elimina",
    "columnResizeTooltip": "larghezza: {{valore}}px",
    "rowResizeTooltip": "altezza: {{valore}}px",
    "commandBarAddRow": "Aggiungi",
    "commandBarDeleteRow": "Elimina",
    "commandBarBatchRevert": "Ripristina",
    "commandBarBatchSave": "Salva",
    "commandBarFilter": "Filtro",
    "commandBarSort": "Ordina",
    "commandBarSearch": "Cerca",
    "commandBarCustomize": "Personalizza",
    "commandBarGroup": "Gruppo",
    "commandColumnEdit": "Modifica",
    "commandColumnDelete": "Elimina",
    "commandColumnCancel": "Annulla",
    "commandColumnUpdate": "Aggiorna",
    "commandColumnMenu": "",
    "expandRow": "Espandi riga",
    "collapseRow": "Comprimi riga",
    "addNewRow": "Fai clic qui per aggiungere una nuova riga",
    "addNewColumn": "Fai clic qui per aggiungere una nuova colonna",
    "dialogChartHeader": "{{value}} Grafico",
    "dialogRowDetailHeader": "ID riga: {{value}}",
    "dialogDescriptionHeader": "Colonna: {{value}}",
    "dialogRowDetailButtonConfirm": "OK",
    "dialogRowDetailButtonCancel": "ANNULLA",
    "dialogEditHeader": "Modifica {{value}}",
    "dialogAddButtonConfirm": "AGGIUNGI",
    "dialogAddButtonCancel": "ANNULLA",
    "dialogEditButtonConfirm": "OK",
    "dialogEditButtonCancel": "ANNULLA",
    "dialogFilterButtonConfirm": "FILTRO",
    "dialogFilterButtonCancel": "CLEAR",
    "dialogDeleteButtonConfirm": "DELETE",
    "dialogDeleteButtonCancel": "ANNULLA",
    "dialogEditColumn": "Colonna: {{value}}",
    "dialogAddColumn": "Aggiungi colonna",
    "dialogAddHeader": "Aggiungi riga",
    "dialogDeleteHeader": "Elimina riga",
    "dialogFilterHeader": "Filtra per",
    "dialogFilterMinLabel": "Min",
    "dialogFilterMaxLabel": "Massimo",
    "conditionalFormatting": "Formattazione condizionale",
    "groupBarLabel": "Trascina qui l'intestazione di una colonna per raggrupparla in base a quella colonna",
    "dialogDeleteContent": "Sei sicuro di voler eliminare questa riga?",
    "calendar": {
      "/": "/",
      ":": ":",
      "firstDay": 1,
      "days": {
        "names": [
          "Domenica",
          "Lunedì",
          "Martedì",
          "Mercoledì",
          "Giovedi",
          "Venerdì",
          "Sabato"
        ],
        "namesAbbr": [
          "Dom",
          "Lun",
          "Mar",
          "Mer",
          "Gio",
          "Ven",
          "Sab"
        ],
        "namesShort": [
          "Do",
          "Lu",
          "Ma",
          "Me",
          "Gi",
          "Ve",
          "Sa"
        ]
      },
      "months": {
        "names": [
          "Gennaio",
          "Febbraio",
          "Marzo",
          "Aprile",
          "Maggio",
          "Giugno",
          "Luglio",
          "Agosto",
          "Settembre",
          "Ottobre",
          "Novembre",
          "Dicembre",
          ""
        ],
        "namesAbbr": [
          "Gen",
          "Feb",
          "Mar",
          "Apr",
          "Mag",
          "Giu",
          "Lug",
          "Ago",
          "Set",
          "Ott",
          "Nov",
          "Dic",
          ""
        ]
      },
      "AM": [
        "AM",
        "am",
        "AM"
      ],
      "PM": [
        "PM",
        "pm",
        "PM"
      ],
      "eras": [{
        "name": "A.D.",
        "start": null,
        "offset": 0
      }],
      "currencySymbol": "€",
      "currency": "EUR",
      "currencySymbolPosition": "after",
      "decimalSeparator": ".",
      "thousandsSeparator": ","
    },
    "CONTAINS": "Contiene",
    "DOES_NOT_CONTAIN": "Non contiene",
    "ENDS_WITH": "Finisce con",
    "EQUAL": "Uguale",
    "GREATER_THAN": "Maggiore di",
    "GREATER_THAN_OR_EQUAL": "Maggiore o uguale di",
    "LESS_THAN": "Meno di",
    "LESS_THAN_OR_EQUAL": "Inferiore o uguale",
    "NOT_EQUAL": "Non uguale",
    "RANGE": "Gamma",
    "CLEAR_FILTER": "Cancella filtro",
    "STARTS_WITH": "Inizia con",
    "addFilter": "+ Aggiungi filtro",
    "and": "e",
    "apply": "Applica",
    "booleanFirst": "☐",
    "booleanLast": "☑",
    "cancel": "Annulla",
    "CONTAINS_CASE_SENSITIVE": "Contiene  (case sensitive)",
    "dateFirst": "1",
    "dateLast": "9",
    "DOES_NOT_CONTAIN_CASE_SENSITIVE": "non contiene (case sensitive)",
    "EMPTY": "vuoto",
    "ENDS_WITH_CASE_SENSITIVE": "termina con (case sensitive)",
    "EQUAL_CASE_SENSITIVE": "uguale (case sensitive)",
    "filter": "Filtro",
    "customize": "Personalizza colonne",
    "filteredByMultiple": "{{n}} filtri",
    "filteredByOne": "1 filtro",
    "filterValuePlaceholder": "Valore",
    "find": "Trova",
    "findInView": "Trova",
    "firstBy": "Ordina per",
    "found": "{{nth}} di {{n}}",
    "from": "da",
    "noFilters": "Nessun filtro applicato",
    "noResults": "Nessun risultato",
    "noSorting": "Nessun ordinamento applicato",
    "NOT_EMPTY": "non vuoto",
    "NOT_NULL": "non nullo",
    "NULL": "nullo",
    "numberFirst": "1",
    "numberLast": "9",
    "ok": "OK",
    "or": "o",
    "pickAnother": "Scegli un altra colonna per ordinare",
    "sort": "Ordina",
    "group": "Gruppo",
    "sortedByMultiple": "Ordinato per {{n}} campi",
    "sortedByOne": "Ordinato per 1 campo",
    "STARTS_WITH_CASE_SENSITIVE": "inizia con  (case sensitive)",
    "stringFirst": "A",
    "stringLast": "Z",
    "thenBy": "dopo di",
    "where": "Dove",
    "collapseAll": "Comprimi tutto",
    "expandAll": "Espandi tutto",
    "noGrouping": "Nessun raggruppamento",
    "groupedByMultiple": "{{n}} gruppi",
    "groupedByOne": "1 gruppo",
    "firstByGroup": "Raggruppa per",
    "pickAnotherGroupBy": "Scegli un altro campo per raggruppare",
    "add": "Aggiungi condizione",
    "all": "Tutte le colonne",
    "between": "Tra",
    "close": "Chiudi",
    "column": "Colonna:",
    "condition": "Condizione:",
    "equal": "Uguale a",
    "fontFamily": "Famiglia di caratteri:",
    "fontSize": "Dimensione carattere:",
    "format": "Formato:",
    "greaterThan": "Maggiore di",
    "highlight": "Evidenziare",
    "lessThan": "Minore di",
    "notEqual": "Non uguale a",
    "remove": "Rimuovi condizione",
    "secondValue": "Secondo valore:",
    "text": "Testo",
    "value": "Valore"
  }
}
Translated grid

Date & Currency Localization

The format of each grid column is set using the formatSettings property. The value can be localized using the Intl.NumberFormat or Intl.DateTimeFormat objects
Expand the translation functions so that the Account Balance and Birth Date column are localized, according to the language:

function englishTranslate() {
  let grid = document.querySelector('smart-grid');
  grid.locale = 'en';
  grid.beginUpdate();

  
  for (let i = 0; i < grid.columns.length; i++) {
    const column = grid.columns[i];

    setFormat(column, grid.locale);
  }

  grid.endUpdate(false);

}

function italianTranslate() {
  let grid = document.querySelector('smart-grid');
  grid.locale = 'it';
  grid.beginUpdate();

  
  for (let i = 0; i < grid.columns.length; i++) {
    const column = grid.columns[i];

    setFormat(column, grid.locale);
  }

  grid.endUpdate(false);

}

const setFormat = function (column, locale) {
  if (column.dataField === 'balance') {
      column.formatSettings = {
          Intl: {
              NumberFormat: {
                  style: 'currency',
                  currency: locale === 'it' ? 'EUR' : 'USD'
              }
          }
      }
  }

  if (column.dataField === 'birthDate') {
      column.formatSettings = {
          Intl: {
              DateTimeFormat: {
                locales: locale
              }
          }
      }
  }
}
Localized formatting

Translating Column Labels

Column labels can be translated by first creating an object, which contains the label text, translated in the different languages:

const columnLabels = {
  'en': {
      'firstName': 'First Name',
      'lastName': 'Last Name',
      'balance': 'Account Balance',
      'birthDate': 'Birth Date',
    },
    'it': {
      'firstName': 'Nome',
      'lastName': 'Cognome',
      'balance': 'Saldo del conto',
      'birthDate': 'Data di nascita',
    }
}

Then, use this object to translate the labels on each language change:

function englishTranslate() {
  let grid = document.querySelector('smart-grid');
  grid.locale = 'en';
  grid.beginUpdate();

  
  for (let i = 0; i < grid.columns.length; i++) {
    const column = grid.columns[i];

    column.label = columnLabels[grid.locale][column.dataField];
    setFormat(column, grid.locale);
  }

  grid.endUpdate(false);

}
function italianTranslate() {
  let grid = document.querySelector('smart-grid');
  grid.locale = 'it';
  grid.beginUpdate();

  
  for (let i = 0; i < grid.columns.length; i++) {
    const column = grid.columns[i];

    column.label = columnLabels[grid.locale][column.dataField];
    setFormat(column, grid.locale);
  }

  grid.endUpdate(false);

}
Translated columns