JSON Buddy Translatable

Allows you to store text data in multiple languages. Based on translateable, but with a few differences:

  1. Support for key methods
  2. No extra table dependency
  3. Single attribute

Translations

class Post < ActiveRecord::Base
  include BuddyTranslatable
  translatable :title, default_key: :de
end

post = Post.create(title: { de: 'Hallo', en: 'Hello' })

# getter using current locale
I18n.locale = :en
post.title #=> Hello
I18n.locale = :de
post.title #=> Hallo

# Getter using methods
post.title_en #=> Hello
post.title_de #=> Hallo
post.title_for(:de) #=> Hallo
post.title_data_for(:en) #=> Hello
post.title_data # => return all data (Hash)

# Update current locale and maintain others
I18n.locale = :en
post.update(title: 'Hello changed')
post.title_en # => Hello changed
post.title_de # => Hallo
post.title_es # => Hallo (return default key if not found)

# Replace all data
post.update(title: { en: 'En val', de: 'De val' })
post.title_en # => En val
post.title_es # => De val # default_key value is used when not defined

Requirements

  • PostgreSQL >= 9.4
  • ActiveRecord >= 4.2
  • I18n

Installation

Add this line to your application's Gemfile:

gem 'buddy_translatable'

Configure your available locales in your rails app, like: I18n.available_locales = %i[de en es]

And then execute: bundle install

Usage

class TestModel < ActiveRecord::Base
  include BuddyTranslatable

  translatable :title, default_key: :de
end

Migration

Attributes must be JSONB type.

class AddTitleToPosts < ActiveRecord::Migration
  def change
    add_column :posts, :title, :jsonb, null: false, default: {}
    add_column :posts, :key, :jsonb, null: false, default: {}
  end
end

Queries

For searching you can use the following concern:

module JsonbQuerable
  extend ActiveSupport::Concern

  included do
    scope :where_jsonb_value, lambda { |attr, value|
      attr_query = sanitize_sql("#{table_name}.#{attr}")
      where("EXISTS (SELECT 1 FROM jsonb_each_text(#{attr_query}) j
                              WHERE j.value = ?)", value)
    }

    scope :where_jsonb_value_like, lambda { |attr, value, case_sens = false|
      attr_query = sanitize_sql("#{table_name}.#{attr}")
      condition = case_sens ? 'j.value LIKE ?' : 'lower(j.value) LIKE lower(?)'
      where("EXISTS (SELECT 1
                     FROM jsonb_each_text(#{attr_query}) j
                     WHERE #{condition})", "%#{value}%")
    }
  end
end

class Post < ActiveRecord::Base
  #...
  include JsonbQuerable
  #...
end

Post.where_jsonb_value_like(:key, 'ebay')

Simple queries:

Post.where("title->>'en' = ?", 'hello')

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/owen2345/buddy_translatable.

License

The gem is available as open source under the terms of the MIT License.