/tolken

A down-to-earth database translation Gem for Rails using psql jsonb

Primary LanguageRubyMIT LicenseMIT

Tolken

Straightforward Rails database translations using psql jsonb

Tolken's API is more verbose than most similar gems. The idea is that you should be aware of when you're dealing with translatable fields and what language you're interested in in any given moment. In tolken a translatable field is just a Ruby hash which makes it easy to reason about. See Usage for details.

Gem Version Build Status Maintainability Test Coverage semver stability

Installation

Add this line to your application's Gemfile:

gem "tolken"

And then execute:

$ bundle

Or install it yourself as:

$ gem install tolken

Usage

Make sure you're running Postgres and that the column you want to translate is of the jsonb type:

Setup

class CreatePosts < ActiveRecord::Migration[5.2]
  def change
    create_table :posts do |t|
      t.jsonb :title, :jsonb, null: false
      t.timestamps
    end

    execute "CREATE INDEX posts_title_index ON posts USING gin (title)"
  end
end

Next you need to configure I18n if you haven't already (usually in config/initializers/locale.rb):

I18n.available_locales = %i[en sv de]

Tolken expects you to only use translations for the locales in I18n.available_locales.

Persistence

Extend your model with Tolken and tell it what column(s) you want to translate:

class Post < ApplicationRecord
  extend Tolken
  translates :title
end

You can now work with title as follows:

post = Post.create(title: { en: "News", sv: "Nyheter" })

post.title # => { en: "News", sv: "Nyheter" }
post.title(:en) # => "News"
post.title(:sv) # => "Nyheter"
post.title("sv") # => "Nyheter"
post.title[:en] # => "News"
post.title["en"] # => "News"
post.title(:dk) # ArgumentError, "Invalid locale dk"
post.title[:dk] # => nil
post.title(:de) # => nil

post.title = { en: "News", sv: "Nyheter" }
post.title[:en] = "News"

Validation

Tolken comes with support for the presence validator:

class Post < ApplicationRecord
  extend Tolken
  translates :title, presence: true
end

post = Post.create(title: { en: "News", sv: "" })
post.errors.messages # => { name_sv: ["can't be blank"] }

Tolken checks that all I18n.available_locales has present values.

View Forms

While creating form inputs for your locale versions are as simple as adding [<locale>] to the html name attribute Tolken provides opt-in support for integrating with SimpleForm. To opt-in update your Gemfile:

gem "tolken", require: "tolken/simple_form"

Now if you add a simple_form field for a translatable field SimpleForm will generate an input per language version:

<%= simple_form_for(@post) do |form| %>
  <%= form.input :title %>
  <%= form.submit %>
<% end %>

By default a text input field is generated. If you want another type you can override with:

<%= form.input :title, type: :text %>

Without simple form your inputs might look something like:

<input name="post[title][en]" id="post_title_en">
<input name="post[title][sv]" id="post_title_sv">

Don't forget whitelist the nested locale params in your controller:

params.require(:post).permit(title: I18n.available_locales)

This will instead render one text area per language version.

The specs for translates is a good resource of additional usage examples.

Development

Native dependencies

You need to have postgresql installed on your system. This can be done on Mac OS with brew install postgresql.

Ruby setup

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.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/varvet/tolken. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

If you use and like Tolken but find yourself adding features that you're missing in Tolken please consider submitting a pull request!

To create a pull request follow these steps:

$ git clone git@github.com:varvet/tolken.git
$ cd tolken
$ git checkout my-feature-branch
Make changes and commits, consider squashing commits that doesn't add anything by themselves
$ rubocop
$ rspec
$ open coverage/index.html
If test coverage is missing address it or add a description to your PR why it is lacking.
Commit, if possible squash in original locations, changes required by rubocop and or failing tests.
$ git checkout master
$ git pull --rebase
$ git checkout my-feature-branch
$ git rebase master
$ git push

Alternative solutions

  • Traco - use multiple columns in the same model (Barsoom)
  • Mobility - pluggable translation framework supporting many strategies, including translatable columns, translation tables and hstore/jsonb (Chris Salzberg)
  • hstore_translate - use PostgreSQL's hstore datatype to store translations, instead of separate translation tables (Cédric Fabianski)
  • json_translate - use PostgreSQL's json/jsonb datatype to store translations, instead of separate translation tables (Cédric Fabianski)
  • Trasto - store translations directly in the model in a Postgres Hstore column

License

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