Created by Chris Rice / Github: Kilowhisky
Globalization is the process of designing and developing applications that function for multiple cultures.
Localization is the process of customizing your application for a given culture and locale.
Source123.43 -> 123,43
10/01/2016 -> 2016/10/01
Mitigation is in the API and platform specific
ember install ember-i18n ember install ember-moment
// config/environment.js
module.exports = function (environment)
{
var ENV = {
i18n: {
defaultLocale: 'en-us'
},
moment: {
includeLocales: ['en', 'pt-br', 'es'],
}
};
return ENV;
};
ember generate locale en-us ember generate locale pt-br ember generate locale es-es
// app/instance-initializers/restore-locale.js
let locale = session.get('MyLocalePreference');
let locales = i18n.get('locales');
if (!locale) {
locale = navigator.language || // Everyone
navigator.userLanguage || // IE... because
Config.i18n.defaultLocale;
}
locale = locale.toLowerCase();
for (let i = 0; i < locales.length; i++) {
let appLocale = locales.objectAt(i);
if (appLocale.toLowerCase().indexOf(locale) === 0) {
i18n.set('locale', appLocale);
moment.locale(appLocale);
break;
}
}
If you are using ember-validations you need to hack i18n support
// app/instance-initializers/restore-locale.js
export function initialize(instance) {
Ember.I18n = instance.lookup('service:i18n');
}
The HTML lang tag is important in informing the browser that the app is localized
// app/instance-initializers/restore-locale.js
export function initialize(instance) {
let i18n = instance.lookup('service:i18n');
let router = instance.lookup('router:main');
Ember.addObserver(i18n, 'locale', function() {
Ember.run.schedule('afterRender', this, function() {
$('html').attr('lang', locale);
if(router.isActive('application')){
router.updateTitle();
}
});
});
Protip: If you are using ember-cli-document-title you need to hack i18n support
Inform all servers of our locale preference on each request
// app/instance-initializers/restore-locale.js
export function initialize(instance) {
let i18n = instance.lookup('service:i18n');
$.ajaxPrefilter((options, originalOptions, xhr) => {
xhr.setRequestHeader("Accept-Language", i18n.get('locale'));
});
}
i18n's default behavior for missing locales is to return nothing. Thats annoying to me.
// app/utils/i18n/missing-message.js
var defaultLocale;
export default function(locale, key, data) {
if(locale === 'en-us'){
return `Missing Translation for ${key}`;
}
if(!defaultLocale){
defaultLocale = new Locale('en-us', getOwner(this));
}
const count = Ember.get(data, 'count');
const defaults = Ember.makeArray(Ember.get(data, 'default'));
defaults.unshift(key);
const template = defaultLocale.getCompiledTemplate(defaults, count);
return template(data);
}
(the incredibly unbearably tedious type of fun)
// app/locales/en-us.js
export default {
"locales": {
"es-es": "Spanish",
"en-us": "English",
"pt-br": "Brazilian Portuguese"
},
Locale files are just JSON files.
Keys can be as nested as you want.
This
<strong>Report Application Issue</strong>
Becomes
<strong>{{t 'reportIssues.title'}}</strong>
// app/locales/en-us.js
"reportIssues": {
"title" : "Report Application Issue"
}
This
<p>You have submitted 6 support cases</p>
Becomes
<p>{{t 'reportIssues.numberCases' count=userReportedCaseCount}}</p>
// app/locales/en-us.js
"reportIssues": {
"numberCases" : "You have submitted {{count}} support cases"
}
You can pass safeStrings, numbers, computedProperties, etc..
<p>You should <strong>really</strong> think</p>
<p>{{{t 'reportIssues.think'}}}</p>
// app/locales/en-us.js
"reportIssues": {
"think" : "You should <strong>really</strong> think"
}
Note the tripple {{{. This disables HTML escaping.
// someComponent.js
i18n: Ember.inject.service(),
actions: {
error() {
this.notifications.error(this.get('i18n').t('loadingError'));
}
}
// someComponent.js
import { translationMacro as t } from "ember-i18n";
export default Ember.Component.extend({
title: t('myTitle')
})
// someComponent.hbs
{{title}}
// someComponent.js
i18n: Ember.inject.service(),
landingImgUrl: Ember.computed('i18n.locale', () => {
this.get('i18n.locale').t('landingImgUrl');
})
What do you do with that hundred of keys in en-us.js
Export your translations to CSV if you want
ember-i18n-csv to-csv --locales-path=/app/locales/ --csv-path=i18n.csv --only-missing
Once done you can import them back.
ember-i18n-csv to-js --csv-path=i18n.csv --locales-path=/app/ocales --merge