Skip to content

Instantly share code, notes, and snippets.

@arkadiyk
Last active November 17, 2021 05:45
Show Gist options
  • Save arkadiyk/8327867 to your computer and use it in GitHub Desktop.
Save arkadiyk/8327867 to your computer and use it in GitHub Desktop.
Quick'n'dirty i18n for Ember application. Allows to switch locales dynamically. Uses `i18n-js` library. Adds handlebars `t` helper and also attribute bindings `placeholderTranslation` to text input views and `promptTranslation` to select view.
Ember.Handlebars.registerBoundHelper 't', (key, options) ->
currentContext = (options.contexts && options.contexts[0]) || this
view = options.data.view
# TODO do we need unregester the observer somehow?
view.get('_childViews').forEach (v) ->
view.registerObserver(currentContext, 'i18n.locale', v, v.rerender) if v.rerender
I18n.t(key, options.hash)
App.I18nHelper = Ember.Object.extend
locale: I18n.defaultLocaTle || 'en'
t: (key, options) -> I18n.t(key, options)
setLocale: (->
Ember.run => I18n.locale = @get('locale')
).observes('locale')
# used in current locale selector
availableLocales: (->
locale for locale of I18n.translations when not I18n.t("locales.#{locale}").match(/^\[missing /)
).property()
availableLocaleNames: (->
for locale in @get('availableLocales')
id: locale
name: I18n.t("locales.#{locale}")
).property()
Ember.Application.initializer
name: "i18nHelper"
before: "applicationState"
initialize: (container, app) ->
app.register('i18nHelper:global', App.I18nHelper, {singleton: true })
app.inject('route', "i18n", "i18nHelper:global")
app.inject('controller', "i18n", "i18nHelper:global")
app.inject('view', "i18n", "i18nHelper:global")
Ember.Application.initializer
name: "defaultLocale"
after: "i18nHelper"
initialize: (container) ->
container.lookup("i18nHelper:global").set('locale', I18n.currentLocale())
# add `placeholderTranslation` attribute binding to Input helpers
Ember.TextSupport.reopen
_placeholder: null
placeholderTranslation: null
placeholder: ( (key, value) ->
@set('_placeholder', value) if arguments.length > 1
if @get('placeholderTranslation')
@get('targetObject.i18n').t(@get('placeholderTranslation'))
else
@get('_placeholder')
).property('placeholderTranslation', 'targetObject.i18n.locale')
# add `promptTranslation` attribute binding to Select helper
Ember.Select.reopen
contentDidChange: (-> @_change() ).observes('content') # to sync up selected item after 'content' refreshes
_prompt: null
promptTranslation: null
prompt: ( (key, value) ->
@set('_prompt', value) if arguments.length > 1
if @get('promptTranslation')
@get('parentView.i18n').t(@get('promptTranslation'))
else
@get('_prompt')
).property('promptTranslation', 'parentView.i18n.locale')

Examples:

Literals:

{{t 'user.last_name'}}
{{t 'user.email' count=1}}

Placeholders:

{{input value=address.street placeholderTranslation="address.street"}}

Prompt:

{{view Ember.Select 
  content=tags 
  optionValuePath="content.id" 
  optionLabelPath="content.name" 
  value=selectedTag 
  promptTranslation="publication.tag"}}

Select to switch current locale:

{{view Ember.Select 
  content=i18n.availableLocaleNames 
  optionValuePath="content.id" 
  optionLabelPath="content.name" 
  value=i18n.locale}}
@ryyppy
Copy link

ryyppy commented Jun 25, 2015

I really like your approach and I try to use it, but for some reason v.rerender() does not actually render the new value... what Ember version did you use for this example? 1.9.1?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment