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.
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.