-
Notifications
You must be signed in to change notification settings - Fork 152
Internationalization (The M Project 1.x)
Since variety is one of the goals of The M-Project, we both support a large number of different devices and provide a built-in mechanism to localize an application. With M.18N
, i18n is an abbreviation of internationalization, you are able to localize any String
within an application, to automatically detect the user's language, to define the application's default / fallback language and even to persistently set the user's language right inside your application.
Working with M.I18N
is pretty easy. All you need to do is to create a language file for every language you want your application to “speak”. These language files are written in JSON syntax and stored in an i18n
folder inside your application. The name of a language file is based on the language it stands for, the file extension is .js
. To match the language file with your Controller you have to tell your config.json
with language your app speaks. Too much information for one paragraph? Don't worry, we will go into details now.
Let's say you want to specify your application with an english language file. What do you need to do? First of all you need to create a folder inside your application folder called i18n
eg. mkdir app/resources/i18n
. Inside that folder you need to create a file called en_us.js
. The file's name is based on both the language (English) and the country (U.S.) since there might be differences between British English (“en_gb”) and American English (“en_us”). These language codes are based on ISO 639. The file extension .i18n
works as a reference for our internal language detector.
Once you've created your language file, you can start specifying the localized strings for this language. As mentioned before, a language file is written in JSON syntax. The following sample file, en_us.js
, will give you an impression of how such a file looks like:
M.I18N.en_us = {
"registry": "Registry",
"firstname": "Firstname",
"lastname": "Lastname",
"submit_btn": "Submit",
"firstname_req": "Firstname is required",
"lastname_req": "Lastname is required",
"date_format": "mm/dd/yyyy HH:MM"
}
As you can see, you basically extend M.I18N
by a property that is called according to the language you want to specify respectively according to the name of your language file, e.g. M.I18N.en_us
. Inside that property you simply specify key / value pairs, while the key is what you will later refer to in your view or controller. So let's take a look at how you do that.
Once you've specified some values inside your language file, you can use them inside your view. The key for this is the l()
method inside M.I18N
. Just call this method anywhere you want a localized string to be displayed and pass along the correct key, specified inside the language file. M.I18N
then will return the according value, based on the user's language. If the user's language doesn't match a language file, the default language is taken. But let's take a look at some code for giving you a better understanding of how to use M.I18N.l()
:
page: M.PageView.design({
childViews: 'header content',
header: M.ToolbarView.design({
value: M.I18N.l('registry'),
anchorLocation: M.TOP
}),
content: M.ScrollView.design({
childViews: 'label',
label: M.LabelView.design({
value: M.I18N.l('firstname')
})
})
})
Now you have to build a bridge between your language files eg. en_en.js
and your Controller or View. So you have to add "supportedLanguages"
to your config.json
file. "supportedLanguages"
represents an array that contains all supported languages eg.: "en_us"
.
...
"supportedLanguages": [
"en_us",
"en_gb",
"de_de"
]
...
Sure! You can use M.I18N
wherever a string is needed. For example, M.I18N
is a pretty convenient way to specify a date format for a dynamically loaded or user entered date. Let's say your application provides an input element for a date and the users enters or selects a specific date and then submits it to your controller. Before applying it to a view you'd probably like to format the date. If this is a specific formatting for just one view, you might use Dynamic Value Computing, but if it is a general formatting, you can easily do this inside the controller by using M.I18N
right there. This could look something like the following:
MyApp.MyController = M.Controller.extend({
date: null,
setDate: function() {
// retrieve the date string from a view or any storage
var dateString = M.ViewManager.getView('page', 'date').value;
// create a date object, using M.Date.create()
var dateObj = M.Date.create(dateString);
// format the date using M.Date.format and a language specific date format string
var dateFormat = M.Date.format(dateObj , M.I18N.l('date_format'));
// asign the formatted date string to the controller's date property so any observer gets notified
this.set('date', dateFormat);
}
});
The default behaviour of M.I18N
is to detect the user's language based on its browser. If there is a language file specified for this language, this one is applied to the application. Otherwise the application's default language is selected. If there is no default language specified, the system's fallback language is selected: American English (“en_us”). But if you want the user to be able to select the application's language right inside the application, M.I18N
provides you with mechanism for that, too. You can use the setLanguage()
method to programmatically set the application's language. Just pass along a string, referring to the desired language, e.g. “de_de” (German). The setLanguage()
method then will check if the desired language is available. If so, the language is stored in the browser's locale storage and then the application is reloaded automatically. The language detection process on the application's startup then will detect the language stored in the browser's locale storage and take this as the application's current language.
No, since this is a very specific problem, there is no built-in “languageSelector” view. But a pretty convenient way is to use M.SelectionList
in the M.SingleSelection
mode. The M.SelectionList
's onSelect
property can be used to specify a method inside your controller where you actually do the language switch by calling M.I18N
's setLanguage()
method. The following code sample will give you an impression of how this could look like:
langSelection: M.SelectionListView.design({
childViews: 'item1 item2 item3',
selectionMode: M.SINGLE_SELECTION,
name: 'language',
onSelect: {
target: MyApp.MyController,
action: 'changeLanguage'
},
item1: M.SelectionListItemView.design({
label: M.I18N.l('german'),
value: 'de_de'
}),
item2: M.SelectionListItemView.design({
label: M.I18N.l('english'),
value: 'en_us'
}),
item3: M.SelectionListItemView.design({
label: M.I18N.l('spanish'),
value: 'es_es'
})
})
Integrated in a real application, this language selection element could look somethin like this: