About one year ago I wrote about i18n and the rails asset pipeline with jQuery.

Last week I took the time to update my jquery-localization-engine to support i18next instead of jquery-localize.
I also added support for an external service, Copycopter. Copycopter enables you to update your localizations without being forced to redeploy your application. The new package is called rails-asset-localization.

So far it’s working really great. To summarize - the upsides

  • all my locales are compiled on deployment. Users accessing my application for the first time wont have any additional network requests for localizations. They might be served outdated locales, but only for a short amount of time.
  • returning users will be served new locales every five hours, leaving them with a more up to date version of the locales. This is handled by i18next without any work on my side.
  • I can update all locales using Copycopter without having to worry to redeploy the application.

The downsides:

  • i18next supports default values, but those default values are not sent back to Copycopter at the moment. This means I’m forced to memorize which keys to add with which default values. Note that i18next has support for posting new translations to a backend but I’ve not added support for this just yet.
  • there’s no way to force the client to redownload locales at the moment. This could be added easily by removing the localStorage elements i18next creates, though.

Here’s a short integration example which I’m running in production:

I’ve set up my to use rails-asset-localization and my application.coffee to load i18next + a simple UI initialization code:

# Gemfile
gem 'rails-asset-localization', git: [email protected]:nicolai86/rails-asset-localization.git', branch: :master
# application.coffee
#= require jquery
#= require jquery_ujs
#= require i18next
#= require i18n/translations

window.UI = {
  currentLocale: null

  load: (locale) ->
    @currentLocale = locale

    for bundledLocale of bundledLocales
      storedLocale = window.localStorage.getItem("res_#{bundledLocale}")
      unless storedLocale?
        object = {}
        object[bundledLocale] = bundledLocales[bundledLocale]
        i18n.sync._storeLocal object

    options = {
      interpolationPrefix: '%{'
      interpolationSuffix: '}'
      lng: locale
      resGetPath: "/locales/%{lng}.json"
      useLocalStorage: true
      localStorageExpirationTime: 60 * 60 * 5 * 1000
    }
    i18n.init options
}

inside my application.haml I’m calling out to UI.load

!!!
%html
  %head
  %body
    :coffeescript
      UI.load("#{I18n.locale}");

my client side templates are using @leshills handlebars_assets

# welcome.hamlbars
%h1
  {{t "app.welcome"}}

I’ve added a Handlebars helper method which enables me to use i18n.t inside my views:

Handlebars.registerHelper 't', ->
  args = [].slice.call(arguments)
  result = i18n.t.apply(i18n,args)
  return new Handlebars.SafeString(result)

A future version of railsassetlocalization will have support for the posting of new translations - but for now this works just great.

That’s it! Happy hacking - and happy easter!


comments powered by Disqus