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