DevExtreme Angular - Localization
Localization adapts your application to linguistic and regional differences. DevExtreme widgets allow you to localize:
- Messages (using dictionaries)
- Numbers, dates, and currencies (using a localization library: Intl or Globalize).
Additional functionality includes value formatting and right-to-left layout support.
Dictionaries
Dictionaries are files that contain localized strings for different languages. These are JavaScript or JSON files depending on the packaging you use. DevExpress curates the following dictionaries:
- English (en) (default)
- German (de)
- Japanese (ja)
- Russian (ru)
The community contributed and is curating the following dictionaries:
- Czech (cs)
- Chinese (zh)
- Finnish (fi)
- French (fr)
- Italian (it)
- Brazilian Portuguese (pt)
- Spanish (es)
- Swedish (sv)
You can find all the dictionaries on your local machine in the DevExtreme installation folder's or ZIP archive's Lib\js\localization directory. These dictionaries are also available on CDN and npm. See the topics on localization libraries for code examples and details on using them.
To make a custom dictionary:
- Copy one of the available dictionaries.
- Rename it according to a new locale.
- Translate the strings in it.
- Link it to your page using a
<script>
tag.
You can submit custom dictionaries to our repository on GitHub. Please, refer to our Contribution Guide before submitting content.
Using Intl
Intl is the short name used to refer to a particular ECMAScript Internationalization API object. DevExtreme supports this API via the DevExtreme-Intl module. It is available on CDN and npm, or you can save the module (JavaScript file) on your local machine and use it.
CDN or local file
Include the DevExtreme-Intl module using the
<script>
tag as shown in the example below. German and Russian dictionaries are included in this example as well. You can replace or complement them with additional dictionaries.CDN
HTML<head> <!-- ... --> <!-- DevExtreme library --> <script src="https://cdn3.devexpress.com/jslib/17.2.18/js/dx.all.js"></script> <!-- DevExtreme-Intl module --> <script src="https://unpkg.com/devextreme-intl@17.2/dist/devextreme-intl.min.js"></script> <!-- Dictionary files for German and Russian languages --> <script src="https://cdn3.devexpress.com/jslib/17.2.18/js/localization/dx.messages.de.js"></script> <script src="https://cdn3.devexpress.com/jslib/17.2.18/js/localization/dx.messages.ru.js"></script> </head> <body> <script> DevExpress.localization.locale(navigator.language || navigator.browserLanguage); // ... // DevExtreme widgets are configured here // ... </script> </body>
npm
Install the
devextreme-intl
package:npm install --save-dev devextreme-intl
Then, include the
devextreme-intl
module and the dictionaries using theimport
orrequire
statement—the statement depends on the syntax for working with modules. The following code shows ECMAScript 6 and CommonJS syntaxes:npm: ECMAScript 6 syntax
JavaScript// ... import 'devextreme-intl'; // Dictionaries for German and Russian languages import deMessages from 'devextreme/localization/messages/de.json!json'; import ruMessages from 'devextreme/localization/messages/ru.json!json'; import { locale, loadMessages } from 'devextreme/localization'; loadMessages(deMessages); loadMessages(ruMessages); locale(navigator.language || navigator.browserLanguage)
npm: CommonJS syntax
JavaScript// ... require("devextreme-intl"); // Dictionaries for German and Russian languages const deMessages = require('devextreme/localization/messages/de.json'); const ruMessages = require('devextreme/localization/messages/ru.json'); const localization = require('devextreme/localization'); localization.loadMessages(deMessages); localization.loadMessages(ruMessages); localization.locale(navigator.language || navigator.browserLanguage);
The Intl setup automatically localizes and formats string, number, date, and currency values according to the specified locale. You can also use a currency other than USD globally or in format definitions:
jQuery
$(function() { // Specifying a currency globally DevExpress.config({ defaultCurrency: "EUR" }); $("#dataGridContainer").dxDataGrid({ // ... columns: [{ dataField: "Price", // Specifying a currency in a format definition format: { type: "currency", currency: "RUB" } }] }); });
Angular
import config from 'devextreme/core/config'; import { DxDataGridModule } from 'devextreme-angular'; // ... export class AppComponent { constructor() { // Specifying a currency globally config({ defaultCurrency: "EUR" }); } } @NgModule({ imports: [ // ... DxDataGridModule ], // ... })
<dx-data-grid ... > <dxi-column dataField="price"> <!-- Specifying a currency in a format definition --> <dxo-format type="currency" currency="RUB"> </dxo-format> </dxi-column> </dx-data-grid>
In addition, you can use structures compatible with the Intl API for value formatting. See an example in the DevExtreme-Intl README's API section. Note that DevExtreme provides extended formatting functionality out of the box, which is detailed here.
Sample projects are available on GitHub, including localization projects. Use them as a starting point for creating new apps or as examples to copy code from when implementing certain functionality in your app.
Using Globalize
Activating Globalize in your project requires the following files:
- Globalize library
- CLDR library
- CLDR JSON files for each required language.
You can find the Globalize and CLDR libraries on your local machine in the DevExtreme installation folder's or ZIP archive's Lib\js directory.
CLDR JSON files are available in the Unicode-CLDR repository. Refer to this table for details on which CLDR JSONs you may require.
All the components are also available via CDN and npm.
CDN or local files
Include the Globalize and CLDR libraries along with the dictionaries using
<script>
tags as shown below. The order is important. Then, load CLDR JSONs using$.getJSON
calls (you need to add the jQuery script) and set the locale using theGlobalize.locale()
method:CDN
HTML<head> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <!-- ... --> <script src="https://cdnjs.cloudflare.com/ajax/libs/cldrjs/0.5.0/cldr.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/cldrjs/0.5.0/cldr/event.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/cldrjs/0.5.0/cldr/supplemental.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/globalize/1.3.0/globalize.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/globalize/1.3.0/globalize/message.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/globalize/1.3.0/globalize/number.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/globalize/1.3.0/globalize/currency.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/globalize/1.3.0/globalize/date.min.js"></script> <!-- DevExtreme library --> <script src="https://cdn3.devexpress.com/jslib/17.2.18/js/dx.all.js"></script> <!-- Dictionary files for German and Russian languages --> <script src="https://cdn3.devexpress.com/jslib/17.2.18/js/localization/dx.messages.de.js"></script> <script src="https://cdn3.devexpress.com/jslib/17.2.18/js/localization/dx.messages.ru.js"></script> </head> <script> $(function() { $.when( // Gets language-specific CLDR JSONs for German and Russian $.getJSON("https://unpkg.com/cldr-dates-full/main/de/ca-gregorian.json"), $.getJSON("https://unpkg.com/cldr-numbers-full/main/de/numbers.json"), $.getJSON("https://unpkg.com/cldr-numbers-full/main/de/currencies.json"), $.getJSON("https://unpkg.com/cldr-dates-full/main/ru/ca-gregorian.json"), $.getJSON("https://unpkg.com/cldr-numbers-full/main/ru/numbers.json"), $.getJSON("https://unpkg.com/cldr-numbers-full/main/ru/currencies.json"), $.getJSON("https://unpkg.com/cldr-core/supplemental/likelySubtags.json"), $.getJSON("https://unpkg.com/cldr-core/supplemental/timeData.json"), $.getJSON("https://unpkg.com/cldr-core/supplemental/weekData.json"), $.getJSON("https://unpkg.com/cldr-core/supplemental/currencyData.json"), $.getJSON("https://unpkg.com/cldr-core/supplemental/numberingSystems.json") ).then(function () { // Normalizes $.getJSON results getting only the JSON without the request statuses return [].slice.apply( arguments, [0] ).map(function( result ) { return result[0]; }); }).then( Globalize.load ).then(function() { Globalize.locale(navigator.language || navigator.browserLanguage); }); }); </script>
npm
Install the
cldr-data
andglobalize
packages:npm install --save-dev cldr-data globalize
Then, include Globalize, CLDR, CLDR JSONs, and the dictionaries using the
import
orrequire
statement—the statement depends on the syntax for working with modules. The following code shows ECMAScript 6 syntax used with a SystemJS module loader, and CommonJS syntax used with a Webpack module bundler:npm: ECMAScript 6 syntax / SystemJS configuration
JavaScriptimport 'devextreme/localization/globalize/number'; import 'devextreme/localization/globalize/date'; import 'devextreme/localization/globalize/currency'; import 'devextreme/localization/globalize/message'; // Dictionaries for German and Russian languages import deMessages from 'devextreme/localization/messages/de.json!json'; import ruMessages from 'devextreme/localization/messages/ru.json!json'; // Language-specific CLDR JSONs for German and Russian import deCaGregorian from 'cldr-data/main/de/ca-gregorian.json!json'; import deNumbers from 'cldr-data/main/de/numbers.json!json'; import deCurrencies from 'cldr-data/main/de/currencies.json!json'; import ruCaGregorian from 'cldr-data/main/ru/ca-gregorian.json!json'; import ruNumbers from 'cldr-data/main/ru/numbers.json!json'; import ruCurrencies from 'cldr-data/main/ru/currencies.json!json'; import likelySubtags from 'cldr-data/supplemental/likelySubtags.json!json'; import timeData from 'cldr-data/supplemental/timeData.json!json'; import weekData from 'cldr-data/supplemental/weekData.json!json'; import currencyData from 'cldr-data/supplemental/currencyData.json!json'; import numberingSystems from 'cldr-data/supplemental/numberingSystems.json!json'; import Globalize from 'globalize'; Globalize.load( deCaGregorian, deNumbers, deCurrencies, ruCaGregorian, ruNumbers, ruCurrencies, likelySubtags, timeData, weekData, currencyData, numberingSystems ); Globalize.loadMessages(deMessages); Globalize.loadMessages(ruMessages); Globalize.locale(navigator.language || navigator.browserLanguage)
config.js
JavaScriptSystem.config({ // ... paths: { 'npm:': 'node_modules/' }, map: { // ... 'globalize': 'npm:globalize/dist/globalize', 'cldr': 'npm:cldrjs/dist/cldr', 'cldr-data': 'npm:cldr-data', 'json': 'npm:systemjs-plugin-json/json.js', }, packages: { app: { // ... 'globalize': { main: '../globalize.js', defaultExtension: 'js' }, 'cldr': { main: '../cldr.js', defaultExtension: 'js' } } } });
npm: CommonJS syntax / Webpack configuration
JavaScriptrequire('devextreme/localization/globalize/message'); require('devextreme/localization/globalize/number'); require('devextreme/localization/globalize/currency'); require('devextreme/localization/globalize/date'); // Dictionaries for German and Russian languages const deMessages = require('devextreme/localization/messages/de.json'); const ruMessages = require('devextreme/localization/messages/ru.json'); const Globalize = require('globalize'); Globalize.load( // Language-specific CLDR JSONs for German and Russian require('cldr-data/main/de/ca-gregorian.json'), require('cldr-data/main/de/numbers.json'), require('cldr-data/main/de/currencies.json'), require('cldr-data/main/ru/ca-gregorian.json'), require('cldr-data/main/ru/numbers.json'), require('cldr-data/main/ru/currencies.json'), require('cldr-data/supplemental/likelySubtags.json'), require('cldr-data/supplemental/timeData.json'), require('cldr-data/supplemental/weekData.json'), require('cldr-data/supplemental/currencyData.json'), require('cldr-data/supplemental/numberingSystems.json') ); Globalize.loadMessages(deMessages); Globalize.loadMessages(ruMessages); Globalize.locale(navigator.language || navigator.browserLanguage);
webpack.config.js
JavaScriptmodule.exports = { // ... resolve: { alias: { globalize$: path.resolve( __dirname, 'node_modules/globalize/dist/globalize.js' ), globalize: path.resolve(__dirname, 'node_modules/globalize/dist/globalize'), cldr$: path.resolve(__dirname, 'node_modules/cldrjs/dist/cldr.js'), cldr: path.resolve(__dirname, 'node_modules/cldrjs/dist/cldr') } } }
Strings, numbers, dates, and currencies are now automatically localized and formatted according to the specified locale. You can also use a currency other than USD (see the last example in the Using Intl topic).
In addition, you can now format values using structures accepted by numberFormatter, currencyFormatter, and dateFormatter, for example:
jQuery
$(function() { $("#dataGridContainer").dxDataGrid({ // ... columns: [{ dataField: "OrderDate", format: { skeleton: "yMMMd" } }, { dataField: "SaleAmount", format: { currency: "EUR", maximumFractionDigits: 2 } }] }); });
Angular
<dx-data-grid ... > <dxi-column dataField="OrderDate" [format]="{ skeleton: 'yMMMd' }"> </dxi-column> <dxi-column dataField="SaleAmount" [format]="{ currency: 'EUR', maximumFractionDigits: 2 }"> </dxi-column> </dx-data-grid>
import { DxDataGridModule } from 'devextreme-angular'; // ... export class AppComponent { // ... } @NgModule({ imports: [ // ... DxDataGridModule ], // ... })
See Also
Predefined Formats
Predefined formats are string literals for formatting numbers and dates. See the format.type description for a full list.
Set the widget option called format to apply a predefined format. In the following code, this option specifies the format and precision of the tooltip's value in the Slider widget. A precision value of 2 means that the value always contains two decimal digits.
jQuery
$(function() { $("#sliderContainer").dxSlider({ min: 0, max: 10, value: 6, step: 0.01, tooltip: { enabled: true, format: { type: "fixedPoint", precision: 2 } } }); });
Angular
<dx-slider [min]="0" [max]="10" [(value)]="sliderValue" [step]="0.01"> <dxo-tooltip [enabled]="true"> <dxo-format type="fixedPoint" [precision]="2"> </dxo-format> </dxo-tooltip> </dx-slider>
import { DxSliderModule } from 'devextreme-angular'; // ... export class AppComponent { sliderValue = 6; } @NgModule({ imports: [ // ... DxSliderModule ], // ... })
The format option in the previous example is specified with an object which allows specifying the precision. If you do not need precision, you can specify the format option with a string literal.
See Also
Custom Format String
A custom format string specifies a format using wildcard characters. It is useful when the predefined formats are not suitable.
The format description details supported characters. A format string can also contain regular characters which are displayed as is. Below the example from the Predefined Formats topic is changed so that the tooltip's value does not contain trailing decimal zeros:
jQuery
$(function() { $("#sliderContainer").dxSlider({ min: 0, max: 10, value: 6, step: 0.01, tooltip: { enabled: true, format: "#0.##" } }); });
Angular
<dx-slider [min]="0" [max]="10" [(value)]="sliderValue" [step]="0.01"> <dxo-tooltip [enabled]="true" format="0.##"> </dxo-tooltip> </dx-slider>
import { DxSliderModule } from 'devextreme-angular'; // ... export class AppComponent { sliderValue = 6; } @NgModule({ imports: [ // ... DxSliderModule ], // ... })
See Also
Custom Function
A custom function is useful when advanced formatting is required. The value to be formatted is passed to the function as the argument. In the following example, a custom function combines absolute and percentage values for the Slider widget's tooltip:
jQuery
$(function() { var sliderMaxValue = 10; $("#sliderContainer").dxSlider({ min: 0, max: sliderMaxValue, value: 6, step: 0.01, tooltip: { enabled: true, format: function (value) { return value + " | " + ((value / sliderMaxValue) * 100).toFixed(1) + "%"; } } }); });
Angular
<dx-slider [min]="0" [max]="sliderMaxValue" [(value)]="sliderValue" [step]="0.01"> <dxo-tooltip [enabled]="true" [format]="formatSliderTooltip"> </dxo-tooltip> </dx-slider>
import { DxSliderModule } from 'devextreme-angular'; // ... export class AppComponent { sliderValue = 6; sliderMaxValue = 10; formatSliderTooltip (value) { return value + " | " + ((value / this.sliderMaxValue) * 100).toFixed(1) + "%"; } } @NgModule({ imports: [ // ... DxSliderModule ], // ... })
Right-to-Left Support
Right-to-left (RTL) support allows the widget to adapt its content to right-to-left locales.
RTL layout can be specified for an individual widget using its rtlEnabled option:
jQuery
$(function() { $("#sliderContainer").dxSlider({ // ... rtlEnabled: true }); });
Angular
<dx-slider ... [rtlEnabled]="true"> </dx-slider>
import { DxSliderModule } from 'devextreme-angular'; // ... export class AppComponent { // ... } @NgModule({ imports: [ // ... DxSliderModule ], // ... })
To apply RTL to your entire application, set the same option globally using the config() function:
jQuery
$(function() { DevExpress.config({ rtlEnabled: true }); // ... });
Angular
import config from 'devextreme/core/config'; // ... export class AppComponent { constructor() { config({ rtlEnabled: true }); } } @NgModule({ imports: [ // ... DxDataGridModule ], // ... })
See Also
- RTL Support Demo: DataGrid | Navigation Widgets | Editors
If you have technical questions, please create a support ticket in the DevExpress Support Center.