1 # Localization in Ext JS
2 ______________________________________________
4 Creating an application that works is one thing; creating an application that works for your users is something very different. Communicating with users in a language that they understand and with conventions that they're used to is vital.
6 Imagine this scenario, you hand your phone to a friend in good faith but when they return it, everything's in Japanese. Frustrated, you try to remember which combination of buttons leads you to the Settings menu so you can change it back, navigating through, you realize that menus slide in the opposite direction, maybe even the color scheme is different. You start to realize just how important language and cultural conventions are and how disorienting it is when faced with a localization setting that wasn't meant for you. Now imagine your users, wanting to use your Ext JS application but feeling the same confusion and unsure of what's being asked of them.
8 To fix this, we go through a process known as 'localization' (sometimes called l10n). A large part of localization is translation and, thankfully, Ext JS makes it easy to localize your application.
10 ## Ext's Localization Files
12 In the root directory of your copy of Ext JS there is a folder called `locale`. This contains common examples (e.g. day names) in 45 languages ranging from Indonesian to Macedonian. You can inspect the contents of each to see exactly what they contain. Here's an excerpt from the Spanish localization file:
14 if (Ext.toolbar.Paging){
15 Ext.apply(Ext.PagingToolbar.prototype, {
16 beforePageText : "Página",
17 afterPageText : "de {0}",
18 firstText : "Primera página",
19 prevText : "Página anterior",
20 nextText : "Página siguiente",
21 lastText : "Última página",
22 refreshText : "Actualizar",
23 displayMsg : "Mostrando {0} - {1} de {2}",
24 emptyMsg : "Sin datos para mostrar"
28 Note: The `�` are character entity references which render as special characters, e.g. `á` shows á.
30 You can see that it checks to see if a {@link Ext.view.BoundList#pagingToolbar Paging toolbar} is in use, and if it is, applies the Spanish strings to each area text is shown. If you have custom text areas you, can append them here as well with the appropriate translations. You'll also notice that it is setting these properties to the Paging Toolbar's prototype. The upshot of this is that every new Paging Toolbar that is created will inherit these translated properties.
32 ## Utilizing Localization
34 There are two ways you could implement localization in your application: statically or dynamically. We're going to look at how to do it dynamically so users can choose which language they're most familiar with. First, we're going to create a Combobox where users will select their language and secondly, we'll deduce the language from the URL so if a user visits http://yoursite.com/?lang=es the Spanish version of your Ext application is used.
36 Set up a basic HTML page with links to Ext JS's necessary parts and our localized application's languages.js and app.js files.
41 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
42 <title>Localization example</title>
43 <!-- Ext Library Files -->
44 <link rel="stylesheet" type="text/css" href="ext/resources/css/ext-all.css">
45 <script src="ext/ext-all-debug.js"></script>
47 <script src="languages.js"></script>
48 <script src="app.js"></script>
51 <div id="languages"></div>
52 <div id="datefield"></div>
56 We have two separate JavaScript files: the first will be a list of all the languages that Ext JS comes with, the second will be the application itself. We've also set up two `div` tags, the first will contain the combobox for users to select their language and the second, `datefield`, will have a date picker.
58 Now create a file called `languages.js`. In this we'll store the languages in an array with two values, the language code and the name of the language like so:
60 Ext.namespace('Ext.local');
62 Ext.local.languages = [
70 ['en_GB', 'English (UK)'],
72 ['es', 'Spanish/Latin American'],
73 ['fa', 'Farsi (Persian)'],
75 ['fr_CA', 'French (Canadian)'],
76 ['fr', 'French (France)'],
77 ['gr', 'Greek (Old Version)'],
89 ['no_NB', 'Norwegian Bokmål'],
90 ['no_NN', 'Norwegian Nynorsk'],
92 ['pt_BR', 'Portuguese/Brazil'],
93 ['pt_PT', 'Portuguese/Portugal'],
98 ['sr_RS', 'Serbian Cyrillic'],
99 ['sr', 'Serbian Latin'],
100 ['sv_SE', 'Swedish'],
103 ['ukr', 'Ukrainian'],
104 ['vn', 'Vietnamese'],
105 ['zh_CN', 'Simplified Chinese'],
106 ['zh_TW', 'Traditional Chinese']
109 This is all the languages file will consist of but will serve as a useful reference for our Ext JS application.
111 Next, we'll start building the application itself. Using the module pattern, we will have four methods: `init`, `onSuccess`, `onFailure` and `setup`.
113 Ext.Loader.setConfig({enabled: true});
114 Ext.Loader.setPath('Ext.ux', 'ext/examples/ux/');
117 'Ext.tip.QuickTipManager',
119 'Ext.ux.data.PagingMemoryProxy',
123 Ext.onReady(function() {
125 MultiLangDemo = (function() {
130 onSuccess: function() {
133 onFailure: function() {
142 MultiLangDemo.init();
145 To create the {@link Ext.form.field.ComboBox combobox} that will contain all the possible language selections we first need to create an {@link Ext.data.ArrayStore array store} in the `init` function like so.
147 var store = Ext.create('Ext.data.ArrayStore', {
148 fields: ['code', 'language'],
149 data : Ext.local.languages //from languages.js
152 This is a very simple store that contains the two fields that correspond to the two values for each record in the `languages.js` file. As we gave it a namespace, we can refer to it as `Ext.local.languages`. You can type this in your browser's console to see what it consists of.
154 Now create the combobox itself, again, within the `init` function:
156 var combo = Ext.create('Ext.form.field.ComboBox', {
157 renderTo: 'languages',
159 displayField: 'language',
161 emptyText: 'Select a language...',
165 fn: function(cb, records) {
166 var record = records[0];
167 window.location.search = Ext.urlEncode({"lang":record.get("code")});
174 If you refresh your browser, you should see a combobox that, when clicked, shows a list of languages bundled with Ext JS. When one of these languages is selected, the page refreshes and appends `?lang=da` (if you chose Danish) to the URL. We'll use this information to display the desired language to the user.
178 After the creation of the combobox, we're going to check to see if any language has been previously selected and act accordingly by checking the URL with Ext's {@link Ext#urlDecode urlDecode} function.
180 var params = Ext.urlDecode(window.location.search.substring(1));
183 var url = Ext.util.Format.format('ext/locale/ext-lang-{0}.js', params.lang);
187 success: this.onSuccess,
188 failure: this.onFailure,
192 // check if there's really a language with passed code
193 var record = store.findRecord('code', params.lang, null, null, null, true);
194 // if language was found in store, assign it as current value in combobox
197 combo.setValue(record.data.language);
200 // no language found, default to english
204 Ext.tip.QuickTipManager.init();
206 Note: We're loading the files with an AJAX request, so the files will have to be uploaded to a server otherwise they'll fail to load due to browser security measures.
208 Here you can see why we have the `onSuccess` and `onFailure` methods. If a language file fails to load then the user must be notified instead of failing silently. First, we'll deal with failed files to make it obvious if debugging is needed; the idea is that if a user types in a nonexistent language code, or for some reason the language has been removed, an alert will be displayed so the user won't be surprised that the application is still in English.
210 onFailure: function() {
211 Ext.Msg.alert('Failure', 'Failed to load locale file.');
217 The `onSuccess` method is similar. We evaluate the locale file and then setup the demo knowing that the file has been loaded:
219 onSuccess: function(response) {
220 eval(response.responseText);
224 The AJAX call that we made returns a few parameters. We use JavaScript's `eval` function on `responseText`. `responseText` is the entirety of the locale file that we loaded and `eval` parses all of the JavaScript contained in the string that is `responseText`, that is, applying all of the translated text and thus localizing the application.
226 However, there's nothing in `setup()` to look at yet so we'll move onto this method next. We're going to start by creating a {@link Ext.menu.DatePicker date picker} that will change based on the chosen language.
229 Ext.create('Ext.FormPanel', {
230 renderTo: 'datefield',
232 title: 'Date picker',
234 defaultType: 'datefield',
242 Now, if you click on the calendar icon you'll see the month in the specified language as well as the first letter of each day.
244 {@img datepicker.png}
246 To show more of Ext JS's localization features we'll now create an e-mail field and a month browser. Inside the setup method, write the following:
248 Ext.create('Ext.FormPanel', {
249 renderTo: 'emailfield',
252 title: 'E-mail Field',
258 defaultType: 'textfield',
266 var monthArray = Ext.Array.map(Ext.Date.monthNames, function (e) { return [e]; });
267 var ds = Ext.create('Ext.data.Store', {
272 type: 'pagingmemory',
280 Ext.create('Ext.grid.Panel', {
284 title:'Month Browser',
286 text: 'Month of the year',
291 bbar: Ext.create('Ext.toolbar.Paging', {
297 // trigger the data store load
300 Remember that `renderTo` corresponds to an `id` on an HTML tag so add those to our index file, too.
302 Notice that when typing in fields, a warning icon is displayed that, when hovered over, reveals context-specific information in the native language as a tooltip.
306 An excellent example of what localization means beyond translation can be seen by selecting Polish and seeing how the order of the date field changes from DD-MM-YYYY to YYYY-MM-DD. Another is selecting Finnish and seeing how instead of dashes (-), periods (.) are used to separate day from month from year and the months are not capitalized. It's details like this that Ext takes care for you with it's comprehensive locale files.
310 In this tutorial we have looked at how to load different locale files included with Ext JS by using AJAX requests that reload the application in the desired language along with subtle cultural conventions.
312 Your users will benefit from a more native experience and appreciate the extra lengths that you've gone to to ensure a better experience.